diff --git a/.gitignore b/.gitignore index 866176fb..02ea0293 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,15 @@ node_modules/ *.sublime-project *.sublime-workspace config.local.json +docs/**/ #----------------------------- # INVALID FILES # (for cross OS compatibility) #----------------------------- *[\<\>\:\"\/\\\|\?\*]* +main.css +*.codekit +*.sass-cache +tests/.grunt +_SpecRunner.html diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..3e508875 --- /dev/null +++ b/.npmignore @@ -0,0 +1,12 @@ +_assets +build +bower.json +docs +examples +extras +icon.png +lib/**-NEXT**.js +spikes +src +tests +VERSIONS.txt \ No newline at end of file diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..5816f788 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,27 @@ +### TODO +- [ ] Is this a question or bug? [Stack Overflow](https://stackoverflow.com/questions/tagged/createjs) is a much better place to ask any questions you may have. + +- [ ] Did you search the [issues](https://github.com/CreateJS/PreloadJS/issues) to see if someone else has already reported your issue? If yes, please add more details if you have any! + +- [ ] If you're using an older [version](https://github.com/CreateJS/PreloadJS/blob/master/VERSIONS.txt), have you tried the latest? + +- [ ] If you're requesting a new feature; provide as many details as you can. Why do you want this feature? Do you have ideas for how this feature should be implemented? Pseudocode is always welcome! + + +### Issue Details +* Version used (Ex; 1.0): + + +* Describe whats happening (Include any relevant console errors, a [Gist](https://gist.github.com/) is preferred for longer errors): + + + +* OS & Browser version *(Please be specific)* (Ex; Windows 10 Home, Chrome 62.0.3202.94): + + + +* Do you know of any workarounds? + + + +* Provide any extra details that will help us fix your issue. Including a link to a [CodePen.io](https://codepen.io) or [JSFiddle.net](https://jsfiddle.net) example that shows the issue in isolation will greatly increase the chance of getting a quick response. diff --git a/LICENSE b/LICENSE.txt similarity index 100% rename from LICENSE rename to LICENSE.txt diff --git a/README.md b/README.md index 37a4a985..be1f3e57 100644 --- a/README.md +++ b/README.md @@ -2,22 +2,27 @@ PreloadJS is a library to make working with asset preloading easier. It provides a consistent API for loading different file types, automatic detection of XHR (XMLHttpRequest) availability with a fallback to tag-base loading, composite -progress events, and a plugin model to assist with preloading in other libraries such as [SoundJS](http://www.soundjs.com). +progress events, and a plugin model to assist with preloading in other libraries such as [SoundJS](http://www.createjs.com/soundjs/). ## Example - var preload = new createjs.LoadQueue(); - preload.addEventListener("fileload", handleFileComplete); - preload.loadFile('http://createjs.com/images/404/gBot-confused.jpg'); - function handleFileComplete(event) { - document.body.appendChild(event.result); - } +```javascript +var queue = new createjs.LoadQueue(false); +queue.on("fileload", handleFileComplete); +queue.loadFile('http://createjs.com/assets/images/png/createjs-badge-dark.png'); +function handleFileComplete(event) { + document.body.appendChild(event.result); +} +``` ## Support and Resources * Find examples and more information at the [PreloadJS web site](http://www.preloadjs.com/) -* Read the [documentation](http://createjs.com/Docs/PreloadJS/) -* You can also ask questions and interact with other users at our [Community](http://community.createjs.com) site. -* Have a look at the included [examples](https://github.com/CreateJS/PreloadJS/tree/master/examples) and [API documentation](http://createjs.com/Docs/PreloadJS/) for more in-depth information. +* Read the [documentation](http://createjs.com/docs/preloadjs/) +* Discuss, share projects, and interact with other users on [reddit](http://www.reddit.com/r/createjs/). +* Ask technical questions on [Stack Overflow](http://stackoverflow.com/questions/tagged/preloadjs). +* File verified bugs or formal feature requests using Issues on [GitHub](https://github.com/createjs/PreloadJS/issues). +* Have a look at the included [examples](https://github.com/CreateJS/PreloadJS/tree/master/examples) and +[API documentation](http://createjs.com/docs/preloadjs/) for more in-depth information. Built by [gskinner.com](http://www.gskinner.com), and is released for free under the MIT license, which means you can use it for almost any purpose (including commercial projects). We appreciate credit where possible, but it is not a requirement. @@ -27,4 +32,4 @@ use it for almost any purpose (including commercial projects). We appreciate cre **LoadQueue** The main class that manages all preloading. Instantiate a LoadQueue instance, load a file or manifest, and track -progress and complete events. Check out the [docs](http://createjs.com/Docs/PreloadJS/) for more information. \ No newline at end of file +progress and complete events. Check out the [docs](http://createjs.com/docs/preloadjs/) for more information. \ No newline at end of file diff --git a/README_CREATEJS_NAMESPACE.txt b/README_CREATEJS_NAMESPACE.txt index f0e11663..26232d22 100644 --- a/README_CREATEJS_NAMESPACE.txt +++ b/README_CREATEJS_NAMESPACE.txt @@ -4,7 +4,7 @@ For example, instead of instantiating a preloader like this: var foo = new PreloadJS(); You will need to reach into the createjs namespace: -var bar = new createjs.PreloadJS(); +var bar = new createjs.LoadQueue(); This functionality is configurable though. You can easily shortcut the namespace or get rid of it completely. @@ -21,4 +21,4 @@ var createjs = window; // sets window as the createjs namespace (the object the -This will also make CreateJS libraries compatible with old content that did not use a namespace, such as the output from the Flash Pro Toolkit for CreateJS v1.0. \ No newline at end of file +This will also make CreateJS libraries compatible with old content that did not use a namespace, such as the output from the Flash Pro Toolkit for CreateJS v1.0. diff --git a/VERSIONS.txt b/VERSIONS.txt index 8861f9ea..12c6d3d6 100644 --- a/VERSIONS.txt +++ b/VERSIONS.txt @@ -1,18 +1,112 @@ -Version NEXT [Not Released] +Version 1.0.0 (September 14, 2017) +**************************************************************************************************** +CRITICAL +- removed old deprecated properties and methods +- Deprecated get/set methods are now protect with an underscore (eg _setEnabled) +- Removed deprecated TYPE duplicates, notably the loader types (LoadQueue.SOUND, AbstractLoader.SOUND) + in place of the Types.SOUND, and request methods (LoadQueue.POST, AbstractLoader.POST) in place + of Methods.POST. + The deprecated methods and properties will still work, but will display a console warning when used. +- Changed version naming to use preloadjs.js, instead of containing the version number + +***** +- Fixed XHRRequest to append values in both GET and POST scenarios +- Updated documentation +- Fixed issue with SpriteSheetLoader.destroy (thanks @Kiv) +- Changed XHR error conditions to only include 400-599. +- Changed XHR error conditions to only treat status=0 as an error when on http/https +- Fixed issue with parameter value in ImageLoader._isLocal check (moved to URLUtils._isLocal) +- Changed tag preloading to use a dedicated container instead of adding all items to the body during + loading, which will avoid affecting the size of the body. +- General refactoring to utility methods +- Fixed issue with error handler when loading images +- Removed type from DataUtils.parseXML, just default to "text/xml" +- Added FontLoader for preloading CSS-fonts and relative font files +- Fixed error callback on resultFormatter in ImageLoader (thanks @xpol) +- added a shared createjs.deprecate() method, which wraps old methods and property getter/setters to display + a console warning when used. + + +Version 0.6.2 [November 26, 2015] +**************************************************************************************************** +- Fixed SpriteSheetLoader's JSONP loading (thanks @JonLucas) +- Added SpriteSheetLoader support for crossOrigin, basePath, and preferXHR for sub-images +- Removed legacy code in JSON loaders +- Changed LoadQueue Array checks from instanceof to Array.isArray() +- Fixed using XHR to load sounds and video (fixes #160) +- Fixed issue with XHR-loaded images, where bad content stalls a load (and a queue). + Updated the example that shows this in action. +- Fixed issue where XHR-loaded images might not clean up their respective ObjectURL +- Changed resultFormatter to call methods in scope, and handle both success and fail callbacks +- Removed anonymous functions from resultFormatter +- Removed BrowserDetect from utils (no longer used) +- Updated error event propagation from AbstractLoader to generate new ErrorEvents instead of + redispatching the existing event +- Fixed script loading when maintainScriptOrder is false (thanks @emlyn) +- Fixed issues with GET requests that have values introduced during refactor +- Added SpriteSheetLoader tests +- Updated tests to do better type checking +- Bower updates: removed bower.json from the exclusions +- Changed callbacks to use createjs.proxy instead of _this +- Documentation updates + + +Version 0.6.1 [May 21, 2015] +**************************************************************************************************** +- Added error handler to TagRequest (GitHub issue #124) +- Added support for loading files with src set to an object that is then decoded by a plugin +- Fixed parsing of certain SVG files in IE 9/10 +- Fixed propagating loaded sub-manifest items +- Fixed XHR support for IE 9 +- Support for IE8 has been dropped +- Fixed loading binary files when BLob constructor is not supported (thanks to @thammin) +- Fixed propagating plugins to sub loaders +- Fixed SVG loading on iOS +- XHR text loads now default to UTF-8 +- Added DOMUtils for adding/removing HEAD and BODY content +- Separated the cleanup() in LoadQueue to be called separately + + +Version 0.6.0 [December 12, 2014] +************************************************************************************************************************ +** Please note PreloadJS 0.6.0 is only compatible with SoundJS 0.6.0 and later. Earlier versions are incompatible. *** ************************************************************************************************************************ CRITICAL (may break existing content) +- Completely changed how loaders are structured. Tag & XHR loaders have been turned into utilities, and top-level + content-based loaders are used instead, such as ImageLoader, CSSLoader, etc. The API hasn't changed, but this could + introduce issues. +- Added low-level classes and utilities, mostly broken out of the existing classes, which makes the re-architecture + easier. This includes the net/Request classes, and utils/. - Completely revisited how file paths are parsed. The new version is much less aggressive, and should be more reliable and simple to edit. +- re-architected the class and inheritance model + - initialize methods removed, use MySuperClass_constructor instead + - helper methods: extend & promote (see the "Utility Methods" docs) + - property definitions are now instance level, and in the constructor (performance gains) + - the .constructor is now set correctly on all classes (thanks kaesve) **** +OTHER: - Fixed issue with erroneous fileload events when manually changing the src property of an image loaded with PreloadJS. - Refactored XMLHTTP fallback for old IE -- Added "headers" property on load items, which is injected into XHR request headers +- Added a LoadItem class, a class that can be used in place of the raw objects for load items. Used in the background + when string paths are used. +- Added "headers" and "withCredentials" property on load items, which is injected into XHR request headers. - Added support for an optional "maintainOrder" property on load items, which makes PreloadJS ensure they get loaded in order. Items other than tag-loaded scripts will be loaded at any time (depending on the setMaxConnections() value, however they will always finish in the order specified. - Added bower support, including grunt task for updating the bower.json - Fixed issues with tag-loaded files preloaded before the body tag is available +- Added .gitignore to subfolders under /docs (thanks mcfarljw) +- Improved EventDispatcher's handling of redispatched event objects +- Added ProgressEvent to simplify progress events, and for usage in the new system +- Added ErrorEvent to createjs package, and changed usages throughout PreloadJS +- Changed ManifestLoader to automatically load sub-content before dispatching complete. Uses an internal LoadQueue. +- Added SpriteSheetLoader to preload json files, their contents, and create a SpriteSheet before "complete". +- Added resultFormatter to LoadItems to handle XML, JSON, etc parsing, which can be user-overridden. +- Updated json polyfill to use json3 +- Build process updates to remove unnecessary copyright headers from the combined file. +- Added unit tests. Run them from the tests/ folder. Version 0.4.1 [December 12, 2013] diff --git a/_assets/README.md b/_assets/README.md new file mode 100644 index 00000000..bea1b394 --- /dev/null +++ b/_assets/README.md @@ -0,0 +1,3 @@ +# _shared folder + +Contains assets that are shared by examples, tutorials, and tests to prevent duplication, and simplify referencing. \ No newline at end of file diff --git a/examples/assets/Autumn.png b/_assets/art/Autumn.png similarity index 100% rename from examples/assets/Autumn.png rename to _assets/art/Autumn.png diff --git a/examples/assets/BlueBird.png b/_assets/art/BlueBird.png similarity index 100% rename from examples/assets/BlueBird.png rename to _assets/art/BlueBird.png diff --git a/examples/assets/Nepal.jpg b/_assets/art/Nepal.jpg similarity index 100% rename from examples/assets/Nepal.jpg rename to _assets/art/Nepal.jpg diff --git a/examples/assets/Texas.jpg b/_assets/art/Texas.jpg similarity index 100% rename from examples/assets/Texas.jpg rename to _assets/art/Texas.jpg diff --git a/examples/assets/gbot.svg b/_assets/art/gbot.svg similarity index 98% rename from examples/assets/gbot.svg rename to _assets/art/gbot.svg index 755ee270..71fa9aa5 100644 --- a/examples/assets/gbot.svg +++ b/_assets/art/gbot.svg @@ -1,1134 +1,1134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/assets/genericButton.png b/_assets/art/genericButton.png similarity index 100% rename from examples/assets/genericButton.png rename to _assets/art/genericButton.png diff --git a/examples/assets/genericButtonOver.png b/_assets/art/genericButtonOver.png similarity index 100% rename from examples/assets/genericButtonOver.png rename to _assets/art/genericButtonOver.png diff --git a/examples/assets/ground.png b/_assets/art/ground.png similarity index 100% rename from examples/assets/ground.png rename to _assets/art/ground.png diff --git a/examples/assets/parallaxHill1.png b/_assets/art/hill1.png similarity index 100% rename from examples/assets/parallaxHill1.png rename to _assets/art/hill1.png diff --git a/examples/assets/parallaxHill2.png b/_assets/art/hill2.png similarity index 100% rename from examples/assets/parallaxHill2.png rename to _assets/art/hill2.png diff --git a/examples/assets/image0.jpg b/_assets/art/image0.jpg similarity index 100% rename from examples/assets/image0.jpg rename to _assets/art/image0.jpg diff --git a/examples/assets/image1.jpg b/_assets/art/image1.jpg similarity index 100% rename from examples/assets/image1.jpg rename to _assets/art/image1.jpg diff --git a/examples/assets/image2.jpg b/_assets/art/image2.jpg similarity index 100% rename from examples/assets/image2.jpg rename to _assets/art/image2.jpg diff --git a/examples/assets/image3.jpg b/_assets/art/image3.jpg similarity index 100% rename from examples/assets/image3.jpg rename to _assets/art/image3.jpg diff --git a/examples/assets/loader.gif b/_assets/art/loader.gif similarity index 100% rename from examples/assets/loader.gif rename to _assets/art/loader.gif diff --git a/_assets/art/loading.gif b/_assets/art/loading.gif new file mode 100644 index 00000000..c02e626a Binary files /dev/null and b/_assets/art/loading.gif differ diff --git a/_assets/art/logo_createjs.svg b/_assets/art/logo_createjs.svg new file mode 100644 index 00000000..6c734001 --- /dev/null +++ b/_assets/art/logo_createjs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/assets/runningGrant.png b/_assets/art/runningGrant.png similarity index 100% rename from examples/assets/runningGrant.png rename to _assets/art/runningGrant.png diff --git a/examples/assets/sky.png b/_assets/art/sky.png similarity index 100% rename from examples/assets/sky.png rename to _assets/art/sky.png diff --git a/_assets/art/spritesheet_font.png b/_assets/art/spritesheet_font.png new file mode 100644 index 00000000..e0c93403 Binary files /dev/null and b/_assets/art/spritesheet_font.png differ diff --git a/examples/assets/Thunder.mp3 b/_assets/audio/Thunder.mp3 similarity index 100% rename from examples/assets/Thunder.mp3 rename to _assets/audio/Thunder.mp3 diff --git a/examples/assets/Thunder.ogg b/_assets/audio/Thunder.ogg similarity index 100% rename from examples/assets/Thunder.ogg rename to _assets/audio/Thunder.ogg diff --git a/_assets/css/examples.css b/_assets/css/examples.css new file mode 100644 index 00000000..09edf070 --- /dev/null +++ b/_assets/css/examples.css @@ -0,0 +1,65 @@ +body { + width: 960px; +} + +header { + margin-bottom: 1rem; + width: 960px; +} + +h1 { + font-weight: 200; + margin-bottom: 1rem; +} + +h1:before { + content:"PRELOADJS "; + font-weight: bold; +} + +header p { + margin: 0; + padding: 1em; + background: rgba(250, 252, 255, 0.7); +} + +.content, canvas { + background: white; +} + +.content { + width: 960px; + height: 400px; + overflow: hidden; + padding: 1em; + box-sizing: border-box; +} + +.loading { + position: relative; +} + +.loading:after { + content: url("../art/loading.gif"); + position: absolute; + left: 50%; + top: 50%; + margin: -13px 0 0 -51px; + opacity: 0.8; +} + +#error, #mobile { + width: 960px; + height: 400px; + display:none; + text-align: left; + padding: 1em; +} + +body.embedded header { + display: none; +} + +body.embedded { + margin: 0; +} diff --git a/_assets/css/preloadjs.css b/_assets/css/preloadjs.css new file mode 100644 index 00000000..8613857c --- /dev/null +++ b/_assets/css/preloadjs.css @@ -0,0 +1,3 @@ +h1:before { + content:"PRELOADJS "; +} diff --git a/_assets/css/shared.css b/_assets/css/shared.css new file mode 100644 index 00000000..c68f0871 --- /dev/null +++ b/_assets/css/shared.css @@ -0,0 +1,68 @@ +body { + margin: 3em auto; + padding: 0; + background-color: #eaebee; + font-family: Arial, Verdana, sans-serif; + font-size: 14px; + font-weight: normal; + color: #333; + line-height: 1.4em; +} + +a:link, a:visited { + color: #39f; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +h1, h2 { + color: #FFF; + font-size: 1.6em; + margin-bottom: 0; + padding: 1.5em; + padding-bottom: 1.2em; + background: #374252; + text-transform: uppercase; +} + +h1::after { + display: block; + content: ""; + background: url('../art/logo_createjs.svg') no-repeat; + height:1.5em; + width: 6em; + margin-top: -0.3em; + float: right; +} + +h1 em { + font-weight: 200; + font-style: normal; +} + +h2 { + font-size: 1.3em; + padding: 1em; + padding-bottom: 0.8em; +} + +h3 { + background: #e0e1e5; + color: #374252; + font-size: 1.25em; + padding: 0.5em; + margin-top: 1.25em; + margin-bottom: -0.5em; + position: relative; +} + +code { + color: black; + background-color: rgba(255, 230, 0, 0.33); + padding: 1px 3px; + font-family: Courier New, Courier, serif; + font-weight: bold; +} \ No newline at end of file diff --git a/_assets/fonts/regul-bold.woff b/_assets/fonts/regul-bold.woff new file mode 100644 index 00000000..f526d85e Binary files /dev/null and b/_assets/fonts/regul-bold.woff differ diff --git a/_assets/fonts/regul-book.woff b/_assets/fonts/regul-book.woff new file mode 100644 index 00000000..51abdeab Binary files /dev/null and b/_assets/fonts/regul-book.woff differ diff --git a/_assets/js/examples.js b/_assets/js/examples.js new file mode 100644 index 00000000..fd061887 --- /dev/null +++ b/_assets/js/examples.js @@ -0,0 +1,25 @@ +/** + * Very minimal shared code for examples. + */ + +(function() { + if (document.body) { setupEmbed(); } + else { document.addEventListener("DOMContentLoaded", setupEmbed); } + + function setupEmbed() { + if (window.top != window) { + document.body.className += " embedded"; + } + } + + var o = window.examples = {}; + o.showDistractor = function(id) { + var div = id ? document.getElementById(id) : document.querySelector("div canvas").parentNode; + div.className += " loading"; + }; + + o.hideDistractor = function() { + var div = document.querySelector(".loading"); + div.className = div.className.replace(/\bloading\b/); + }; +})(); \ No newline at end of file diff --git a/_assets/libs/easeljs-NEXT.min.js b/_assets/libs/easeljs-NEXT.min.js new file mode 100644 index 00000000..39bec8a4 --- /dev/null +++ b/_assets/libs/easeljs-NEXT.min.js @@ -0,0 +1,15 @@ +/*! +* @license EaselJS +* Visit http://createjs.com/ for documentation, updates and examples. +* +* Copyright (c) 2011-2015 gskinner.com, inc. +* +* Distributed under the terms of the MIT license. +* http://www.opensource.org/licenses/mit-license.html +* +* This notice shall be included in all copies or substantial portions of the Software. +*/ +this.createjs=this.createjs||{},createjs.extend=function(a,b){"use strict";function c(){this.constructor=a}return c.prototype=b.prototype,a.prototype=new c},this.createjs=this.createjs||{},createjs.promote=function(a,b){"use strict";var c=a.prototype,d=Object.getPrototypeOf&&Object.getPrototypeOf(c)||c.__proto__;if(d){c[(b+="_")+"constructor"]=d.constructor;for(var e in d)c.hasOwnProperty(e)&&"function"==typeof d[e]&&(c[b+e]=d[e])}return a},this.createjs=this.createjs||{},createjs.indexOf=function(a,b){"use strict";for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1},this.createjs=this.createjs||{},function(){"use strict";function a(){throw"UID cannot be instantiated"}a._nextID=0,a.get=function(){return a._nextID++},createjs.UID=a}(),this.createjs=this.createjs||{},createjs.deprecate=function(a,b){"use strict";return function(){var c="Deprecated property or method '"+b+"'. See docs for info.";return console&&(console.warn?console.warn(c):console.log(c)),a&&a.apply(this,arguments)}},this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c){this.type=a,this.target=null,this.currentTarget=null,this.eventPhase=0,this.bubbles=!!b,this.cancelable=!!c,this.timeStamp=(new Date).getTime(),this.defaultPrevented=!1,this.propagationStopped=!1,this.immediatePropagationStopped=!1,this.removed=!1}var b=a.prototype;b.preventDefault=function(){this.defaultPrevented=this.cancelable&&!0},b.stopPropagation=function(){this.propagationStopped=!0},b.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},b.remove=function(){this.removed=!0},b.clone=function(){return new a(this.type,this.bubbles,this.cancelable)},b.set=function(a){for(var b in a)this[b]=a[b];return this},b.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(){this._listeners=null,this._captureListeners=null}var b=a.prototype;a.initialize=function(a){a.addEventListener=b.addEventListener,a.on=b.on,a.removeEventListener=a.off=b.removeEventListener,a.removeAllEventListeners=b.removeAllEventListeners,a.hasEventListener=b.hasEventListener,a.dispatchEvent=b.dispatchEvent,a._dispatchEvent=b._dispatchEvent,a.willTrigger=b.willTrigger},b.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},b.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},b.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},b.off=b.removeEventListener,b.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},b.dispatchEvent=function(a,b,c){if("string"==typeof a){var d=this._listeners;if(!(b||d&&d[a]))return!0;a=new createjs.Event(a,b,c)}else a.target&&a.clone&&(a=a.clone());try{a.target=this}catch(e){}if(a.bubbles&&this.parent){for(var f=this,g=[f];f.parent;)g.push(f=f.parent);var h,i=g.length;for(h=i-1;h>=0&&!a.propagationStopped;h--)g[h]._dispatchEvent(a,1+(0==h));for(h=1;i>h&&!a.propagationStopped;h++)g[h]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return!a.defaultPrevented},b.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},b.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},b.toString=function(){return"[EventDispatcher]"},b._dispatchEvent=function(a,b){var c,d,e=2>=b?this._captureListeners:this._listeners;if(a&&e&&(d=e[a.type])&&(c=d.length)){try{a.currentTarget=this}catch(f){}try{a.eventPhase=0|b}catch(f){}a.removed=!1,d=d.slice();for(var g=0;c>g&&!a.immediatePropagationStopped;g++){var h=d[g];h.handleEvent?h.handleEvent(a):h(a),a.removed&&(this.off(a.type,h,1==b),a.removed=!1)}}2===b&&this._dispatchEvent(a,2.1)},createjs.EventDispatcher=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(){throw"Ticker cannot be instantiated."}a.RAF_SYNCHED="synched",a.RAF="raf",a.TIMEOUT="timeout",a.timingMode=null,a.maxDelta=0,a.paused=!1,a.removeEventListener=null,a.removeAllEventListeners=null,a.dispatchEvent=null,a.hasEventListener=null,a._listeners=null,createjs.EventDispatcher.initialize(a),a._addEventListener=a.addEventListener,a.addEventListener=function(){return!a._inited&&a.init(),a._addEventListener.apply(a,arguments)},a._inited=!1,a._startTime=0,a._pausedTime=0,a._ticks=0,a._pausedTicks=0,a._interval=50,a._lastTime=0,a._times=null,a._tickTimes=null,a._timerId=null,a._raf=!0,a._setInterval=function(b){a._interval=b,a._inited&&a._setupTick()},a.setInterval=createjs.deprecate(a._setInterval,"Ticker.setInterval"),a._getInterval=function(){return a._interval},a.getInterval=createjs.deprecate(a._getInterval,"Ticker.getInterval"),a._setFPS=function(b){a._setInterval(1e3/b)},a.setFPS=createjs.deprecate(a._setFPS,"Ticker.setFPS"),a._getFPS=function(){return 1e3/a._interval},a.getFPS=createjs.deprecate(a._getFPS,"Ticker.getFPS");try{Object.defineProperties(a,{interval:{get:a._getInterval,set:a._setInterval},framerate:{get:a._getFPS,set:a._setFPS}})}catch(b){console.log(b)}a.init=function(){a._inited||(a._inited=!0,a._times=[],a._tickTimes=[],a._startTime=a._getTime(),a._times.push(a._lastTime=0),a.interval=a._interval)},a.reset=function(){if(a._raf){var b=window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame;b&&b(a._timerId)}else clearTimeout(a._timerId);a.removeAllEventListeners("tick"),a._timerId=a._times=a._tickTimes=null,a._startTime=a._lastTime=a._ticks=a._pausedTime=0,a._inited=!1},a.getMeasuredTickTime=function(b){var c=0,d=a._tickTimes;if(!d||d.length<1)return-1;b=Math.min(d.length,b||0|a._getFPS());for(var e=0;b>e;e++)c+=d[e];return c/b},a.getMeasuredFPS=function(b){var c=a._times;return!c||c.length<2?-1:(b=Math.min(c.length-1,b||0|a._getFPS()),1e3/((c[0]-c[b])/b))},a.getTime=function(b){return a._startTime?a._getTime()-(b?a._pausedTime:0):-1},a.getEventTime=function(b){return a._startTime?(a._lastTime||a._startTime)-(b?a._pausedTime:0):-1},a.getTicks=function(b){return a._ticks-(b?a._pausedTicks:0)},a._handleSynch=function(){a._timerId=null,a._setupTick(),a._getTime()-a._lastTime>=.97*(a._interval-1)&&a._tick()},a._handleRAF=function(){a._timerId=null,a._setupTick(),a._tick()},a._handleTimeout=function(){a._timerId=null,a._setupTick(),a._tick()},a._setupTick=function(){if(null==a._timerId){var b=a.timingMode;if(b==a.RAF_SYNCHED||b==a.RAF){var c=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame;if(c)return a._timerId=c(b==a.RAF?a._handleRAF:a._handleSynch),void(a._raf=!0)}a._raf=!1,a._timerId=setTimeout(a._handleTimeout,a._interval)}},a._tick=function(){var b=a.paused,c=a._getTime(),d=c-a._lastTime;if(a._lastTime=c,a._ticks++,b&&(a._pausedTicks++,a._pausedTime+=d),a.hasEventListener("tick")){var e=new createjs.Event("tick"),f=a.maxDelta;e.delta=f&&d>f?f:d,e.paused=b,e.time=c,e.runTime=c-a._pausedTime,a.dispatchEvent(e)}for(a._tickTimes.unshift(a._getTime()-c);a._tickTimes.length>100;)a._tickTimes.pop();for(a._times.unshift(c);a._times.length>100;)a._times.pop()};var c=window,d=c.performance.now||c.performance.mozNow||c.performance.msNow||c.performance.oNow||c.performance.webkitNow;a._getTime=function(){return(d&&d.call(c.performance)||(new Date).getTime())-a._startTime},createjs.Ticker=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a){this.readyState=a.readyState,this._video=a,this._canvas=null,this._lastTime=-1,this.readyState<2&&a.addEventListener("canplaythrough",this._videoReady.bind(this))}var b=a.prototype;b.getImage=function(){if(!(this.readyState<2)){var a=this._canvas,b=this._video;if(a||(a=this._canvas=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"),a.width=b.videoWidth,a.height=b.videoHeight),b.readyState>=2&&b.currentTime!==this._lastTime){var c=a.getContext("2d");c.clearRect(0,0,a.width,a.height),c.drawImage(b,0,0,a.width,a.height),this._lastTime=b.currentTime}return a}},b._videoReady=function(){this.readyState=2},createjs.VideoBuffer=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c,d,e,f,g,h,i,j,k){this.Event_constructor(a,b,c),this.stageX=d,this.stageY=e,this.rawX=null==i?d:i,this.rawY=null==j?e:j,this.nativeEvent=f,this.pointerID=g,this.primary=!!h,this.relatedTarget=k}var b=createjs.extend(a,createjs.Event);b._get_localX=function(){return this.currentTarget.globalToLocal(this.rawX,this.rawY).x},b._get_localY=function(){return this.currentTarget.globalToLocal(this.rawX,this.rawY).y},b._get_isTouch=function(){return-1!==this.pointerID};try{Object.defineProperties(b,{localX:{get:b._get_localX},localY:{get:b._get_localY},isTouch:{get:b._get_isTouch}})}catch(c){}b.clone=function(){return new a(this.type,this.bubbles,this.cancelable,this.stageX,this.stageY,this.nativeEvent,this.pointerID,this.primary,this.rawX,this.rawY)},b.toString=function(){return"[MouseEvent (type="+this.type+" stageX="+this.stageX+" stageY="+this.stageY+")]"},createjs.MouseEvent=createjs.promote(a,"Event")}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c,d,e,f){this.setValues(a,b,c,d,e,f)}var b=a.prototype;a.DEG_TO_RAD=Math.PI/180,a.identity=null,b.setValues=function(a,b,c,d,e,f){return this.a=null==a?1:a,this.b=b||0,this.c=c||0,this.d=null==d?1:d,this.tx=e||0,this.ty=f||0,this},b.append=function(a,b,c,d,e,f){var g=this.a,h=this.b,i=this.c,j=this.d;return(1!=a||0!=b||0!=c||1!=d)&&(this.a=g*a+i*b,this.b=h*a+j*b,this.c=g*c+i*d,this.d=h*c+j*d),this.tx=g*e+i*f+this.tx,this.ty=h*e+j*f+this.ty,this},b.prepend=function(a,b,c,d,e,f){var g=this.a,h=this.c,i=this.tx;return this.a=a*g+c*this.b,this.b=b*g+d*this.b,this.c=a*h+c*this.d,this.d=b*h+d*this.d,this.tx=a*i+c*this.ty+e,this.ty=b*i+d*this.ty+f,this},b.appendMatrix=function(a){return this.append(a.a,a.b,a.c,a.d,a.tx,a.ty)},b.prependMatrix=function(a){return this.prepend(a.a,a.b,a.c,a.d,a.tx,a.ty)},b.appendTransform=function(b,c,d,e,f,g,h,i,j){if(f%360)var k=f*a.DEG_TO_RAD,l=Math.cos(k),m=Math.sin(k);else l=1,m=0;return g||h?(g*=a.DEG_TO_RAD,h*=a.DEG_TO_RAD,this.append(Math.cos(h),Math.sin(h),-Math.sin(g),Math.cos(g),b,c),this.append(l*d,m*d,-m*e,l*e,0,0)):this.append(l*d,m*d,-m*e,l*e,b,c),(i||j)&&(this.tx-=i*this.a+j*this.c,this.ty-=i*this.b+j*this.d),this},b.prependTransform=function(b,c,d,e,f,g,h,i,j){if(f%360)var k=f*a.DEG_TO_RAD,l=Math.cos(k),m=Math.sin(k);else l=1,m=0;return(i||j)&&(this.tx-=i,this.ty-=j),g||h?(g*=a.DEG_TO_RAD,h*=a.DEG_TO_RAD,this.prepend(l*d,m*d,-m*e,l*e,0,0),this.prepend(Math.cos(h),Math.sin(h),-Math.sin(g),Math.cos(g),b,c)):this.prepend(l*d,m*d,-m*e,l*e,b,c),this},b.rotate=function(b){b*=a.DEG_TO_RAD;var c=Math.cos(b),d=Math.sin(b),e=this.a,f=this.b;return this.a=e*c+this.c*d,this.b=f*c+this.d*d,this.c=-e*d+this.c*c,this.d=-f*d+this.d*c,this},b.skew=function(b,c){return b*=a.DEG_TO_RAD,c*=a.DEG_TO_RAD,this.append(Math.cos(c),Math.sin(c),-Math.sin(b),Math.cos(b),0,0),this},b.scale=function(a,b){return this.a*=a,this.b*=a,this.c*=b,this.d*=b,this},b.translate=function(a,b){return this.tx+=this.a*a+this.c*b,this.ty+=this.b*a+this.d*b,this},b.identity=function(){return this.a=this.d=1,this.b=this.c=this.tx=this.ty=0,this},b.invert=function(){var a=this.a,b=this.b,c=this.c,d=this.d,e=this.tx,f=a*d-b*c;return this.a=d/f,this.b=-b/f,this.c=-c/f,this.d=a/f,this.tx=(c*this.ty-d*e)/f,this.ty=-(a*this.ty-b*e)/f,this},b.isIdentity=function(){return 0===this.tx&&0===this.ty&&1===this.a&&0===this.b&&0===this.c&&1===this.d},b.equals=function(a){return this.tx===a.tx&&this.ty===a.ty&&this.a===a.a&&this.b===a.b&&this.c===a.c&&this.d===a.d},b.transformPoint=function(a,b,c){return c=c||{},c.x=a*this.a+b*this.c+this.tx,c.y=a*this.b+b*this.d+this.ty,c},b.decompose=function(b){null==b&&(b={}),b.x=this.tx,b.y=this.ty,b.scaleX=Math.sqrt(this.a*this.a+this.b*this.b),b.scaleY=Math.sqrt(this.c*this.c+this.d*this.d);var c=Math.atan2(-this.c,this.d),d=Math.atan2(this.b,this.a),e=Math.abs(1-c/d);return 1e-5>e?(b.rotation=d/a.DEG_TO_RAD,this.a<0&&this.d>=0&&(b.rotation+=b.rotation<=0?180:-180),b.skewX=b.skewY=0):(b.skewX=c/a.DEG_TO_RAD,b.skewY=d/a.DEG_TO_RAD),b},b.copy=function(a){return this.setValues(a.a,a.b,a.c,a.d,a.tx,a.ty)},b.clone=function(){return new a(this.a,this.b,this.c,this.d,this.tx,this.ty)},b.toString=function(){return"[Matrix2D (a="+this.a+" b="+this.b+" c="+this.c+" d="+this.d+" tx="+this.tx+" ty="+this.ty+")]"},a.identity=new a,createjs.Matrix2D=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c,d,e){this.setValues(a,b,c,d,e)}var b=a.prototype;b.setValues=function(a,b,c,d,e){return this.visible=null==a?!0:!!a,this.alpha=null==b?1:b,this.shadow=c,this.compositeOperation=d,this.matrix=e||this.matrix&&this.matrix.identity()||new createjs.Matrix2D,this},b.append=function(a,b,c,d,e){return this.alpha*=b,this.shadow=c||this.shadow,this.compositeOperation=d||this.compositeOperation,this.visible=this.visible&&a,e&&this.matrix.appendMatrix(e),this},b.prepend=function(a,b,c,d,e){return this.alpha*=b,this.shadow=this.shadow||c,this.compositeOperation=this.compositeOperation||d,this.visible=this.visible&&a,e&&this.matrix.prependMatrix(e),this},b.identity=function(){return this.visible=!0,this.alpha=1,this.shadow=this.compositeOperation=null,this.matrix.identity(),this},b.clone=function(){return new a(this.alpha,this.shadow,this.compositeOperation,this.visible,this.matrix.clone())},createjs.DisplayProps=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b){this.setValues(a,b)}var b=a.prototype;b.setValues=function(a,b){return this.x=a||0,this.y=b||0,this},b.copy=function(a){return this.x=a.x,this.y=a.y,this},b.clone=function(){return new a(this.x,this.y)},b.toString=function(){return"[Point (x="+this.x+" y="+this.y+")]"},createjs.Point=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c,d){this.setValues(a,b,c,d)}var b=a.prototype;b.setValues=function(a,b,c,d){return this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0,this},b.extend=function(a,b,c,d){return c=c||0,d=d||0,a+c>this.x+this.width&&(this.width=a+c-this.x),b+d>this.y+this.height&&(this.height=b+d-this.y),a=this.x&&a+c<=this.x+this.width&&b>=this.y&&b+d<=this.y+this.height},b.union=function(a){return this.clone().extend(a.x,a.y,a.width,a.height)},b.intersection=function(b){var c=b.x,d=b.y,e=c+b.width,f=d+b.height;return this.x>c&&(c=this.x),this.y>d&&(d=this.y),this.x+this.width=e||d>=f?null:new a(c,d,e-c,f-d)},b.intersects=function(a){return a.x<=this.x+this.width&&this.x<=a.x+a.width&&a.y<=this.y+this.height&&this.y<=a.y+a.height},b.isEmpty=function(){return this.width<=0||this.height<=0},b.clone=function(){return new a(this.x,this.y,this.width,this.height)},b.toString=function(){return"[Rectangle (x="+this.x+" y="+this.y+" width="+this.width+" height="+this.height+")]"},createjs.Rectangle=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c,d,e,f,g){a.addEventListener&&(this.target=a,this.overLabel=null==c?"over":c,this.outLabel=null==b?"out":b,this.downLabel=null==d?"down":d,this.play=e,this._isPressed=!1,this._isOver=!1,this._enabled=!1,a.mouseChildren=!1,this.enabled=!0,this.handleEvent({}),f&&(g&&(f.actionsEnabled=!1,f.gotoAndStop&&f.gotoAndStop(g)),a.hitArea=f))}var b=a.prototype;b._setEnabled=function(a){if(a!=this._enabled){var b=this.target;this._enabled=a,a?(b.cursor="pointer",b.addEventListener("rollover",this),b.addEventListener("rollout",this),b.addEventListener("mousedown",this),b.addEventListener("pressup",this),b._reset&&(b.__reset=b._reset,b._reset=this._reset)):(b.cursor=null,b.removeEventListener("rollover",this),b.removeEventListener("rollout",this),b.removeEventListener("mousedown",this),b.removeEventListener("pressup",this),b.__reset&&(b._reset=b.__reset,delete b.__reset))}},b.setEnabled=createjs.deprecate(b._setEnabled,"ButtonHelper.setEnabled"),b._getEnabled=function(){return this._enabled},b.getEnabled=createjs.deprecate(b._getEnabled,"ButtonHelper.getEnabled");try{Object.defineProperties(b,{enabled:{get:b._getEnabled,set:b._setEnabled}})}catch(c){}b.toString=function(){return"[ButtonHelper]"},b.handleEvent=function(a){var b,c=this.target,d=a.type;"mousedown"==d?(this._isPressed=!0,b=this.downLabel):"pressup"==d?(this._isPressed=!1,b=this._isOver?this.overLabel:this.outLabel):"rollover"==d?(this._isOver=!0,b=this._isPressed?this.downLabel:this.overLabel):(this._isOver=!1,b=this._isPressed?this.overLabel:this.outLabel),this.play?c.gotoAndPlay&&c.gotoAndPlay(b):c.gotoAndStop&&c.gotoAndStop(b)},b._reset=function(){var a=this.paused;this.__reset(),this.paused=a},createjs.ButtonHelper=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c,d){this.color=a||"black",this.offsetX=b||0,this.offsetY=c||0,this.blur=d||0}var b=a.prototype;a.identity=new a("transparent",0,0,0),b.toString=function(){return"[Shadow]"},b.clone=function(){return new a(this.color,this.offsetX,this.offsetY,this.blur)},createjs.Shadow=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a){this.EventDispatcher_constructor(),this.complete=!0,this.framerate=0,this._animations=null,this._frames=null,this._images=null,this._data=null,this._loadCount=0,this._frameHeight=0,this._frameWidth=0,this._numFrames=0,this._regX=0,this._regY=0,this._spacing=0,this._margin=0,this._parseData(a)}var b=createjs.extend(a,createjs.EventDispatcher);b._getAnimations=function(){return this._animations.slice()},b.getAnimations=createjs.deprecate(b._getAnimations,"SpriteSheet.getAnimations");try{Object.defineProperties(b,{animations:{get:b._getAnimations}})}catch(c){}b.getNumFrames=function(a){if(null==a)return this._frames?this._frames.length:this._numFrames||0;var b=this._data[a];return null==b?0:b.frames.length},b.getAnimation=function(a){return this._data[a]},b.getFrame=function(a){var b;return this._frames&&(b=this._frames[a])?b:null},b.getFrameBounds=function(a,b){var c=this.getFrame(a);return c?(b||new createjs.Rectangle).setValues(-c.regX,-c.regY,c.rect.width,c.rect.height):null},b.toString=function(){return"[SpriteSheet]"},b.clone=function(){throw"SpriteSheet cannot be cloned."},b._parseData=function(a){var b,c,d,e;if(null!=a){if(this.framerate=a.framerate||0,a.images&&(c=a.images.length)>0)for(e=this._images=[],b=0;c>b;b++){var f=a.images[b];if("string"==typeof f){var g=f;f=document.createElement("img"),f.src=g}e.push(f),f.getContext||f.naturalWidth||(this._loadCount++,this.complete=!1,function(a,b){f.onload=function(){a._handleImageLoad(b)}}(this,g),function(a,b){f.onerror=function(){a._handleImageError(b)}}(this,g))}if(null==a.frames);else if(Array.isArray(a.frames))for(this._frames=[],e=a.frames,b=0,c=e.length;c>b;b++){var h=e[b];this._frames.push({image:this._images[h[4]?h[4]:0],rect:new createjs.Rectangle(h[0],h[1],h[2],h[3]),regX:h[5]||0,regY:h[6]||0})}else d=a.frames,this._frameWidth=d.width,this._frameHeight=d.height,this._regX=d.regX||0,this._regY=d.regY||0,this._spacing=d.spacing||0,this._margin=d.margin||0,this._numFrames=d.count,0==this._loadCount&&this._calculateFrames();if(this._animations=[],null!=(d=a.animations)){this._data={};var i;for(i in d){var j={name:i},k=d[i];if("number"==typeof k)e=j.frames=[k];else if(Array.isArray(k))if(1==k.length)j.frames=[k[0]];else for(j.speed=k[3],j.next=k[2],e=j.frames=[],b=k[0];b<=k[1];b++)e.push(b);else{j.speed=k.speed,j.next=k.next;var l=k.frames;e=j.frames="number"==typeof l?[l]:l.slice(0)}(j.next===!0||void 0===j.next)&&(j.next=i),(j.next===!1||e.length<2&&j.next==i)&&(j.next=null),j.speed||(j.speed=1),this._animations.push(i),this._data[i]=j}}}},b._handleImageLoad=function(){0==--this._loadCount&&(this._calculateFrames(),this.complete=!0,this.dispatchEvent("complete"))},b._handleImageError=function(a){var b=new createjs.Event("error");b.src=a,this.dispatchEvent(b),0==--this._loadCount&&this.dispatchEvent("complete")},b._calculateFrames=function(){if(!this._frames&&0!=this._frameWidth){this._frames=[];var a=this._numFrames||1e5,b=0,c=this._frameWidth,d=this._frameHeight,e=this._spacing,f=this._margin;a:for(var g=0,h=this._images;g=l;){for(var m=f;j-f-c>=m;){if(b>=a)break a;b++,this._frames.push({image:i,rect:new createjs.Rectangle(m,l,c,d),regX:this._regX,regY:this._regY}),m+=c+e}l+=d+e}this._numFrames=b}},createjs.SpriteSheet=createjs.promote(a,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function a(){this.command=null,this._stroke=null,this._strokeStyle=null,this._oldStrokeStyle=null,this._strokeDash=null,this._oldStrokeDash=null,this._strokeIgnoreScale=!1,this._fill=null,this._instructions=[],this._commitIndex=0,this._activeInstructions=[],this._dirty=!1,this._storeIndex=0,this.clear()}var b=a.prototype,c=a;a.getRGB=function(a,b,c,d){return null!=a&&null==c&&(d=b,c=255&a,b=a>>8&255,a=a>>16&255),null==d?"rgb("+a+","+b+","+c+")":"rgba("+a+","+b+","+c+","+d+")"},a.getHSL=function(a,b,c,d){return null==d?"hsl("+a%360+","+b+"%,"+c+"%)":"hsla("+a%360+","+b+"%,"+c+"%,"+d+")"},a.BASE_64={A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8,J:9,K:10,L:11,M:12,N:13,O:14,P:15,Q:16,R:17,S:18,T:19,U:20,V:21,W:22,X:23,Y:24,Z:25,a:26,b:27,c:28,d:29,e:30,f:31,g:32,h:33,i:34,j:35,k:36,l:37,m:38,n:39,o:40,p:41,q:42,r:43,s:44,t:45,u:46,v:47,w:48,x:49,y:50,z:51,0:52,1:53,2:54,3:55,4:56,5:57,6:58,7:59,8:60,9:61,"+":62,"/":63},a.STROKE_CAPS_MAP=["butt","round","square"],a.STROKE_JOINTS_MAP=["miter","round","bevel"];var d=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");d.getContext&&(a._ctx=d.getContext("2d"),d.width=d.height=1),b._getInstructions=function(){return this._updateInstructions(),this._instructions},b.getInstructions=createjs.deprecate(b._getInstructions,"Graphics.getInstructions");try{Object.defineProperties(b,{instructions:{get:b._getInstructions}})}catch(e){}b.isEmpty=function(){return!(this._instructions.length||this._activeInstructions.length)},b.draw=function(a,b){this._updateInstructions();for(var c=this._instructions,d=this._storeIndex,e=c.length;e>d;d++)c[d].exec(a,b)},b.drawAsPath=function(a){this._updateInstructions();for(var b,c=this._instructions,d=this._storeIndex,e=c.length;e>d;d++)(b=c[d]).path!==!1&&b.exec(a)},b.moveTo=function(a,b){return this.append(new c.MoveTo(a,b),!0)},b.lineTo=function(a,b){return this.append(new c.LineTo(a,b))},b.arcTo=function(a,b,d,e,f){return this.append(new c.ArcTo(a,b,d,e,f))},b.arc=function(a,b,d,e,f,g){return this.append(new c.Arc(a,b,d,e,f,g))},b.quadraticCurveTo=function(a,b,d,e){return this.append(new c.QuadraticCurveTo(a,b,d,e))},b.bezierCurveTo=function(a,b,d,e,f,g){return this.append(new c.BezierCurveTo(a,b,d,e,f,g))},b.rect=function(a,b,d,e){return this.append(new c.Rect(a,b,d,e))},b.closePath=function(){return this._activeInstructions.length?this.append(new c.ClosePath):this},b.clear=function(){return this._instructions.length=this._activeInstructions.length=this._commitIndex=0,this._strokeStyle=this._oldStrokeStyle=this._stroke=this._fill=this._strokeDash=this._oldStrokeDash=null,this._dirty=this._strokeIgnoreScale=!1,this},b.beginFill=function(a){return this._setFill(a?new c.Fill(a):null)},b.beginLinearGradientFill=function(a,b,d,e,f,g){return this._setFill((new c.Fill).linearGradient(a,b,d,e,f,g))},b.beginRadialGradientFill=function(a,b,d,e,f,g,h,i){return this._setFill((new c.Fill).radialGradient(a,b,d,e,f,g,h,i))},b.beginBitmapFill=function(a,b,d){return this._setFill(new c.Fill(null,d).bitmap(a,b))},b.endFill=function(){return this.beginFill()},b.setStrokeStyle=function(a,b,d,e,f){return this._updateInstructions(!0),this._strokeStyle=this.command=new c.StrokeStyle(a,b,d,e,f),this._stroke&&(this._stroke.ignoreScale=f),this._strokeIgnoreScale=f,this},b.setStrokeDash=function(a,b){return this._updateInstructions(!0),this._strokeDash=this.command=new c.StrokeDash(a,b),this},b.beginStroke=function(a){return this._setStroke(a?new c.Stroke(a):null)},b.beginLinearGradientStroke=function(a,b,d,e,f,g){return this._setStroke((new c.Stroke).linearGradient(a,b,d,e,f,g))},b.beginRadialGradientStroke=function(a,b,d,e,f,g,h,i){return this._setStroke((new c.Stroke).radialGradient(a,b,d,e,f,g,h,i))},b.beginBitmapStroke=function(a,b){return this._setStroke((new c.Stroke).bitmap(a,b))},b.endStroke=function(){return this.beginStroke()},b.curveTo=b.quadraticCurveTo,b.drawRect=b.rect,b.drawRoundRect=function(a,b,c,d,e){return this.drawRoundRectComplex(a,b,c,d,e,e,e,e)},b.drawRoundRectComplex=function(a,b,d,e,f,g,h,i){return this.append(new c.RoundRect(a,b,d,e,f,g,h,i))},b.drawCircle=function(a,b,d){return this.append(new c.Circle(a,b,d))},b.drawEllipse=function(a,b,d,e){return this.append(new c.Ellipse(a,b,d,e))},b.drawPolyStar=function(a,b,d,e,f,g){return this.append(new c.PolyStar(a,b,d,e,f,g))},b.append=function(a,b){return this._activeInstructions.push(a),this.command=a,b||(this._dirty=!0),this},b.decodePath=function(b){for(var c=[this.moveTo,this.lineTo,this.quadraticCurveTo,this.bezierCurveTo,this.closePath],d=[2,2,4,6,0],e=0,f=b.length,g=[],h=0,i=0,j=a.BASE_64;f>e;){var k=b.charAt(e),l=j[k],m=l>>3,n=c[m];if(!n||3&l)throw"bad path data (@"+e+"): "+k;var o=d[m];m||(h=i=0),g.length=0,e++;for(var p=(l>>2&1)+2,q=0;o>q;q++){var r=j[b.charAt(e)],s=r>>5?-1:1;r=(31&r)<<6|j[b.charAt(e+1)],3==p&&(r=r<<6|j[b.charAt(e+2)]),r=s*r/10,q%2?h=r+=h:i=r+=i,g[q]=r,e+=p}n.apply(this,g)}return this},b.store=function(){return this._updateInstructions(!0),this._storeIndex=this._instructions.length,this},b.unstore=function(){return this._storeIndex=0,this},b.clone=function(){var b=new a;return b.command=this.command,b._stroke=this._stroke,b._strokeStyle=this._strokeStyle,b._strokeDash=this._strokeDash,b._strokeIgnoreScale=this._strokeIgnoreScale,b._fill=this._fill,b._instructions=this._instructions.slice(),b._commitIndex=this._commitIndex,b._activeInstructions=this._activeInstructions.slice(),b._dirty=this._dirty,b._storeIndex=this._storeIndex,b},b.toString=function(){return"[Graphics]"},b.mt=b.moveTo,b.lt=b.lineTo,b.at=b.arcTo,b.bt=b.bezierCurveTo,b.qt=b.quadraticCurveTo,b.a=b.arc,b.r=b.rect,b.cp=b.closePath,b.c=b.clear,b.f=b.beginFill,b.lf=b.beginLinearGradientFill,b.rf=b.beginRadialGradientFill,b.bf=b.beginBitmapFill,b.ef=b.endFill,b.ss=b.setStrokeStyle,b.sd=b.setStrokeDash,b.s=b.beginStroke,b.ls=b.beginLinearGradientStroke,b.rs=b.beginRadialGradientStroke,b.bs=b.beginBitmapStroke,b.es=b.endStroke,b.dr=b.drawRect,b.rr=b.drawRoundRect,b.rc=b.drawRoundRectComplex,b.dc=b.drawCircle,b.de=b.drawEllipse,b.dp=b.drawPolyStar,b.p=b.decodePath,b._updateInstructions=function(b){var c=this._instructions,d=this._activeInstructions,e=this._commitIndex;if(this._dirty&&d.length){c.length=e,c.push(a.beginCmd);var f=d.length,g=c.length;c.length=g+f;for(var h=0;f>h;h++)c[h+g]=d[h];this._fill&&c.push(this._fill),this._stroke&&(this._strokeDash!==this._oldStrokeDash&&c.push(this._strokeDash),this._strokeStyle!==this._oldStrokeStyle&&c.push(this._strokeStyle),b&&(this._oldStrokeStyle=this._strokeStyle,this._oldStrokeDash=this._strokeDash),c.push(this._stroke)),this._dirty=!1}b&&(d.length=0,this._commitIndex=c.length)},b._setFill=function(a){return this._updateInstructions(!0),this.command=this._fill=a,this},b._setStroke=function(a){return this._updateInstructions(!0),(this.command=this._stroke=a)&&(a.ignoreScale=this._strokeIgnoreScale),this},(c.LineTo=function(a,b){this.x=a,this.y=b}).prototype.exec=function(a){a.lineTo(this.x,this.y)},(c.MoveTo=function(a,b){this.x=a,this.y=b}).prototype.exec=function(a){a.moveTo(this.x,this.y)},(c.ArcTo=function(a,b,c,d,e){this.x1=a,this.y1=b,this.x2=c,this.y2=d,this.radius=e}).prototype.exec=function(a){a.arcTo(this.x1,this.y1,this.x2,this.y2,this.radius)},(c.Arc=function(a,b,c,d,e,f){this.x=a,this.y=b,this.radius=c,this.startAngle=d,this.endAngle=e,this.anticlockwise=!!f}).prototype.exec=function(a){a.arc(this.x,this.y,this.radius,this.startAngle,this.endAngle,this.anticlockwise)},(c.QuadraticCurveTo=function(a,b,c,d){this.cpx=a,this.cpy=b,this.x=c,this.y=d}).prototype.exec=function(a){a.quadraticCurveTo(this.cpx,this.cpy,this.x,this.y)},(c.BezierCurveTo=function(a,b,c,d,e,f){this.cp1x=a,this.cp1y=b,this.cp2x=c,this.cp2y=d,this.x=e,this.y=f}).prototype.exec=function(a){a.bezierCurveTo(this.cp1x,this.cp1y,this.cp2x,this.cp2y,this.x,this.y)},(c.Rect=function(a,b,c,d){this.x=a,this.y=b,this.w=c,this.h=d}).prototype.exec=function(a){a.rect(this.x,this.y,this.w,this.h)},(c.ClosePath=function(){}).prototype.exec=function(a){a.closePath()},(c.BeginPath=function(){}).prototype.exec=function(a){a.beginPath()},b=(c.Fill=function(a,b){this.style=a,this.matrix=b}).prototype,b.exec=function(a){if(this.style){a.fillStyle=this.style;var b=this.matrix;b&&(a.save(),a.transform(b.a,b.b,b.c,b.d,b.tx,b.ty)),a.fill(),b&&a.restore()}},b.linearGradient=function(b,c,d,e,f,g){for(var h=this.style=a._ctx.createLinearGradient(d,e,f,g),i=0,j=b.length;j>i;i++)h.addColorStop(c[i],b[i]);return h.props={colors:b,ratios:c,x0:d,y0:e,x1:f,y1:g,type:"linear"},this},b.radialGradient=function(b,c,d,e,f,g,h,i){for(var j=this.style=a._ctx.createRadialGradient(d,e,f,g,h,i),k=0,l=b.length;l>k;k++)j.addColorStop(c[k],b[k]);return j.props={colors:b,ratios:c,x0:d,y0:e,r0:f,x1:g,y1:h,r1:i,type:"radial"},this},b.bitmap=function(b,c){if(b.naturalWidth||b.getContext||b.readyState>=2){var d=this.style=a._ctx.createPattern(b,c||"");d.props={image:b,repetition:c,type:"bitmap"}}return this},b.path=!1,b=(c.Stroke=function(a,b){this.style=a,this.ignoreScale=b}).prototype,b.exec=function(a){this.style&&(a.strokeStyle=this.style,this.ignoreScale&&(a.save(),a.setTransform(1,0,0,1,0,0)),a.stroke(),this.ignoreScale&&a.restore())},b.linearGradient=c.Fill.prototype.linearGradient,b.radialGradient=c.Fill.prototype.radialGradient,b.bitmap=c.Fill.prototype.bitmap,b.path=!1,b=(c.StrokeStyle=function(a,b,c,d,e){this.width=a,this.caps=b,this.joints=c,this.miterLimit=d,this.ignoreScale=e}).prototype,b.exec=function(b){b.lineWidth=null==this.width?"1":this.width,b.lineCap=null==this.caps?"butt":isNaN(this.caps)?this.caps:a.STROKE_CAPS_MAP[this.caps],b.lineJoin=null==this.joints?"miter":isNaN(this.joints)?this.joints:a.STROKE_JOINTS_MAP[this.joints],b.miterLimit=null==this.miterLimit?"10":this.miterLimit,b.ignoreScale=null==this.ignoreScale?!1:this.ignoreScale},b.path=!1,(c.StrokeDash=function(a,b){this.segments=a,this.offset=b||0}).prototype.exec=function(a){a.setLineDash&&(a.setLineDash(this.segments||c.StrokeDash.EMPTY_SEGMENTS),a.lineDashOffset=this.offset||0)},c.StrokeDash.EMPTY_SEGMENTS=[],(c.RoundRect=function(a,b,c,d,e,f,g,h){this.x=a,this.y=b,this.w=c,this.h=d,this.radiusTL=e,this.radiusTR=f,this.radiusBR=g,this.radiusBL=h}).prototype.exec=function(a){var b=(j>i?i:j)/2,c=0,d=0,e=0,f=0,g=this.x,h=this.y,i=this.w,j=this.h,k=this.radiusTL,l=this.radiusTR,m=this.radiusBR,n=this.radiusBL;0>k&&(k*=c=-1),k>b&&(k=b),0>l&&(l*=d=-1),l>b&&(l=b),0>m&&(m*=e=-1),m>b&&(m=b),0>n&&(n*=f=-1),n>b&&(n=b),a.moveTo(g+i-l,h),a.arcTo(g+i+l*d,h-l*d,g+i,h+l,l),a.lineTo(g+i,h+j-m),a.arcTo(g+i+m*e,h+j+m*e,g+i-m,h+j,m),a.lineTo(g+n,h+j),a.arcTo(g-n*f,h+j+n*f,g,h+j-n,n),a.lineTo(g,h+k),a.arcTo(g-k*c,h-k*c,g+k,h,k),a.closePath() +},(c.Circle=function(a,b,c){this.x=a,this.y=b,this.radius=c}).prototype.exec=function(a){a.arc(this.x,this.y,this.radius,0,2*Math.PI)},(c.Ellipse=function(a,b,c,d){this.x=a,this.y=b,this.w=c,this.h=d}).prototype.exec=function(a){var b=this.x,c=this.y,d=this.w,e=this.h,f=.5522848,g=d/2*f,h=e/2*f,i=b+d,j=c+e,k=b+d/2,l=c+e/2;a.moveTo(b,l),a.bezierCurveTo(b,l-h,k-g,c,k,c),a.bezierCurveTo(k+g,c,i,l-h,i,l),a.bezierCurveTo(i,l+h,k+g,j,k,j),a.bezierCurveTo(k-g,j,b,l+h,b,l)},(c.PolyStar=function(a,b,c,d,e,f){this.x=a,this.y=b,this.radius=c,this.sides=d,this.pointSize=e,this.angle=f}).prototype.exec=function(a){var b=this.x,c=this.y,d=this.radius,e=(this.angle||0)/180*Math.PI,f=this.sides,g=1-(this.pointSize||0),h=Math.PI/f;a.moveTo(b+Math.cos(e)*d,c+Math.sin(e)*d);for(var i=0;f>i;i++)e+=h,1!=g&&a.lineTo(b+Math.cos(e)*d*g,c+Math.sin(e)*d*g),e+=h,a.lineTo(b+Math.cos(e)*d,c+Math.sin(e)*d);a.closePath()},a.beginCmd=new c.BeginPath,createjs.Graphics=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(){this.EventDispatcher_constructor(),this.alpha=1,this.cacheCanvas=null,this.bitmapCache=null,this.id=createjs.UID.get(),this.mouseEnabled=!0,this.tickEnabled=!0,this.name=null,this.parent=null,this.regX=0,this.regY=0,this.rotation=0,this.scaleX=1,this.scaleY=1,this.skewX=0,this.skewY=0,this.shadow=null,this.visible=!0,this.x=0,this.y=0,this.transformMatrix=null,this.compositeOperation=null,this.snapToPixel=!0,this.filters=null,this.mask=null,this.hitArea=null,this.cursor=null,this._props=new createjs.DisplayProps,this._rectangle=new createjs.Rectangle,this._bounds=null,this._webGLRenderStyle=a._StageGL_NONE}var b=createjs.extend(a,createjs.EventDispatcher);a._MOUSE_EVENTS=["click","dblclick","mousedown","mouseout","mouseover","pressmove","pressup","rollout","rollover"],a.suppressCrossDomainErrors=!1,a._snapToPixelEnabled=!1,a._StageGL_NONE=0,a._StageGL_SPRITE=1,a._StageGL_BITMAP=2;var c=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");c.getContext&&(a._hitTestCanvas=c,a._hitTestContext=c.getContext("2d"),c.width=c.height=1),b._getStage=function(){for(var a=this,b=createjs.Stage;a.parent;)a=a.parent;return a instanceof b?a:null},b.getStage=createjs.deprecate(b._getStage,"DisplayObject.getStage");try{Object.defineProperties(b,{stage:{get:b._getStage},cacheID:{get:function(){return this.bitmapCache&&this.bitmapCache.cacheID},set:function(a){this.bitmapCache&&(this.bitmapCache.cacheID=a)}},scale:{get:function(){return this.scaleX},set:function(a){this.scaleX=this.scaleY=a}}})}catch(d){}b.isVisible=function(){return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY)},b.draw=function(a,b){var c=this.bitmapCache;return c&&!b?c.draw(a):!1},b.updateContext=function(b){var c=this,d=c.mask,e=c._props.matrix;d&&d.graphics&&!d.graphics.isEmpty()&&(d.getMatrix(e),b.transform(e.a,e.b,e.c,e.d,e.tx,e.ty),d.graphics.drawAsPath(b),b.clip(),e.invert(),b.transform(e.a,e.b,e.c,e.d,e.tx,e.ty)),this.getMatrix(e);var f=e.tx,g=e.ty;a._snapToPixelEnabled&&c.snapToPixel&&(f=f+(0>f?-.5:.5)|0,g=g+(0>g?-.5:.5)|0),b.transform(e.a,e.b,e.c,e.d,f,g),b.globalAlpha*=c.alpha,c.compositeOperation&&(b.globalCompositeOperation=c.compositeOperation),c.shadow&&this._applyShadow(b,c.shadow)},b.cache=function(a,b,c,d,e,f){this.bitmapCache||(this.bitmapCache=new createjs.BitmapCache),this.bitmapCache.define(this,a,b,c,d,e,f)},b.updateCache=function(a){if(!this.bitmapCache)throw"cache() must be called before updateCache()";this.bitmapCache.update(a)},b.uncache=function(){this.bitmapCache&&(this.bitmapCache.release(),this.bitmapCache=void 0)},b.getCacheDataURL=function(){return this.bitmapCache?this.bitmapCache.getDataURL():null},b.localToGlobal=function(a,b,c){return this.getConcatenatedMatrix(this._props.matrix).transformPoint(a,b,c||new createjs.Point)},b.globalToLocal=function(a,b,c){return this.getConcatenatedMatrix(this._props.matrix).invert().transformPoint(a,b,c||new createjs.Point)},b.localToLocal=function(a,b,c,d){return d=this.localToGlobal(a,b,d),c.globalToLocal(d.x,d.y,d)},b.setTransform=function(a,b,c,d,e,f,g,h,i){return this.x=a||0,this.y=b||0,this.scaleX=null==c?1:c,this.scaleY=null==d?1:d,this.rotation=e||0,this.skewX=f||0,this.skewY=g||0,this.regX=h||0,this.regY=i||0,this},b.getMatrix=function(a){var b=this,c=a&&a.identity()||new createjs.Matrix2D;return b.transformMatrix?c.copy(b.transformMatrix):c.appendTransform(b.x,b.y,b.scaleX,b.scaleY,b.rotation,b.skewX,b.skewY,b.regX,b.regY)},b.getConcatenatedMatrix=function(a){for(var b=this,c=this.getMatrix(a);b=b.parent;)c.prependMatrix(b.getMatrix(b._props.matrix));return c},b.getConcatenatedDisplayProps=function(a){a=a?a.identity():new createjs.DisplayProps;var b=this,c=b.getMatrix(a.matrix);do a.prepend(b.visible,b.alpha,b.shadow,b.compositeOperation),b!=this&&c.prependMatrix(b.getMatrix(b._props.matrix));while(b=b.parent);return a},b.hitTest=function(b,c){var d=a._hitTestContext;d.setTransform(1,0,0,1,-b,-c),this.draw(d);var e=this._testHit(d);return d.setTransform(1,0,0,1,0,0),d.clearRect(0,0,2,2),e},b.set=function(a){for(var b in a)this[b]=a[b];return this},b.getBounds=function(){if(this._bounds)return this._rectangle.copy(this._bounds);var a=this.cacheCanvas;if(a){var b=this._cacheScale;return this._rectangle.setValues(this._cacheOffsetX,this._cacheOffsetY,a.width/b,a.height/b)}return null},b.getTransformedBounds=function(){return this._getBounds()},b.setBounds=function(a,b,c,d){return null==a?void(this._bounds=a):void(this._bounds=(this._bounds||new createjs.Rectangle).setValues(a,b,c,d))},b.clone=function(){return this._cloneProps(new a)},b.toString=function(){return"[DisplayObject (name="+this.name+")]"},b._updateState=null,b._cloneProps=function(a){return a.alpha=this.alpha,a.mouseEnabled=this.mouseEnabled,a.tickEnabled=this.tickEnabled,a.name=this.name,a.regX=this.regX,a.regY=this.regY,a.rotation=this.rotation,a.scaleX=this.scaleX,a.scaleY=this.scaleY,a.shadow=this.shadow,a.skewX=this.skewX,a.skewY=this.skewY,a.visible=this.visible,a.x=this.x,a.y=this.y,a.compositeOperation=this.compositeOperation,a.snapToPixel=this.snapToPixel,a.filters=null==this.filters?null:this.filters.slice(0),a.mask=this.mask,a.hitArea=this.hitArea,a.cursor=this.cursor,a._bounds=this._bounds,a},b._applyShadow=function(a,b){b=b||Shadow.identity,a.shadowColor=b.color,a.shadowOffsetX=b.offsetX,a.shadowOffsetY=b.offsetY,a.shadowBlur=b.blur},b._tick=function(a){var b=this._listeners;b&&b.tick&&(a.target=null,a.propagationStopped=a.immediatePropagationStopped=!1,this.dispatchEvent(a))},b._testHit=function(b){try{var c=b.getImageData(0,0,1,1).data[3]>1}catch(d){if(!a.suppressCrossDomainErrors)throw"An error has occurred. This is most likely due to security restrictions on reading canvas pixel data with local or cross-domain images."}return c},b._getBounds=function(a,b){return this._transformBounds(this.getBounds(),a,b)},b._transformBounds=function(a,b,c){if(!a)return a;var d=a.x,e=a.y,f=a.width,g=a.height,h=this._props.matrix;h=c?h.identity():this.getMatrix(h),(d||e)&&h.appendTransform(0,0,1,1,0,0,0,-d,-e),b&&h.prependMatrix(b);var i=f*h.a,j=f*h.b,k=g*h.c,l=g*h.d,m=h.tx,n=h.ty,o=m,p=m,q=n,r=n;return(d=i+m)p&&(p=d),(d=i+k+m)p&&(p=d),(d=k+m)p&&(p=d),(e=j+n)r&&(r=e),(e=j+l+n)r&&(r=e),(e=l+n)r&&(r=e),a.setValues(o,q,p-o,r-q)},b._hasMouseEventListener=function(){for(var b=a._MOUSE_EVENTS,c=0,d=b.length;d>c;c++)if(this.hasEventListener(b[c]))return!0;return!!this.cursor},createjs.DisplayObject=createjs.promote(a,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function a(){this.DisplayObject_constructor(),this.children=[],this.mouseChildren=!0,this.tickChildren=!0}var b=createjs.extend(a,createjs.DisplayObject);b._getNumChildren=function(){return this.children.length},b.getNumChildren=createjs.deprecate(b._getNumChildren,"Container.getNumChildren");try{Object.defineProperties(b,{numChildren:{get:b._getNumChildren}})}catch(c){}b.initialize=a,b.isVisible=function(){var a=this.cacheCanvas||this.children.length;return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&a)},b.draw=function(a,b){if(this.DisplayObject_draw(a,b))return!0;for(var c=this.children.slice(),d=0,e=c.length;e>d;d++){var f=c[d];f.isVisible()&&(a.save(),f.updateContext(a),f.draw(a),a.restore())}return!0},b.addChild=function(a){if(null==a)return a;var b=arguments.length;if(b>1){for(var c=0;b>c;c++)this.addChild(arguments[c]);return arguments[b-1]}var d=a.parent,e=d===this;return d&&d._removeChildAt(createjs.indexOf(d.children,a),e),a.parent=this,this.children.push(a),e||a.dispatchEvent("added"),a},b.addChildAt=function(a,b){var c=arguments.length,d=arguments[c-1];if(0>d||d>this.children.length)return arguments[c-2];if(c>2){for(var e=0;c-1>e;e++)this.addChildAt(arguments[e],d+e);return arguments[c-2]}var f=a.parent,g=f===this;return f&&f._removeChildAt(createjs.indexOf(f.children,a),g),a.parent=this,this.children.splice(b,0,a),g||a.dispatchEvent("added"),a},b.removeChild=function(a){var b=arguments.length;if(b>1){for(var c=!0,d=0;b>d;d++)c=c&&this.removeChild(arguments[d]);return c}return this._removeChildAt(createjs.indexOf(this.children,a))},b.removeChildAt=function(a){var b=arguments.length;if(b>1){for(var c=[],d=0;b>d;d++)c[d]=arguments[d];c.sort(function(a,b){return b-a});for(var e=!0,d=0;b>d;d++)e=e&&this._removeChildAt(c[d]);return e}return this._removeChildAt(a)},b.removeAllChildren=function(){for(var a=this.children;a.length;)this._removeChildAt(0)},b.getChildAt=function(a){return this.children[a]},b.getChildByName=function(a){for(var b=this.children,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},b.sortChildren=function(a){this.children.sort(a)},b.getChildIndex=function(a){return createjs.indexOf(this.children,a)},b.swapChildrenAt=function(a,b){var c=this.children,d=c[a],e=c[b];d&&e&&(c[a]=e,c[b]=d)},b.swapChildren=function(a,b){for(var c,d,e=this.children,f=0,g=e.length;g>f&&(e[f]==a&&(c=f),e[f]==b&&(d=f),null==c||null==d);f++);f!=g&&(e[c]=b,e[d]=a)},b.setChildIndex=function(a,b){var c=this.children,d=c.length;if(!(a.parent!=this||0>b||b>=d)){for(var e=0;d>e&&c[e]!=a;e++);e!=d&&e!=b&&(c.splice(e,1),c.splice(b,0,a))}},b.contains=function(a){for(;a;){if(a==this)return!0;a=a.parent}return!1},b.hitTest=function(a,b){return null!=this.getObjectUnderPoint(a,b)},b.getObjectsUnderPoint=function(a,b,c){var d=[],e=this.localToGlobal(a,b);return this._getObjectsUnderPoint(e.x,e.y,d,c>0,1==c),d},b.getObjectUnderPoint=function(a,b,c){var d=this.localToGlobal(a,b);return this._getObjectsUnderPoint(d.x,d.y,null,c>0,1==c)},b.getBounds=function(){return this._getBounds(null,!0)},b.getTransformedBounds=function(){return this._getBounds()},b.clone=function(b){var c=this._cloneProps(new a);return b&&this._cloneChildren(c),c},b.toString=function(){return"[Container (name="+this.name+")]"},b._tick=function(a){if(this.tickChildren)for(var b=this.children.length-1;b>=0;b--){var c=this.children[b];c.tickEnabled&&c._tick&&c._tick(a)}this.DisplayObject__tick(a)},b._cloneChildren=function(a){a.children.length&&a.removeAllChildren();for(var b=a.children,c=0,d=this.children.length;d>c;c++){var e=this.children[c].clone(!0);e.parent=a,b.push(e)}},b._removeChildAt=function(a,b){if(0>a||a>this.children.length-1)return!1;var c=this.children[a];return c&&(c.parent=null),this.children.splice(a,1),b||c.dispatchEvent("removed"),!0},b._getObjectsUnderPoint=function(b,c,d,e,f,g){if(g=g||0,!g&&!this._testMask(this,b,c))return null;var h,i=createjs.DisplayObject._hitTestContext;f=f||e&&this._hasMouseEventListener();for(var j=this.children,k=j.length,l=k-1;l>=0;l--){var m=j[l],n=m.hitArea;if(m.visible&&(n||m.isVisible())&&(!e||m.mouseEnabled)&&(n||this._testMask(m,b,c)))if(!n&&m instanceof a){var o=m._getObjectsUnderPoint(b,c,d,e,f,g+1);if(!d&&o)return e&&!this.mouseChildren?this:o}else{if(e&&!f&&!m._hasMouseEventListener())continue;var p=m.getConcatenatedDisplayProps(m._props);if(h=p.matrix,n&&(h.appendMatrix(n.getMatrix(n._props.matrix)),p.alpha=n.alpha),i.globalAlpha=p.alpha,i.setTransform(h.a,h.b,h.c,h.d,h.tx-b,h.ty-c),(n||m).draw(i),!this._testHit(i))continue;if(i.setTransform(1,0,0,1,0,0),i.clearRect(0,0,2,2),!d)return e&&!this.mouseChildren?this:m;d.push(m)}}return null},b._testMask=function(a,b,c){var d=a.mask;if(!d||!d.graphics||d.graphics.isEmpty())return!0;var e=this._props.matrix,f=a.parent;e=f?f.getConcatenatedMatrix(e):e.identity(),e=d.getMatrix(d._props.matrix).prependMatrix(e);var g=createjs.DisplayObject._hitTestContext;return g.setTransform(e.a,e.b,e.c,e.d,e.tx-b,e.ty-c),d.graphics.drawAsPath(g),g.fillStyle="#000",g.fill(),this._testHit(g)?(g.setTransform(1,0,0,1,0,0),g.clearRect(0,0,2,2),!0):!1},b._getBounds=function(a,b){var c=this.DisplayObject_getBounds();if(c)return this._transformBounds(c,a,b);var d=this._props.matrix;d=b?d.identity():this.getMatrix(d),a&&d.prependMatrix(a);for(var e=this.children.length,f=null,g=0;e>g;g++){var h=this.children[g];h.visible&&(c=h._getBounds(d))&&(f?f.extend(c.x,c.y,c.width,c.height):f=c.clone())}return f},createjs.Container=createjs.promote(a,"DisplayObject")}(),this.createjs=this.createjs||{},function(){"use strict";function a(a){this.Container_constructor(),this.autoClear=!0,this.canvas="string"==typeof a?document.getElementById(a):a,this.mouseX=0,this.mouseY=0,this.drawRect=null,this.snapToPixelEnabled=!1,this.mouseInBounds=!1,this.tickOnUpdate=!0,this.mouseMoveOutside=!1,this.preventSelection=!0,this._pointerData={},this._pointerCount=0,this._primaryPointerID=null,this._mouseOverIntervalID=null,this._nextStage=null,this._prevStage=null,this.enableDOMEvents(!0)}var b=createjs.extend(a,createjs.Container);b._get_nextStage=function(){return this._nextStage},b._set_nextStage=function(a){this._nextStage&&(this._nextStage._prevStage=null),a&&(a._prevStage=this),this._nextStage=a};try{Object.defineProperties(b,{nextStage:{get:b._get_nextStage,set:b._set_nextStage}})}catch(c){}b.update=function(a){if(this.canvas&&(this.tickOnUpdate&&this.tick(a),this.dispatchEvent("drawstart",!1,!0)!==!1)){createjs.DisplayObject._snapToPixelEnabled=this.snapToPixelEnabled;var b=this.drawRect,c=this.canvas.getContext("2d");c.setTransform(1,0,0,1,0,0),this.autoClear&&(b?c.clearRect(b.x,b.y,b.width,b.height):c.clearRect(0,0,this.canvas.width+1,this.canvas.height+1)),c.save(),this.drawRect&&(c.beginPath(),c.rect(b.x,b.y,b.width,b.height),c.clip()),this.updateContext(c),this.draw(c,!1),c.restore(),this.dispatchEvent("drawend")}},b.tick=function(a){if(this.tickEnabled&&this.dispatchEvent("tickstart",!1,!0)!==!1){var b=new createjs.Event("tick");if(a)for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);this._tick(b),this.dispatchEvent("tickend")}},b.handleEvent=function(a){"tick"==a.type&&this.update(a)},b.clear=function(){if(this.canvas){var a=this.canvas.getContext("2d");a.setTransform(1,0,0,1,0,0),a.clearRect(0,0,this.canvas.width+1,this.canvas.height+1)}},b.toDataURL=function(a,b){var c,d=this.canvas.getContext("2d"),e=this.canvas.width,f=this.canvas.height;if(a){c=d.getImageData(0,0,e,f);var g=d.globalCompositeOperation;d.globalCompositeOperation="destination-over",d.fillStyle=a,d.fillRect(0,0,e,f)}var h=this.canvas.toDataURL(b||"image/png");return a&&(d.putImageData(c,0,0),d.globalCompositeOperation=g),h},b.enableMouseOver=function(a){if(this._mouseOverIntervalID&&(clearInterval(this._mouseOverIntervalID),this._mouseOverIntervalID=null,0==a&&this._testMouseOver(!0)),null==a)a=20;else if(0>=a)return;var b=this;this._mouseOverIntervalID=setInterval(function(){b._testMouseOver()},1e3/Math.min(50,a))},b.enableDOMEvents=function(a){null==a&&(a=!0);var b,c,d=this._eventListeners;if(!a&&d){for(b in d)c=d[b],c.t.removeEventListener(b,c.f,!1);this._eventListeners=null}else if(a&&!d&&this.canvas){var e=window.addEventListener?window:document,f=this;d=this._eventListeners={},d.mouseup={t:e,f:function(a){f._handleMouseUp(a)}},d.mousemove={t:e,f:function(a){f._handleMouseMove(a)}},d.dblclick={t:this.canvas,f:function(a){f._handleDoubleClick(a)}},d.mousedown={t:this.canvas,f:function(a){f._handleMouseDown(a)}};for(b in d)c=d[b],c.t.addEventListener(b,c.f,!1)}},b.clone=function(){throw"Stage cannot be cloned."},b.toString=function(){return"[Stage (name="+this.name+")]"},b._getElementRect=function(a){var b;try{b=a.getBoundingClientRect()}catch(c){b={top:a.offsetTop,left:a.offsetLeft,width:a.offsetWidth,height:a.offsetHeight}}var d=(window.pageXOffset||document.scrollLeft||0)-(document.clientLeft||document.body.clientLeft||0),e=(window.pageYOffset||document.scrollTop||0)-(document.clientTop||document.body.clientTop||0),f=window.getComputedStyle?getComputedStyle(a,null):a.currentStyle,g=parseInt(f.paddingLeft)+parseInt(f.borderLeftWidth),h=parseInt(f.paddingTop)+parseInt(f.borderTopWidth),i=parseInt(f.paddingRight)+parseInt(f.borderRightWidth),j=parseInt(f.paddingBottom)+parseInt(f.borderBottomWidth);return{left:b.left+d+g,right:b.right+d-i,top:b.top+e+h,bottom:b.bottom+e-j}},b._getPointerData=function(a){var b=this._pointerData[a];return b||(b=this._pointerData[a]={x:0,y:0}),b},b._handleMouseMove=function(a){a||(a=window.event),this._handlePointerMove(-1,a,a.pageX,a.pageY)},b._handlePointerMove=function(a,b,c,d,e){if((!this._prevStage||void 0!==e)&&this.canvas){var f=this._nextStage,g=this._getPointerData(a),h=g.inBounds;this._updatePointerPosition(a,b,c,d),(h||g.inBounds||this.mouseMoveOutside)&&(-1===a&&g.inBounds==!h&&this._dispatchMouseEvent(this,h?"mouseleave":"mouseenter",!1,a,g,b),this._dispatchMouseEvent(this,"stagemousemove",!1,a,g,b),this._dispatchMouseEvent(g.target,"pressmove",!0,a,g,b)),f&&f._handlePointerMove(a,b,c,d,null)}},b._updatePointerPosition=function(a,b,c,d){var e=this._getElementRect(this.canvas);c-=e.left,d-=e.top;var f=this.canvas.width,g=this.canvas.height;c/=(e.right-e.left)/f,d/=(e.bottom-e.top)/g;var h=this._getPointerData(a);(h.inBounds=c>=0&&d>=0&&f-1>=c&&g-1>=d)?(h.x=c,h.y=d):this.mouseMoveOutside&&(h.x=0>c?0:c>f-1?f-1:c,h.y=0>d?0:d>g-1?g-1:d),h.posEvtObj=b,h.rawX=c,h.rawY=d,(a===this._primaryPointerID||-1===a)&&(this.mouseX=h.x,this.mouseY=h.y,this.mouseInBounds=h.inBounds)},b._handleMouseUp=function(a){this._handlePointerUp(-1,a,!1)},b._handlePointerUp=function(a,b,c,d){var e=this._nextStage,f=this._getPointerData(a);if(!this._prevStage||void 0!==d){var g=null,h=f.target;d||!h&&!e||(g=this._getObjectsUnderPoint(f.x,f.y,null,!0)),f.down&&(this._dispatchMouseEvent(this,"stagemouseup",!1,a,f,b,g),f.down=!1),g==h&&this._dispatchMouseEvent(h,"click",!0,a,f,b),this._dispatchMouseEvent(h,"pressup",!0,a,f,b),c?(a==this._primaryPointerID&&(this._primaryPointerID=null),delete this._pointerData[a]):f.target=null,e&&e._handlePointerUp(a,b,c,d||g&&this)}},b._handleMouseDown=function(a){this._handlePointerDown(-1,a,a.pageX,a.pageY)},b._handlePointerDown=function(a,b,c,d,e){this.preventSelection&&b.preventDefault(),(null==this._primaryPointerID||-1===a)&&(this._primaryPointerID=a),null!=d&&this._updatePointerPosition(a,b,c,d);var f=null,g=this._nextStage,h=this._getPointerData(a);e||(f=h.target=this._getObjectsUnderPoint(h.x,h.y,null,!0)),h.inBounds&&(this._dispatchMouseEvent(this,"stagemousedown",!1,a,h,b,f),h.down=!0),this._dispatchMouseEvent(f,"mousedown",!0,a,h,b),g&&g._handlePointerDown(a,b,c,d,e||f&&this)},b._testMouseOver=function(a,b,c){if(!this._prevStage||void 0!==b){var d=this._nextStage;if(!this._mouseOverIntervalID)return void(d&&d._testMouseOver(a,b,c));var e=this._getPointerData(-1);if(e&&(a||this.mouseX!=this._mouseOverX||this.mouseY!=this._mouseOverY||!this.mouseInBounds)){var f,g,h,i=e.posEvtObj,j=c||i&&i.target==this.canvas,k=null,l=-1,m="";!b&&(a||this.mouseInBounds&&j)&&(k=this._getObjectsUnderPoint(this.mouseX,this.mouseY,null,!0),this._mouseOverX=this.mouseX,this._mouseOverY=this.mouseY);var n=this._mouseOverTarget||[],o=n[n.length-1],p=this._mouseOverTarget=[];for(f=k;f;)p.unshift(f),m||(m=f.cursor),f=f.parent;for(this.canvas.style.cursor=m,!b&&c&&(c.canvas.style.cursor=m),g=0,h=p.length;h>g&&p[g]==n[g];g++)l=g;for(o!=k&&this._dispatchMouseEvent(o,"mouseout",!0,-1,e,i,k),g=n.length-1;g>l;g--)this._dispatchMouseEvent(n[g],"rollout",!1,-1,e,i,k);for(g=p.length-1;g>l;g--)this._dispatchMouseEvent(p[g],"rollover",!1,-1,e,i,o);o!=k&&this._dispatchMouseEvent(k,"mouseover",!0,-1,e,i,o),d&&d._testMouseOver(a,b||k&&this,c||j&&this)}}},b._handleDoubleClick=function(a,b){var c=null,d=this._nextStage,e=this._getPointerData(-1);b||(c=this._getObjectsUnderPoint(e.x,e.y,null,!0),this._dispatchMouseEvent(c,"dblclick",!0,-1,e,a)),d&&d._handleDoubleClick(a,b||c&&this)},b._dispatchMouseEvent=function(a,b,c,d,e,f,g){if(a&&(c||a.hasEventListener(b))){var h=new createjs.MouseEvent(b,c,!1,e.x,e.y,f,d,d===this._primaryPointerID||-1===d,e.rawX,e.rawY,g);a.dispatchEvent(h)}},createjs.Stage=createjs.promote(a,"Container")}(),this.createjs=this.createjs||{},function(){"use strict";function a(b,c){if(this.Stage_constructor(b),void 0!==c){if("object"!=typeof c)throw"Invalid options object";var d=c.premultiply,e=c.transparent,f=c.antialias,g=c.preserveBuffer,h=c.autoPurge}this.vocalDebug=!1,this._preserveBuffer=g||!1,this._antialias=f||!1,this._transparent=e||!1,this._premultiply=d||!1,this._autoPurge=void 0,this.autoPurge=h,this._viewportWidth=0,this._viewportHeight=0,this._projectionMatrix=null,this._webGLContext=null,this._clearColor={r:.5,g:.5,b:.5,a:0},this._maxCardsPerBatch=a.DEFAULT_MAX_BATCH_SIZE,this._activeShader=null,this._vertices=null,this._vertexPositionBuffer=null,this._uvs=null,this._uvPositionBuffer=null,this._indices=null,this._textureIndexBuffer=null,this._alphas=null,this._alphaBuffer=null,this._textureDictionary=[],this._textureIDs={},this._batchTextures=[],this._baseTextures=[],this._batchTextureCount=8,this._lastTextureInsert=-1,this._batchID=0,this._drawID=0,this._slotBlacklist=[],this._isDrawing=0,this._lastTrackedCanvas=0,this.isCacheControlled=!1,this._cacheContainer=new createjs.Container,this._initializeWebGL()}var b=createjs.extend(a,createjs.Stage);a.buildUVRects=function(a,b,c){if(!a||!a._frames)return null;void 0===b&&(b=-1),void 0===c&&(c=!1);for(var d=-1!=b&&c?b:0,e=-1!=b&&c?b+1:a._frames.length,f=d;e>f;f++){var g=a._frames[f];if(!(g.uvRect||g.image.width<=0||g.image.height<=0)){var h=g.rect;g.uvRect={t:h.y/g.image.height,l:h.x/g.image.width,b:(h.y+h.height)/g.image.height,r:(h.x+h.width)/g.image.width}}}return a._frames[-1!=b?b:0].uvRect||{t:0,l:0,b:1,r:1}},a.isWebGLActive=function(a){return a&&a instanceof WebGLRenderingContext&&"undefined"!=typeof WebGLRenderingContext},a.VERTEX_PROPERTY_COUNT=6,a.INDICIES_PER_CARD=6,a.DEFAULT_MAX_BATCH_SIZE=1e4,a.WEBGL_MAX_INDEX_NUM=Math.pow(2,16),a.UV_RECT={t:0,l:0,b:1,r:1};try{a.COVER_VERT=new Float32Array([-1,1,1,1,-1,-1,1,1,1,-1,-1,-1]),a.COVER_UV=new Float32Array([0,0,1,0,0,1,1,0,1,1,0,1]),a.COVER_UV_FLIP=new Float32Array([0,1,1,1,0,0,1,1,1,0,0,0])}catch(c){}a.REGULAR_VARYING_HEADER="precision mediump float;varying vec2 vTextureCoord;varying lowp float indexPicker;varying lowp float alphaValue;",a.REGULAR_VERTEX_HEADER=a.REGULAR_VARYING_HEADER+"attribute vec2 vertexPosition;attribute vec2 uvPosition;attribute lowp float textureIndex;attribute lowp float objectAlpha;uniform mat4 pMatrix;",a.REGULAR_FRAGMENT_HEADER=a.REGULAR_VARYING_HEADER+"uniform sampler2D uSampler[{{count}}];",a.REGULAR_VERTEX_BODY="void main(void) {gl_Position = vec4((vertexPosition.x * pMatrix[0][0]) + pMatrix[3][0],(vertexPosition.y * pMatrix[1][1]) + pMatrix[3][1],pMatrix[3][2],1.0);alphaValue = objectAlpha;indexPicker = textureIndex;vTextureCoord = uvPosition;}",a.REGULAR_FRAGMENT_BODY="void main(void) {vec4 color = vec4(1.0, 0.0, 0.0, 1.0);if (indexPicker <= 0.5) {color = texture2D(uSampler[0], vTextureCoord);{{alternates}}}{{fragColor}}}",a.REGULAR_FRAG_COLOR_NORMAL="gl_FragColor = vec4(color.rgb, color.a * alphaValue);",a.REGULAR_FRAG_COLOR_PREMULTIPLY="if(color.a > 0.0035) {gl_FragColor = vec4(color.rgb/color.a, color.a * alphaValue);} else {gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);}",a.PARTICLE_VERTEX_BODY=a.REGULAR_VERTEX_BODY,a.PARTICLE_FRAGMENT_BODY=a.REGULAR_FRAGMENT_BODY,a.COVER_VARYING_HEADER="precision mediump float;varying highp vec2 vRenderCoord;varying highp vec2 vTextureCoord;",a.COVER_VERTEX_HEADER=a.COVER_VARYING_HEADER+"attribute vec2 vertexPosition;attribute vec2 uvPosition;uniform float uUpright;",a.COVER_FRAGMENT_HEADER=a.COVER_VARYING_HEADER+"uniform sampler2D uSampler;",a.COVER_VERTEX_BODY="void main(void) {gl_Position = vec4(vertexPosition.x, vertexPosition.y, 0.0, 1.0);vRenderCoord = uvPosition;vTextureCoord = vec2(uvPosition.x, abs(uUpright - uvPosition.y));}",a.COVER_FRAGMENT_BODY="void main(void) {vec4 color = texture2D(uSampler, vRenderCoord);gl_FragColor = color;}",b._get_isWebGL=function(){return!!this._webGLContext},b._set_autoPurge=function(a){a=isNaN(a)?1200:a,-1!=a&&(a=10>a?10:a),this._autoPurge=a},b._get_autoPurge=function(){return Number(this._autoPurge)};try{Object.defineProperties(b,{isWebGL:{get:b._get_isWebGL},autoPurge:{get:b._get_autoPurge,set:b._set_autoPurge}})}catch(c){}b._initializeWebGL=function(){if(this.canvas){if(!this._webGLContext||this._webGLContext.canvas!==this.canvas){var a={depth:!1,alpha:this._transparent,stencil:!0,antialias:this._antialias,premultipliedAlpha:this._premultiply,preserveDrawingBuffer:this._preserveBuffer},b=this._webGLContext=this._fetchWebGLContext(this.canvas,a);if(!b)return null;this.updateSimultaneousTextureCount(b.getParameter(b.MAX_TEXTURE_IMAGE_UNITS)),this._maxTextureSlots=b.getParameter(b.MAX_COMBINED_TEXTURE_IMAGE_UNITS),this._createBuffers(b),this._initTextures(b),b.disable(b.DEPTH_TEST),b.enable(b.BLEND),b.blendFuncSeparate(b.SRC_ALPHA,b.ONE_MINUS_SRC_ALPHA,b.ONE,b.ONE_MINUS_SRC_ALPHA),b.pixelStorei(b.UNPACK_PREMULTIPLY_ALPHA_WEBGL,this._premultiply),this._webGLContext.clearColor(this._clearColor.r,this._clearColor.g,this._clearColor.b,this._clearColor.a),this.updateViewport(this._viewportWidth||this.canvas.width,this._viewportHeight||this.canvas.height)}}else this._webGLContext=null;return this._webGLContext},b.update=function(a){if(this.canvas){if(this.tickOnUpdate&&this.tick(a),this.dispatchEvent("drawstart"),this.autoClear&&this.clear(),this._webGLContext)this._batchDraw(this,this._webGLContext),-1==this._autoPurge||this._drawID%(this._autoPurge/2|0)||this.purgeTextures(this._autoPurge);else{var b=this.canvas.getContext("2d");b.save(),this.updateContext(b),this.draw(b,!1),b.restore()}this.dispatchEvent("drawend")}},b.clear=function(){if(this.canvas)if(a.isWebGLActive(this._webGLContext)){var b=this._webGLContext,c=this._clearColor,d=this._transparent?c.a:1;this._webGLContext.clearColor(c.r*d,c.g*d,c.b*d,d),b.clear(b.COLOR_BUFFER_BIT),this._webGLContext.clearColor(c.r,c.g,c.b,c.a)}else this.Stage_clear()},b.draw=function(b,c){if(b===this._webGLContext&&a.isWebGLActive(this._webGLContext)){var d=this._webGLContext;return this._batchDraw(this,d,c),!0}return this.Stage_draw(b,c)},b.cacheDraw=function(b,c,d){if(a.isWebGLActive(this._webGLContext)){var e=this._webGLContext;return this._cacheDraw(e,b,c,d),!0}return!1},b.protectTextureSlot=function(a,b){if(a>this._maxTextureSlots||0>a)throw"Slot outside of acceptable range";this._slotBlacklist[a]=!!b},b.getTargetRenderTexture=function(a,b,c){var d,e=!1,f=this._webGLContext;if(void 0!==a.__lastRT&&a.__lastRT===a.__rtA&&(e=!0),e?(void 0===a.__rtB?a.__rtB=this.getRenderBufferTexture(b,c):((b!=a.__rtB._width||c!=a.__rtB._height)&&this.resizeTexture(a.__rtB,b,c),this.setTextureParams(f)),d=a.__rtB):(void 0===a.__rtA?a.__rtA=this.getRenderBufferTexture(b,c):((b!=a.__rtA._width||c!=a.__rtA._height)&&this.resizeTexture(a.__rtA,b,c),this.setTextureParams(f)),d=a.__rtA),!d)throw"Problems creating render textures, known causes include using too much VRAM by not releasing WebGL texture instances";return a.__lastRT=d,d},b.releaseTexture=function(a){var b,c;if(a){if(a.children)for(b=0,c=a.children.length;c>b;b++)this.releaseTexture(a.children[b]);a.cacheCanvas&&a.uncache();var d=void 0;if(void 0!==a._storeID){if(a===this._textureDictionary[a._storeID])return this._killTextureObject(a),void(a._storeID=void 0);d=a}else if(2===a._webGLRenderStyle)d=a.image;else if(1===a._webGLRenderStyle){for(b=0,c=a.spriteSheet._images.length;c>b;b++)this.releaseTexture(a.spriteSheet._images[b]);return}if(void 0===d)return void(this.vocalDebug&&console.log("No associated texture found on release"));this._killTextureObject(this._textureDictionary[d._storeID]),d._storeID=void 0}},b.purgeTextures=function(a){void 0==a&&(a=100);for(var b=this._textureDictionary,c=b.length,d=0;c>d;d++){var e=b[d];e&&e._drawID+a<=this._drawID&&this._killTextureObject(e)}},b.updateSimultaneousTextureCount=function(a){var b=this._webGLContext,c=!1;for((1>a||isNaN(a))&&(a=1),this._batchTextureCount=a;!c;)try{this._activeShader=this._fetchShaderProgram(b),c=!0}catch(d){if(1==this._batchTextureCount)throw"Cannot compile shader "+d;this._batchTextureCount-=4,this._batchTextureCount<1&&(this._batchTextureCount=1),this.vocalDebug&&console.log("Reducing desired texture count due to errors: "+this._batchTextureCount)}},b.updateViewport=function(a,b){this._viewportWidth=0|a,this._viewportHeight=0|b;var c=this._webGLContext;c&&(c.viewport(0,0,this._viewportWidth,this._viewportHeight),this._projectionMatrix=new Float32Array([2/this._viewportWidth,0,0,0,0,-2/this._viewportHeight,1,0,0,0,1,0,-1,1,.1,0]),this._projectionMatrixFlip=new Float32Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),this._projectionMatrixFlip.set(this._projectionMatrix),this._projectionMatrixFlip[5]*=-1,this._projectionMatrixFlip[13]*=-1)},b.getFilterShader=function(a){a||(a=this);var b=this._webGLContext,c=this._activeShader;if(a._builtShader)c=a._builtShader,a.shaderParamSetup&&(b.useProgram(c),a.shaderParamSetup(b,this,c));else try{c=this._fetchShaderProgram(b,"filter",a.VTX_SHADER_BODY,a.FRAG_SHADER_BODY,a.shaderParamSetup&&a.shaderParamSetup.bind(a)),a._builtShader=c,c._name=a.toString()}catch(d){console&&console.log("SHADER SWITCH FAILURE",d)}return c},b.getBaseTexture=function(a,b){var c=Math.ceil(a>0?a:1)||1,d=Math.ceil(b>0?b:1)||1,e=this._webGLContext,f=e.createTexture();return this.resizeTexture(f,c,d),this.setTextureParams(e,!1),f},b.resizeTexture=function(a,b,c){var d=this._webGLContext;d.bindTexture(d.TEXTURE_2D,a),d.texImage2D(d.TEXTURE_2D,0,d.RGBA,b,c,0,d.RGBA,d.UNSIGNED_BYTE,null),a.width=b,a.height=c},b.getRenderBufferTexture=function(a,b){var c=this._webGLContext,d=this.getBaseTexture(a,b);if(!d)return null;var e=c.createFramebuffer();return e?(d.width=a,d.height=b,c.bindFramebuffer(c.FRAMEBUFFER,e),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,d,0),e._renderTexture=d,d._frameBuffer=e,d._storeID=this._textureDictionary.length,this._textureDictionary[d._storeID]=d,c.bindFramebuffer(c.FRAMEBUFFER,null),d):null},b.setTextureParams=function(a,b){b&&this._antialias?(a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR)):(a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.NEAREST),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.NEAREST)),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE)},b.setClearColor=function(a){var b,c,d,e,f;"string"==typeof a?0==a.indexOf("#")?(4==a.length&&(a="#"+a.charAt(1)+a.charAt(1)+a.charAt(2)+a.charAt(2)+a.charAt(3)+a.charAt(3)),b=Number("0x"+a.slice(1,3))/255,c=Number("0x"+a.slice(3,5))/255,d=Number("0x"+a.slice(5,7))/255,e=Number("0x"+a.slice(7,9))/255):0==a.indexOf("rgba(")&&(f=a.slice(5,-1).split(","),b=Number(f[0])/255,c=Number(f[1])/255,d=Number(f[2])/255,e=Number(f[3])):(b=((4278190080&a)>>>24)/255,c=((16711680&a)>>>16)/255,d=((65280&a)>>>8)/255,e=(255&a)/255),this._clearColor.r=b||0,this._clearColor.g=c||0,this._clearColor.b=d||0,this._clearColor.a=e||0,this._webGLContext&&this._webGLContext.clearColor(this._clearColor.r,this._clearColor.g,this._clearColor.b,this._clearColor.a)},b.toString=function(){return"[StageGL (name="+this.name+")]" +},b._fetchWebGLContext=function(a,b){var c;try{c=a.getContext("webgl",b)||a.getContext("experimental-webgl",b)}catch(d){}if(c)c.viewportWidth=a.width,c.viewportHeight=a.height;else{var e="Could not initialize WebGL";console.error?console.error(e):console.log(e)}return c},b._fetchShaderProgram=function(b,c,d,e,f){b.useProgram(null);var g,h;switch(c){case"filter":h=a.COVER_VERTEX_HEADER+(d||a.COVER_VERTEX_BODY),g=a.COVER_FRAGMENT_HEADER+(e||a.COVER_FRAGMENT_BODY);break;case"particle":h=a.REGULAR_VERTEX_HEADER+a.PARTICLE_VERTEX_BODY,g=a.REGULAR_FRAGMENT_HEADER+a.PARTICLE_FRAGMENT_BODY;break;case"override":h=a.REGULAR_VERTEX_HEADER+(d||a.REGULAR_VERTEX_BODY),g=a.REGULAR_FRAGMENT_HEADER+(e||a.REGULAR_FRAGMENT_BODY);break;case"regular":default:h=a.REGULAR_VERTEX_HEADER+a.REGULAR_VERTEX_BODY,g=a.REGULAR_FRAGMENT_HEADER+a.REGULAR_FRAGMENT_BODY}var i=this._createShader(b,b.VERTEX_SHADER,h),j=this._createShader(b,b.FRAGMENT_SHADER,g),k=b.createProgram();if(b.attachShader(k,i),b.attachShader(k,j),b.linkProgram(k),k._type=c,!b.getProgramParameter(k,b.LINK_STATUS))throw b.useProgram(this._activeShader),b.getProgramInfoLog(k);switch(b.useProgram(k),c){case"filter":k.vertexPositionAttribute=b.getAttribLocation(k,"vertexPosition"),b.enableVertexAttribArray(k.vertexPositionAttribute),k.uvPositionAttribute=b.getAttribLocation(k,"uvPosition"),b.enableVertexAttribArray(k.uvPositionAttribute),k.samplerUniform=b.getUniformLocation(k,"uSampler"),b.uniform1i(k.samplerUniform,0),k.uprightUniform=b.getUniformLocation(k,"uUpright"),b.uniform1f(k.uprightUniform,0),f&&f(b,this,k);break;case"override":case"particle":case"regular":default:k.vertexPositionAttribute=b.getAttribLocation(k,"vertexPosition"),b.enableVertexAttribArray(k.vertexPositionAttribute),k.uvPositionAttribute=b.getAttribLocation(k,"uvPosition"),b.enableVertexAttribArray(k.uvPositionAttribute),k.textureIndexAttribute=b.getAttribLocation(k,"textureIndex"),b.enableVertexAttribArray(k.textureIndexAttribute),k.alphaAttribute=b.getAttribLocation(k,"objectAlpha"),b.enableVertexAttribArray(k.alphaAttribute);for(var l=[],m=0;md;d+=c)h[d]=h[d+1]=0;b.bufferData(b.ARRAY_BUFFER,h,b.DYNAMIC_DRAW),g.itemSize=c,g.numItems=f;var i=this._uvPositionBuffer=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,i),c=2;var j=this._uvs=new Float32Array(f*c);for(d=0,e=j.length;e>d;d+=c)j[d]=j[d+1]=0;b.bufferData(b.ARRAY_BUFFER,j,b.DYNAMIC_DRAW),i.itemSize=c,i.numItems=f;var k=this._textureIndexBuffer=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,k),c=1;var l=this._indices=new Float32Array(f*c);for(d=0,e=l.length;e>d;d++)l[d]=0;b.bufferData(b.ARRAY_BUFFER,l,b.DYNAMIC_DRAW),k.itemSize=c,k.numItems=f;var m=this._alphaBuffer=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,m),c=1;var n=this._alphas=new Float32Array(f*c);for(d=0,e=n.length;e>d;d++)n[d]=1;b.bufferData(b.ARRAY_BUFFER,n,b.DYNAMIC_DRAW),m.itemSize=c,m.numItems=f},b._initTextures=function(){this._lastTextureInsert=-1,this._textureDictionary=[],this._textureIDs={},this._baseTextures=[],this._batchTextures=[];for(var a=0;aa.MAX_TEXTURE_SIZE||b.height>a.MAX_TEXTURE_SIZE)&&console&&console.error("Oversized Texture: "+b.width+"x"+b.height+" vs "+a.MAX_TEXTURE_SIZE+"max"))},b._insertTextureInBatch=function(a,b){if(this._batchTextures[b._activeIndex]!==b){var c=-1,d=(this._lastTextureInsert+1)%this._batchTextureCount,e=d;do{if(this._batchTextures[e]._batchID!=this._batchID&&!this._slotBlacklist[e]){c=e;break}e=(e+1)%this._batchTextureCount}while(e!==d);-1===c&&(this.batchReason="textureOverflow",this._drawBuffers(a),this.batchCardCount=0,c=d),this._batchTextures[c]=b,b._activeIndex=c;var f=b._imageData;f&&f._invalid&&void 0!==b._drawID?this._updateTextureImageData(a,f):(a.activeTexture(a.TEXTURE0+c),a.bindTexture(a.TEXTURE_2D,b),this.setTextureParams(a)),this._lastTextureInsert=c}else{var f=b._imageData;void 0!=b._storeID&&f&&f._invalid&&this._updateTextureImageData(a,f)}b._drawID=this._drawID,b._batchID=this._batchID},b._killTextureObject=function(a){if(a){var b=this._webGLContext;if(void 0!==a._storeID&&a._storeID>=0){this._textureDictionary[a._storeID]=void 0;for(var c in this._textureIDs)this._textureIDs[c]==a._storeID&&delete this._textureIDs[c];a._imageData&&(a._imageData._storeID=void 0),a._imageData=a._storeID=void 0}void 0!==a._activeIndex&&this._batchTextures[a._activeIndex]===a&&(this._batchTextures[a._activeIndex]=this._baseTextures[a._activeIndex]);try{a._frameBuffer&&b.deleteFramebuffer(a._frameBuffer),a._frameBuffer=void 0}catch(d){this.vocalDebug&&console.log(d)}try{b.deleteTexture(a)}catch(d){this.vocalDebug&&console.log(d)}}},b._backupBatchTextures=function(a,b){var c=this._webGLContext;this._backupTextures||(this._backupTextures=[]),void 0===b&&(b=this._backupTextures);for(var d=0;d0&&this._drawBuffers(b),this._isDrawing++,this._drawID++,this.batchCardCount=0,this.depth=0,this._appendToBatchGroup(a,b,new createjs.Matrix2D,this.alpha,c),this.batchReason="drawFinish",this._drawBuffers(b),this._isDrawing--},b._cacheDraw=function(a,b,c,d){var e,f=this._activeShader,g=this._slotBlacklist,h=this._maxTextureSlots-1,i=this._viewportWidth,j=this._viewportHeight;this.protectTextureSlot(h,!0);var k=b.getMatrix();k=k.clone(),k.scale(1/d.scale,1/d.scale),k=k.invert(),k.translate(-d.offX/d.scale*b.scaleX,-d.offY/d.scale*b.scaleY);var l=this._cacheContainer;l.children=[b],l.transformMatrix=k,this._backupBatchTextures(!1),c&&c.length?this._drawFilters(b,c,d):this.isCacheControlled?(a.clear(a.COLOR_BUFFER_BIT),this._batchDraw(l,a,!0)):(a.activeTexture(a.TEXTURE0+h),b.cacheCanvas=this.getTargetRenderTexture(b,d._drawWidth,d._drawHeight),e=b.cacheCanvas,a.bindFramebuffer(a.FRAMEBUFFER,e._frameBuffer),this.updateViewport(d._drawWidth,d._drawHeight),this._projectionMatrix=this._projectionMatrixFlip,a.clear(a.COLOR_BUFFER_BIT),this._batchDraw(l,a,!0),a.bindFramebuffer(a.FRAMEBUFFER,null),this.updateViewport(i,j)),this._backupBatchTextures(!0),this.protectTextureSlot(h,!1),this._activeShader=f,this._slotBlacklist=g},b._drawFilters=function(a,b,c){var d,e=this._webGLContext,f=this._maxTextureSlots-1,g=this._viewportWidth,h=this._viewportHeight,i=this._cacheContainer,j=b.length;e.activeTexture(e.TEXTURE0+f),d=this.getTargetRenderTexture(a,c._drawWidth,c._drawHeight),e.bindFramebuffer(e.FRAMEBUFFER,d._frameBuffer),this.updateViewport(c._drawWidth,c._drawHeight),e.clear(e.COLOR_BUFFER_BIT),this._batchDraw(i,e,!0),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,d),this.setTextureParams(e);var k=!1,l=0,m=b[l];do this._activeShader=this.getFilterShader(m),this._activeShader&&(e.activeTexture(e.TEXTURE0+f),d=this.getTargetRenderTexture(a,c._drawWidth,c._drawHeight),e.bindFramebuffer(e.FRAMEBUFFER,d._frameBuffer),e.viewport(0,0,c._drawWidth,c._drawHeight),e.clear(e.COLOR_BUFFER_BIT),this._drawCover(e,k),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,d),this.setTextureParams(e),(j>1||b[0]._multiPass)&&(k=!k),m=null!==m._multiPass?m._multiPass:b[++l]);while(m);this.isCacheControlled?(e.bindFramebuffer(e.FRAMEBUFFER,null),this.updateViewport(g,h),this._activeShader=this.getFilterShader(this),e.clear(e.COLOR_BUFFER_BIT),this._drawCover(e,k)):(k&&(e.activeTexture(e.TEXTURE0+f),d=this.getTargetRenderTexture(a,c._drawWidth,c._drawHeight),e.bindFramebuffer(e.FRAMEBUFFER,d._frameBuffer),this._activeShader=this.getFilterShader(this),e.viewport(0,0,c._drawWidth,c._drawHeight),e.clear(e.COLOR_BUFFER_BIT),this._drawCover(e,!k)),e.bindFramebuffer(e.FRAMEBUFFER,null),this.updateViewport(g,h),a.cacheCanvas=d)},b._appendToBatchGroup=function(b,c,d,e,f){b._glMtx||(b._glMtx=new createjs.Matrix2D);var g=b._glMtx;g.copy(d),b.transformMatrix?g.appendMatrix(b.transformMatrix):g.appendTransform(b.x,b.y,b.scaleX,b.scaleY,b.rotation,b.skewX,b.skewY,b.regX,b.regY);for(var h,i,j,k,l=b.children.length,m=0;l>m;m++){var n=b.children[m];if(n.visible&&e)if(n.cacheCanvas&&!f||(n._updateState&&n._updateState(),!n.children)){this.batchCardCount+1>this._maxCardsPerBatch&&(this.batchReason="vertexOverflow",this._drawBuffers(c),this.batchCardCount=0),n._glMtx||(n._glMtx=new createjs.Matrix2D);var o=n._glMtx;o.copy(g),n.transformMatrix?o.appendMatrix(n.transformMatrix):o.appendTransform(n.x,n.y,n.scaleX,n.scaleY,n.rotation,n.skewX,n.skewY,n.regX,n.regY);var p,q,r,s,t,u,v=n.cacheCanvas&&!f;if(2===n._webGLRenderStyle||v)r=(f?!1:n.cacheCanvas)||n.image;else{if(1!==n._webGLRenderStyle)continue;if(s=n.spriteSheet.getFrame(n.currentFrame),null===s)continue;r=s.image}var w=this._uvs,x=this._vertices,y=this._indices,z=this._alphas;if(r){if(void 0===r._storeID)t=this._loadTextureImage(c,r),this._insertTextureInBatch(c,t);else{if(t=this._textureDictionary[r._storeID],!t){this.vocalDebug&&console.log("Texture should not be looked up while not being stored.");continue}t._batchID!==this._batchID&&this._insertTextureInBatch(c,t)}if(q=t._activeIndex,2===n._webGLRenderStyle||v)!v&&n.sourceRect?(n._uvRect||(n._uvRect={}),u=n.sourceRect,p=n._uvRect,p.t=u.y/r.height,p.l=u.x/r.width,p.b=(u.y+u.height)/r.height,p.r=(u.x+u.width)/r.width,h=0,i=0,j=u.width+h,k=u.height+i):(p=a.UV_RECT,v?(u=n.bitmapCache,h=u.x+u._filterOffX/u.scale,i=u.y+u._filterOffY/u.scale,j=u._drawWidth/u.scale+h,k=u._drawHeight/u.scale+i):(h=0,i=0,j=r.width+h,k=r.height+i));else if(1===n._webGLRenderStyle){var A=s.rect;p=s.uvRect,p||(p=a.buildUVRects(n.spriteSheet,n.currentFrame,!1)),h=-s.regX,i=-s.regY,j=A.width-s.regX,k=A.height-s.regY}var B=this.batchCardCount*a.INDICIES_PER_CARD,C=2*B;x[C]=h*o.a+i*o.c+o.tx,x[C+1]=h*o.b+i*o.d+o.ty,x[C+2]=h*o.a+k*o.c+o.tx,x[C+3]=h*o.b+k*o.d+o.ty,x[C+4]=j*o.a+i*o.c+o.tx,x[C+5]=j*o.b+i*o.d+o.ty,x[C+6]=x[C+2],x[C+7]=x[C+3],x[C+8]=x[C+4],x[C+9]=x[C+5],x[C+10]=j*o.a+k*o.c+o.tx,x[C+11]=j*o.b+k*o.d+o.ty,w[C]=p.l,w[C+1]=p.t,w[C+2]=p.l,w[C+3]=p.b,w[C+4]=p.r,w[C+5]=p.t,w[C+6]=p.l,w[C+7]=p.b,w[C+8]=p.r,w[C+9]=p.t,w[C+10]=p.r,w[C+11]=p.b,y[B]=y[B+1]=y[B+2]=y[B+3]=y[B+4]=y[B+5]=q,z[B]=z[B+1]=z[B+2]=z[B+3]=z[B+4]=z[B+5]=n.alpha*e,this.batchCardCount++}}else this._appendToBatchGroup(n,c,g,n.alpha*e)}},b._drawBuffers=function(b){if(!(this.batchCardCount<=0)){this.vocalDebug&&console.log("Draw["+this._drawID+":"+this._batchID+"] : "+this.batchReason);var c=this._activeShader,d=this._vertexPositionBuffer,e=this._textureIndexBuffer,f=this._uvPositionBuffer,g=this._alphaBuffer;b.useProgram(c),b.bindBuffer(b.ARRAY_BUFFER,d),b.vertexAttribPointer(c.vertexPositionAttribute,d.itemSize,b.FLOAT,!1,0,0),b.bufferSubData(b.ARRAY_BUFFER,0,this._vertices),b.bindBuffer(b.ARRAY_BUFFER,e),b.vertexAttribPointer(c.textureIndexAttribute,e.itemSize,b.FLOAT,!1,0,0),b.bufferSubData(b.ARRAY_BUFFER,0,this._indices),b.bindBuffer(b.ARRAY_BUFFER,f),b.vertexAttribPointer(c.uvPositionAttribute,f.itemSize,b.FLOAT,!1,0,0),b.bufferSubData(b.ARRAY_BUFFER,0,this._uvs),b.bindBuffer(b.ARRAY_BUFFER,g),b.vertexAttribPointer(c.alphaAttribute,g.itemSize,b.FLOAT,!1,0,0),b.bufferSubData(b.ARRAY_BUFFER,0,this._alphas),b.uniformMatrix4fv(c.pMatrixUniform,b.FALSE,this._projectionMatrix);for(var h=0;h0&&this._drawBuffers(b),this.vocalDebug&&console.log("Draw["+this._drawID+":"+this._batchID+"] : Cover");var d=this._activeShader,e=this._vertexPositionBuffer,f=this._uvPositionBuffer;b.clear(b.COLOR_BUFFER_BIT),b.useProgram(d),b.bindBuffer(b.ARRAY_BUFFER,e),b.vertexAttribPointer(d.vertexPositionAttribute,e.itemSize,b.FLOAT,!1,0,0),b.bufferSubData(b.ARRAY_BUFFER,0,a.COVER_VERT),b.bindBuffer(b.ARRAY_BUFFER,f),b.vertexAttribPointer(d.uvPositionAttribute,f.itemSize,b.FLOAT,!1,0,0),b.bufferSubData(b.ARRAY_BUFFER,0,c?a.COVER_UV_FLIP:a.COVER_UV),b.uniform1i(d.samplerUniform,0),b.uniform1f(d.uprightUniform,c?0:1),b.drawArrays(b.TRIANGLES,0,a.INDICIES_PER_CARD)},createjs.StageGL=createjs.promote(a,"Stage")}(),this.createjs=this.createjs||{},function(){function a(a){this.DisplayObject_constructor(),"string"==typeof a?(this.image=document.createElement("img"),this.image.src=a):this.image=a,this.sourceRect=null,this._webGLRenderStyle=createjs.DisplayObject._StageGL_BITMAP}var b=createjs.extend(a,createjs.DisplayObject);b.initialize=a,b.isVisible=function(){var a=this.image,b=this.cacheCanvas||a&&(a.naturalWidth||a.getContext||a.readyState>=2);return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&b)},b.draw=function(a,b){if(this.DisplayObject_draw(a,b))return!0;var c=this.image,d=this.sourceRect;if(c.getImage&&(c=c.getImage()),!c)return!0;if(d){var e=d.x,f=d.y,g=e+d.width,h=f+d.height,i=0,j=0,k=c.width,l=c.height;0>e&&(i-=e,e=0),g>k&&(g=k),0>f&&(j-=f,f=0),h>l&&(h=l),a.drawImage(c,e,f,g-e,h-f,i,j,g-e,h-f)}else a.drawImage(c,0,0);return!0},b.getBounds=function(){var a=this.DisplayObject_getBounds();if(a)return a;var b=this.image,c=this.sourceRect||b,d=b&&(b.naturalWidth||b.getContext||b.readyState>=2);return d?this._rectangle.setValues(0,0,c.width,c.height):null},b.clone=function(b){var c=this.image;c&&b&&(c=c.cloneNode());var d=new a(c);return this.sourceRect&&(d.sourceRect=this.sourceRect.clone()),this._cloneProps(d),d},b.toString=function(){return"[Bitmap (name="+this.name+")]"},createjs.Bitmap=createjs.promote(a,"DisplayObject")}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b){this.DisplayObject_constructor(),this.currentFrame=0,this.currentAnimation=null,this.paused=!0,this.spriteSheet=a,this.currentAnimationFrame=0,this.framerate=0,this._animation=null,this._currentFrame=null,this._skipAdvance=!1,this._webGLRenderStyle=createjs.DisplayObject._StageGL_SPRITE,null!=b&&this.gotoAndPlay(b)}var b=createjs.extend(a,createjs.DisplayObject);b.initialize=a,b.isVisible=function(){var a=this.cacheCanvas||this.spriteSheet.complete;return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&a)},b.draw=function(a,b){if(this.DisplayObject_draw(a,b))return!0;this._normalizeFrame();var c=this.spriteSheet.getFrame(0|this._currentFrame);if(!c)return!1;var d=c.rect;return d.width&&d.height&&a.drawImage(c.image,d.x,d.y,d.width,d.height,-c.regX,-c.regY,d.width,d.height),!0},b.play=function(){this.paused=!1},b.stop=function(){this.paused=!0},b.gotoAndPlay=function(a){this.paused=!1,this._skipAdvance=!0,this._goto(a)},b.gotoAndStop=function(a){this.paused=!0,this._goto(a)},b.advance=function(a){var b=this.framerate||this.spriteSheet.framerate,c=b&&null!=a?a/(1e3/b):1;this._normalizeFrame(c)},b.getBounds=function(){return this.DisplayObject_getBounds()||this.spriteSheet.getFrameBounds(this.currentFrame,this._rectangle)},b.clone=function(){return this._cloneProps(new a(this.spriteSheet))},b.toString=function(){return"[Sprite (name="+this.name+")]"},b._cloneProps=function(a){return this.DisplayObject__cloneProps(a),a.currentFrame=this.currentFrame,a.currentAnimation=this.currentAnimation,a.paused=this.paused,a.currentAnimationFrame=this.currentAnimationFrame,a.framerate=this.framerate,a._animation=this._animation,a._currentFrame=this._currentFrame,a._skipAdvance=this._skipAdvance,a},b._tick=function(a){this.paused||(this._skipAdvance||this.advance(a&&a.delta),this._skipAdvance=!1),this.DisplayObject__tick(a)},b._normalizeFrame=function(a){a=a||0;var b,c=this._animation,d=this.paused,e=this._currentFrame;if(c){var f=c.speed||1,g=this.currentAnimationFrame;if(b=c.frames.length,g+a*f>=b){var h=c.next;if(this._dispatchAnimationEnd(c,e,d,h,b-1))return;if(h)return this._goto(h,a-(b-g)/f);this.paused=!0,g=c.frames.length-1}else g+=a*f;this.currentAnimationFrame=g,this._currentFrame=c.frames[0|g]}else if(e=this._currentFrame+=a,b=this.spriteSheet.getNumFrames(),e>=b&&b>0&&!this._dispatchAnimationEnd(c,e,d,b-1)&&(this._currentFrame-=b)>=b)return this._normalizeFrame();e=0|this._currentFrame,this.currentFrame!=e&&(this.currentFrame=e,this.dispatchEvent("change"))},b._dispatchAnimationEnd=function(a,b,c,d,e){var f=a?a.name:null;if(this.hasEventListener("animationend")){var g=new createjs.Event("animationend");g.name=f,g.next=d,this.dispatchEvent(g)}var h=this._animation!=a||this._currentFrame!=b;return h||c||!this.paused||(this.currentAnimationFrame=e,h=!0),h},b._goto=function(a,b){if(this.currentAnimationFrame=0,isNaN(a)){var c=this.spriteSheet.getAnimation(a);c&&(this._animation=c,this.currentAnimation=a,this._normalizeFrame(b))}else this.currentAnimation=this._animation=null,this._currentFrame=a,this._normalizeFrame()},createjs.Sprite=createjs.promote(a,"DisplayObject")}(),this.createjs=this.createjs||{},function(){"use strict";function a(a){this.DisplayObject_constructor(),this.graphics=a?a:new createjs.Graphics}var b=createjs.extend(a,createjs.DisplayObject);b.isVisible=function(){var a=this.cacheCanvas||this.graphics&&!this.graphics.isEmpty();return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&a)},b.draw=function(a,b){return this.DisplayObject_draw(a,b)?!0:(this.graphics.draw(a,this),!0)},b.clone=function(b){var c=b&&this.graphics?this.graphics.clone():this.graphics;return this._cloneProps(new a(c))},b.toString=function(){return"[Shape (name="+this.name+")]"},createjs.Shape=createjs.promote(a,"DisplayObject")}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c){this.DisplayObject_constructor(),this.text=a,this.font=b,this.color=c,this.textAlign="left",this.textBaseline="top",this.maxWidth=null,this.outline=0,this.lineHeight=0,this.lineWidth=null}var b=createjs.extend(a,createjs.DisplayObject),c=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");c.getContext&&(a._workingContext=c.getContext("2d"),c.width=c.height=1),a.H_OFFSETS={start:0,left:0,center:-.5,end:-1,right:-1},a.V_OFFSETS={top:0,hanging:-.01,middle:-.4,alphabetic:-.8,ideographic:-.85,bottom:-1},b.isVisible=function(){var a=this.cacheCanvas||null!=this.text&&""!==this.text;return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&a)},b.draw=function(a,b){if(this.DisplayObject_draw(a,b))return!0;var c=this.color||"#000";return this.outline?(a.strokeStyle=c,a.lineWidth=1*this.outline):a.fillStyle=c,this._drawText(this._prepContext(a)),!0},b.getMeasuredWidth=function(){return this._getMeasuredWidth(this.text)},b.getMeasuredLineHeight=function(){return 1.2*this._getMeasuredWidth("M")},b.getMeasuredHeight=function(){return this._drawText(null,{}).height},b.getBounds=function(){var b=this.DisplayObject_getBounds();if(b)return b;if(null==this.text||""===this.text)return null;var c=this._drawText(null,{}),d=this.maxWidth&&this.maxWidthj;j++){var l=i[j],m=null;if(null!=this.lineWidth&&(m=b.measureText(l).width)>this.lineWidth){var n=l.split(/(\s)/);l=n[0],m=b.measureText(l).width;for(var o=1,p=n.length;p>o;o+=2){var q=b.measureText(n[o]+n[o+1]).width;m+q>this.lineWidth?(e&&this._drawTextLine(b,l,h*f),d&&d.push(l),m>g&&(g=m),l=n[o+1],m=b.measureText(l).width,h++):(l+=n[o]+n[o+1],m+=q)}}e&&this._drawTextLine(b,l,h*f),d&&d.push(l),c&&null==m&&(m=b.measureText(l).width),m>g&&(g=m),h++}return c&&(c.width=g,c.height=h*f),e||b.restore(),c},b._drawTextLine=function(a,b,c){this.outline?a.strokeText(b,0,c,this.maxWidth||65535):a.fillText(b,0,c,this.maxWidth||65535)},b._getMeasuredWidth=function(b){var c=a._workingContext;c.save();var d=this._prepContext(c).measureText(b).width;return c.restore(),d},createjs.Text=createjs.promote(a,"DisplayObject")}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b){this.Container_constructor(),this.text=a||"",this.spriteSheet=b,this.lineHeight=0,this.letterSpacing=0,this.spaceWidth=0,this._oldProps={text:0,spriteSheet:0,lineHeight:0,letterSpacing:0,spaceWidth:0},this._oldStage=null,this._drawAction=null}var b=createjs.extend(a,createjs.Container);a.maxPoolSize=100,a._spritePool=[],b.draw=function(a,b){this.DisplayObject_draw(a,b)||(this._updateState(),this.Container_draw(a,b))},b.getBounds=function(){return this._updateText(),this.Container_getBounds()},b.isVisible=function(){var a=this.cacheCanvas||this.spriteSheet&&this.spriteSheet.complete&&this.text;return!!(this.visible&&this.alpha>0&&0!==this.scaleX&&0!==this.scaleY&&a)},b.clone=function(){return this._cloneProps(new a(this.text,this.spriteSheet))},b.addChild=b.addChildAt=b.removeChild=b.removeChildAt=b.removeAllChildren=function(){},b._updateState=function(){this._updateText()},b._cloneProps=function(a){return this.Container__cloneProps(a),a.lineHeight=this.lineHeight,a.letterSpacing=this.letterSpacing,a.spaceWidth=this.spaceWidth,a},b._getFrameIndex=function(a,b){var c,d=b.getAnimation(a);return d||(a!=(c=a.toUpperCase())||a!=(c=a.toLowerCase())||(c=null),c&&(d=b.getAnimation(c))),d&&d.frames[0]},b._getFrame=function(a,b){var c=this._getFrameIndex(a,b);return null==c?c:b.getFrame(c)},b._getLineHeight=function(a){var b=this._getFrame("1",a)||this._getFrame("T",a)||this._getFrame("L",a)||a.getFrame(0);return b?b.rect.height:1},b._getSpaceWidth=function(a){var b=this._getFrame("1",a)||this._getFrame("l",a)||this._getFrame("e",a)||this._getFrame("a",a)||a.getFrame(0);return b?b.rect.width:1},b._updateText=function(){var b,c=0,d=0,e=this._oldProps,f=!1,g=this.spaceWidth,h=this.lineHeight,i=this.spriteSheet,j=a._spritePool,k=this.children,l=0,m=k.length;for(var n in e)e[n]!=this[n]&&(e[n]=this[n],f=!0);if(f){var o=!!this._getFrame(" ",i);o||g||(g=this._getSpaceWidth(i)),h||(h=this._getLineHeight(i));for(var p=0,q=this.text.length;q>p;p++){var r=this.text.charAt(p);if(" "!=r||o)if("\n"!=r&&"\r"!=r){var s=this._getFrameIndex(r,i);null!=s&&(m>l?b=k[l]:(k.push(b=j.length?j.pop():new createjs.Sprite),b.parent=this,m++),b.spriteSheet=i,b.gotoAndStop(s),b.x=c,b.y=d,l++,c+=b.getBounds().width+this.letterSpacing)}else"\r"==r&&"\n"==this.text.charAt(p+1)&&p++,c=0,d+=h;else c+=g}for(;m>l;)j.push(b=k.pop()),b.parent=null,m--;j.length>a.maxPoolSize&&(j.length=a.maxPoolSize)}},createjs.BitmapText=createjs.promote(a,"Container")}(),this.createjs=this.createjs||{},function(){"use strict";function a(b){this.Container_constructor(),!a.inited&&a.init();var c,d,e,f;b instanceof String||arguments.length>1?(c=b,d=arguments[1],e=arguments[2],f=arguments[3],null==e&&(e=-1),b=null):b&&(c=b.mode,d=b.startPosition,e=b.loop,f=b.labels),b||(b={labels:f}),this.mode=c||a.INDEPENDENT,this.startPosition=d||0,this.loop=e===!0?-1:e||0,this.currentFrame=0,this.paused=b.paused||!1,this.actionsEnabled=!0,this.autoReset=!0,this.frameBounds=this.frameBounds||b.frameBounds,this.framerate=null,b.useTicks=b.paused=!0,this.timeline=new createjs.Timeline(b),this._synchOffset=0,this._rawPosition=-1,this._bound_resolveState=this._resolveState.bind(this),this._t=0,this._managed={}}function b(){throw"MovieClipPlugin cannot be instantiated."}var c=createjs.extend(a,createjs.Container);a.INDEPENDENT="independent",a.SINGLE_FRAME="single",a.SYNCHED="synched",a.inited=!1,a.init=function(){a.inited||(b.install(),a.inited=!0)},c._getLabels=function(){return this.timeline.getLabels()},c.getLabels=createjs.deprecate(c._getLabels,"MovieClip.getLabels"),c._getCurrentLabel=function(){return this.timeline.currentLabel},c.getCurrentLabel=createjs.deprecate(c._getCurrentLabel,"MovieClip.getCurrentLabel"),c._getDuration=function(){return this.timeline.duration},c.getDuration=createjs.deprecate(c._getDuration,"MovieClip.getDuration");try{Object.defineProperties(c,{labels:{get:c._getLabels},currentLabel:{get:c._getCurrentLabel},totalFrames:{get:c._getDuration},duration:{get:c._getDuration}})}catch(d){}c.initialize=a,c.isVisible=function(){return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY)},c.draw=function(a,b){return this.DisplayObject_draw(a,b)?!0:(this._updateState(),this.Container_draw(a,b),!0)},c.play=function(){this.paused=!1},c.stop=function(){this.paused=!0},c.gotoAndPlay=function(a){this.paused=!1,this._goto(a)},c.gotoAndStop=function(a){this.paused=!0,this._goto(a)},c.advance=function(b){var c=a.INDEPENDENT;if(this.mode===c){for(var d=this,e=d.framerate;(d=d.parent)&&null===e;)d.mode===c&&(e=d._framerate);if(this._framerate=e,!this.paused){var f=null!==e&&-1!==e&&null!==b?b/(1e3/e)+this._t:1,g=0|f;for(this._t=f-g;g--;)this._updateTimeline(this._rawPosition+1,!1)}}},c.clone=function(){throw"MovieClip cannot be cloned."},c.toString=function(){return"[MovieClip (name="+this.name+")]"},c._updateState=function(){(-1===this._rawPosition||this.mode!==a.INDEPENDENT)&&this._updateTimeline(-1)},c._tick=function(a){this.advance(a&&a.delta),this.Container__tick(a)},c._goto=function(a){var b=this.timeline.resolve(a);null!=b&&(this._t=0,this._updateTimeline(b,!0))},c._reset=function(){this._rawPosition=-1,this._t=this.currentFrame=0,this.paused=!1},c._updateTimeline=function(b,c){var d=this.mode!==a.INDEPENDENT,e=this.timeline;d&&(b=this.startPosition+(this.mode===a.SINGLE_FRAME?0:this._synchOffset)),0>b&&(b=0),(this._rawPosition!==b||d)&&(this._rawPosition=b,e.loop=this.loop,e.setPosition(b,d||!this.actionsEnabled,c,this._bound_resolveState))},c._renderFirstFrame=function(){var a=this.timeline,b=a.rawPosition;a.setPosition(0,!0,!0,this._bound_resolveState),a.rawPosition=b},c._resolveState=function(){var a=this.timeline;this.currentFrame=a.position;for(var b in this._managed)this._managed[b]=1;for(var c=a.tweens,d=0,e=c.length;e>d;d++){var f=c[d],g=f.target;if(g!==this&&!f.passive){var h=f._stepPosition;g instanceof createjs.DisplayObject?this._addManagedChild(g,h):this._setState(g.state,h)}}var i=this.children;for(d=i.length-1;d>=0;d--){var j=i[d].id;1===this._managed[j]&&(this.removeChildAt(d),delete this._managed[j])}},c._setState=function(a,b){if(a)for(var c=a.length-1;c>=0;c--){var d=a[c],e=d.t,f=d.p;for(var g in f)e[g]=f[g];this._addManagedChild(e,b)}},c._addManagedChild=function(b,c){b._off||(this.addChildAt(b,0),b instanceof a&&(b._synchOffset=c,b.mode===a.INDEPENDENT&&b.autoReset&&!this._managed[b.id]&&b._reset()),this._managed[b.id]=2)},c._getBounds=function(a,b){var c=this.DisplayObject_getBounds();return c||this.frameBounds&&(c=this._rectangle.copy(this.frameBounds[this.currentFrame])),c?this._transformBounds(c,a,b):this.Container__getBounds(a,b)},createjs.MovieClip=createjs.promote(a,"Container"),b.priority=100,b.ID="MovieClip",b.install=function(){createjs.Tween._installPlugin(b)},b.init=function(c,d){"startPosition"===d&&c.target instanceof a&&c._addPlugin(b)},b.step=function(){},b.change=function(a,b,c,d,e){return"startPosition"===c?1===e?b.props[c]:b.prev.props[c]:void 0}}(),this.createjs=this.createjs||{},function(){"use strict";function a(){throw"SpriteSheetUtils cannot be instantiated"}var b=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");b.getContext&&(a._workingCanvas=b,a._workingContext=b.getContext("2d"),b.width=b.height=1),a.extractFrame=function(b,c){isNaN(c)&&(c=b.getAnimation(c).frames[0]);var d=b.getFrame(c);if(!d)return null;var e=d.rect,f=a._workingCanvas;f.width=e.width,f.height=e.height,a._workingContext.drawImage(d.image,e.x,e.y,e.width,e.height,0,0,e.width,e.height);var g=document.createElement("img");return g.src=f.toDataURL("image/png"),g},a.addFlippedFrames=createjs.deprecate(null,"SpriteSheetUtils.addFlippedFrames"),a.mergeAlpha=createjs.deprecate(null,"SpriteSheetUtils.mergeAlpha"),a._flip=function(b,c,d,e){for(var f=b._images,g=a._workingCanvas,h=a._workingContext,i=f.length/c,j=0;i>j;j++){var k=f[j];k.__tmp=j,h.setTransform(1,0,0,1,0,0),h.clearRect(0,0,g.width+1,g.height+1),g.width=k.width,g.height=k.height,h.setTransform(d?-1:1,0,0,e?-1:1,d?k.width:0,e?k.height:0),h.drawImage(k,0,0);var l=document.createElement("img");l.src=g.toDataURL("image/png"),l.width=k.width||k.naturalWidth,l.height=k.height||k.naturalHeight,f.push(l)}var m=b._frames,n=m.length/c;for(j=0;n>j;j++){k=m[j]; +var o=k.rect.clone();l=f[k.image.__tmp+i*c];var p={image:l,rect:o,regX:k.regX,regY:k.regY};d&&(o.x=(l.width||l.naturalWidth)-o.x-o.width,p.regX=o.width-k.regX),e&&(o.y=(l.height||l.naturalHeight)-o.y-o.height,p.regY=o.height-k.regY),m.push(p)}var q="_"+(d?"h":"")+(e?"v":""),r=b._animations,s=b._data,t=r.length/c;for(j=0;t>j;j++){var u=r[j];k=s[u];var v={name:u+q,speed:k.speed,next:k.next,frames:[]};k.next&&(v.next+=q),m=k.frames;for(var w=0,x=m.length;x>w;w++)v.frames.push(m[w]+n*c);s[v.name]=v,r.push(v.name)}},createjs.SpriteSheetUtils=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a){this.EventDispatcher_constructor(),this.maxWidth=2048,this.maxHeight=2048,this.spriteSheet=null,this.scale=1,this.padding=1,this.timeSlice=.3,this.progress=-1,this.framerate=a||0,this._frames=[],this._animations={},this._data=null,this._nextFrameIndex=0,this._index=0,this._timerID=null,this._scale=1}var b=createjs.extend(a,createjs.EventDispatcher);a.ERR_DIMENSIONS="frame dimensions exceed max spritesheet dimensions",a.ERR_RUNNING="a build is already running",b.addFrame=function(b,c,d,e,f){if(this._data)throw a.ERR_RUNNING;var g=c||b.bounds||b.nominalBounds;return!g&&b.getBounds&&(g=b.getBounds()),g?(d=d||1,this._frames.push({source:b,sourceRect:g,scale:d,funct:e,data:f,index:this._frames.length,height:g.height*d})-1):null},b.addAnimation=function(b,c,d,e){if(this._data)throw a.ERR_RUNNING;this._animations[b]={frames:c,next:d,speed:e}},b.addMovieClip=function(b,c,d,e,f,g){if(this._data)throw a.ERR_RUNNING;var h=b.frameBounds,i=c||b.bounds||b.nominalBounds;if(!i&&b.getBounds&&(i=b.getBounds()),i||h){var j,k,l=this._frames.length,m=b.timeline.duration;for(j=0;m>j;j++){var n=h&&h[j]?h[j]:i;this.addFrame(b,n,d,this._setupMovieClipFrame,{i:j,f:e,d:f})}var o=b.timeline._labels,p=[];for(var q in o)p.push({index:o[q],label:q});if(p.length)for(p.sort(function(a,b){return a.index-b.index}),j=0,k=p.length;k>j;j++){for(var r=p[j].label,s=l+p[j].index,t=l+(j==k-1?m:p[j+1].index),u=[],v=s;t>v;v++)u.push(v);(!g||(r=g(r,b,s,t)))&&this.addAnimation(r,u,!0)}}},b.build=function(){if(this._data)throw a.ERR_RUNNING;for(this._startBuild();this._drawNext(););return this._endBuild(),this.spriteSheet},b.buildAsync=function(b){if(this._data)throw a.ERR_RUNNING;this.timeSlice=b,this._startBuild();var c=this;this._timerID=setTimeout(function(){c._run()},50-50*Math.max(.01,Math.min(.99,this.timeSlice||.3)))},b.stopAsync=function(){clearTimeout(this._timerID),this._data=null},b.clone=function(){throw"SpriteSheetBuilder cannot be cloned."},b.toString=function(){return"[SpriteSheetBuilder]"},b._startBuild=function(){var b=this.padding||0;this.progress=0,this.spriteSheet=null,this._index=0,this._scale=this.scale;var c=[];this._data={images:[],frames:c,framerate:this.framerate,animations:this._animations};var d=this._frames.slice();if(d.sort(function(a,b){return a.height<=b.height?-1:1}),d[d.length-1].height+2*b>this.maxHeight)throw a.ERR_DIMENSIONS;for(var e=0,f=0,g=0;d.length;){var h=this._fillRow(d,e,g,c,b);if(h.w>f&&(f=h.w),e+=h.h,!h.h||!d.length){var i=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");i.width=this._getSize(f,this.maxWidth),i.height=this._getSize(e,this.maxHeight),this._data.images[g]=i,h.h||(f=e=0,g++)}}},b._setupMovieClipFrame=function(a,b){var c=a.actionsEnabled;a.actionsEnabled=!1,a.gotoAndStop(b.i),a.actionsEnabled=c,b.f&&b.f(a,b.d,b.i)},b._getSize=function(a,b){for(var c=4;Math.pow(2,++c)=0;l--){var m=b[l],n=this._scale*m.scale,o=m.sourceRect,p=m.source,q=Math.floor(n*o.x-f),r=Math.floor(n*o.y-f),s=Math.ceil(n*o.height+2*f),t=Math.ceil(n*o.width+2*f);if(t>g)throw a.ERR_DIMENSIONS;s>i||j+t>g||(m.img=d,m.rect=new createjs.Rectangle(j,c,t,s),k=k||s,b.splice(l,1),e[m.index]=[j,c,t,s,d,Math.round(-q+n*p.regX-f),Math.round(-r+n*p.regY-f)],j+=t)}return{w:j,h:k}},b._endBuild=function(){this.spriteSheet=new createjs.SpriteSheet(this._data),this._data=null,this.progress=1,this.dispatchEvent("complete")},b._run=function(){for(var a=50*Math.max(.01,Math.min(.99,this.timeSlice||.3)),b=(new Date).getTime()+a,c=!1;b>(new Date).getTime();)if(!this._drawNext()){c=!0;break}if(c)this._endBuild();else{var d=this;this._timerID=setTimeout(function(){d._run()},50-a)}var e=this.progress=this._index/this._frames.length;if(this.hasEventListener("progress")){var f=new createjs.Event("progress");f.progress=e,this.dispatchEvent(f)}},b._drawNext=function(){var a=this._frames[this._index],b=a.scale*this._scale,c=a.rect,d=a.sourceRect,e=this._data.images[a.img],f=e.getContext("2d");return a.funct&&a.funct(a.source,a.data),f.save(),f.beginPath(),f.rect(c.x,c.y,c.width,c.height),f.clip(),f.translate(Math.ceil(c.x-d.x*b),Math.ceil(c.y-d.y*b)),f.scale(b,b),a.source.draw(f),f.restore(),++this._index=!!d)return b;for(var e=0;d>e;e++){var f=c[e];if(f&&f.getBounds){var g=f.getBounds();g&&(0==e?b.setValues(g.x,g.y,g.width,g.height):b.extend(g.x,g.y,g.width,g.height))}}return b},b.toString=function(){return"[BitmapCache]"},b.define=function(a,b,c,d,e,f,g){if(!a)throw"No symbol to cache";this._options=g,this.target=a,this.width=d>=1?d:1,this.height=e>=1?e:1,this.x=b||0,this.y=c||0,this.scale=f||1,this.update()},b.update=function(b){if(!this.target)throw"define() must be called before update()";var c=a.getFilterBounds(this.target),d=this.target.cacheCanvas;this._drawWidth=Math.ceil(this.width*this.scale)+c.width,this._drawHeight=Math.ceil(this.height*this.scale)+c.height,d&&this._drawWidth==d.width&&this._drawHeight==d.height||this._updateSurface(),this._filterOffX=c.x,this._filterOffY=c.y,this.offX=this.x*this.scale+this._filterOffX,this.offY=this.y*this.scale+this._filterOffY,this._drawToCache(b),this.cacheID=this.cacheID?this.cacheID+1:1},b.release=function(){if(this._webGLCache)this._webGLCache.isCacheControlled||(this.__lastRT&&(this.__lastRT=void 0),this.__rtA&&this._webGLCache._killTextureObject(this.__rtA),this.__rtB&&this._webGLCache._killTextureObject(this.__rtB),this.target&&this.target.cacheCanvas&&this._webGLCache._killTextureObject(this.target.cacheCanvas)),this._webGLCache=!1;else{var a=this.target.stage;a instanceof createjs.StageGL&&a.releaseTexture(this.target.cacheCanvas)}this.target=this.target.cacheCanvas=null,this.cacheID=this._cacheDataURLID=this._cacheDataURL=void 0,this.width=this.height=this.x=this.y=this.offX=this.offY=0,this.scale=1},b.getCacheDataURL=function(){var a=this.target&&this.target.cacheCanvas;return a?(this.cacheID!=this._cacheDataURLID&&(this._cacheDataURLID=this.cacheID,this._cacheDataURL=a.toDataURL?a.toDataURL():null),this._cacheDataURL):null},b.draw=function(a){return this.target?(a.drawImage(this.target.cacheCanvas,this.x+this._filterOffX/this.scale,this.y+this._filterOffY/this.scale,this._drawWidth/this.scale,this._drawHeight/this.scale),!0):!1},b._updateSurface=function(){if(!this._options||!this._options.useGL){var a=this.target.cacheCanvas;return a||(a=this.target.cacheCanvas=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")),a.width=this._drawWidth,void(a.height=this._drawHeight)}if(!this._webGLCache)if("stage"===this._options.useGL){if(!this.target.stage||!this.target.stage.isWebGL){var b="Cannot use 'stage' for cache because the object's parent stage is ";throw b+=this.target.stage?"non WebGL.":"not set, please addChild to the correct stage."}this.target.cacheCanvas=!0,this._webGLCache=this.target.stage}else if("new"===this._options.useGL)this.target.cacheCanvas=document.createElement("canvas"),this._webGLCache=new createjs.StageGL(this.target.cacheCanvas,{antialias:!0,transparent:!0,autoPurge:-1}),this._webGLCache.isCacheControlled=!0;else{if(!(this._options.useGL instanceof createjs.StageGL))throw"Invalid option provided to useGL, expected ['stage', 'new', StageGL, undefined], got "+this._options.useGL;this.target.cacheCanvas=!0,this._webGLCache=this._options.useGL,this._webGLCache.isCacheControlled=!0}var a=this.target.cacheCanvas,c=this._webGLCache;c.isCacheControlled&&(a.width=this._drawWidth,a.height=this._drawHeight,c.updateViewport(this._drawWidth,this._drawHeight)),this.target.filters?(c.getTargetRenderTexture(this.target,this._drawWidth,this._drawHeight),c.getTargetRenderTexture(this.target,this._drawWidth,this._drawHeight)):c.isCacheControlled||c.getTargetRenderTexture(this.target,this._drawWidth,this._drawHeight)},b._drawToCache=function(a){var b=this.target.cacheCanvas,c=this.target,d=this._webGLCache;if(d)d.cacheDraw(c,c.filters,this),b=this.target.cacheCanvas,b.width=this._drawWidth,b.height=this._drawHeight;else{var e=b.getContext("2d");a||e.clearRect(0,0,this._drawWidth+1,this._drawHeight+1),e.save(),e.globalCompositeOperation=a,e.setTransform(this.scale,0,0,this.scale,-this._filterOffX,-this._filterOffY),e.translate(-this.x,-this.y),c.draw(e,!0),e.restore(),c.filters&&c.filters.length&&this._applyFilters(e)}b._invalid=!0},b._applyFilters=function(a){var b,c=this.target.filters,d=this._drawWidth,e=this._drawHeight,f=0,g=c[f];do g.usesContext?(b&&(a.putImageData(b,0,0),b=null),g.applyFilter(a,0,0,d,e)):(b||(b=a.getImageData(0,0,d,e)),g._applyFilter(b)),g=null!==g._multiPass?g._multiPass:c[++f];while(g);b&&a.putImageData(b,0,0)},createjs.BitmapCache=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c){this.Filter_constructor(),this._blurX=a,this._blurXTable=[],this._lastBlurX=null,this._blurY=b,this._blurYTable=[],this._lastBlurY=null,this._quality,this._lastQuality=null,this.FRAG_SHADER_TEMPLATE="uniform float xWeight[{{blurX}}];uniform float yWeight[{{blurY}}];uniform vec2 textureOffset;void main(void) {vec4 color = vec4(0.0);float xAdj = ({{blurX}}.0-1.0)/2.0;float yAdj = ({{blurY}}.0-1.0)/2.0;vec2 sampleOffset;for(int i=0; i<{{blurX}}; i++) {for(int j=0; j<{{blurY}}; j++) {sampleOffset = vRenderCoord + (textureOffset * vec2(float(i)-xAdj, float(j)-yAdj));color += texture2D(uSampler, sampleOffset) * (xWeight[i] * yWeight[j]);}}gl_FragColor = color.rgba;}",(isNaN(c)||1>c)&&(c=1),this.setQuality(0|c)}var b=createjs.extend(a,createjs.Filter);b.getBlurX=function(){return this._blurX},b.getBlurY=function(){return this._blurY},b.setBlurX=function(a){(isNaN(a)||0>a)&&(a=0),this._blurX=a},b.setBlurY=function(a){(isNaN(a)||0>a)&&(a=0),this._blurY=a},b.getQuality=function(){return this._quality},b.setQuality=function(a){(isNaN(a)||0>a)&&(a=0),this._quality=0|a},b._getShader=function(){var a=this._lastBlurX!==this._blurX,b=this._lastBlurY!==this._blurY,c=this._lastQuality!==this._quality;return a||b||c?((a||c)&&(this._blurXTable=this._getTable(this._blurX*this._quality)),(b||c)&&(this._blurYTable=this._getTable(this._blurY*this._quality)),this._updateShader(),this._lastBlurX=this._blurX,this._lastBlurY=this._blurY,void(this._lastQuality=this._quality)):this._compiledShader},b._setShader=function(){this._compiledShader};try{Object.defineProperties(b,{blurX:{get:b.getBlurX,set:b.setBlurX},blurY:{get:b.getBlurY,set:b.setBlurY},quality:{get:b.getQuality,set:b.setQuality},_builtShader:{get:b._getShader,set:b._setShader}})}catch(c){console.log(c)}b._getTable=function(a){var b=4.2;if(1>=a)return[1];var c=[],d=Math.ceil(2*a);d+=d%2?0:1;for(var e=d/2|0,f=-e;e>=f;f++){var g=f/e*b;c.push(1/Math.sqrt(2*Math.PI)*Math.pow(Math.E,-(Math.pow(g,2)/4)))}var h=c.reduce(function(a,b){return a+b});return c.map(function(a){return a/h})},b._updateShader=function(){if(void 0!==this._blurX&&void 0!==this._blurY){var a=this.FRAG_SHADER_TEMPLATE;a=a.replace(/\{\{blurX\}\}/g,this._blurXTable.length.toFixed(0)),a=a.replace(/\{\{blurY\}\}/g,this._blurYTable.length.toFixed(0)),this.FRAG_SHADER_BODY=a}},b.shaderParamSetup=function(a,b,c){a.uniform1fv(a.getUniformLocation(c,"xWeight"),this._blurXTable),a.uniform1fv(a.getUniformLocation(c,"yWeight"),this._blurYTable),a.uniform2f(a.getUniformLocation(c,"textureOffset"),2/(b._viewportWidth*this._quality),2/(b._viewportHeight*this._quality))},a.MUL_TABLE=[1,171,205,293,57,373,79,137,241,27,391,357,41,19,283,265,497,469,443,421,25,191,365,349,335,161,155,149,9,278,269,261,505,245,475,231,449,437,213,415,405,395,193,377,369,361,353,345,169,331,325,319,313,307,301,37,145,285,281,69,271,267,263,259,509,501,493,243,479,118,465,459,113,446,55,435,429,423,209,413,51,403,199,393,97,3,379,375,371,367,363,359,355,351,347,43,85,337,333,165,327,323,5,317,157,311,77,305,303,75,297,294,73,289,287,71,141,279,277,275,68,135,67,133,33,262,260,129,511,507,503,499,495,491,61,121,481,477,237,235,467,232,115,457,227,451,7,445,221,439,218,433,215,427,425,211,419,417,207,411,409,203,202,401,399,396,197,49,389,387,385,383,95,189,47,187,93,185,23,183,91,181,45,179,89,177,11,175,87,173,345,343,341,339,337,21,167,83,331,329,327,163,81,323,321,319,159,79,315,313,39,155,309,307,153,305,303,151,75,299,149,37,295,147,73,291,145,289,287,143,285,71,141,281,35,279,139,69,275,137,273,17,271,135,269,267,133,265,33,263,131,261,130,259,129,257,1],a.SHG_TABLE=[0,9,10,11,9,12,10,11,12,9,13,13,10,9,13,13,14,14,14,14,10,13,14,14,14,13,13,13,9,14,14,14,15,14,15,14,15,15,14,15,15,15,14,15,15,15,15,15,14,15,15,15,15,15,15,12,14,15,15,13,15,15,15,15,16,16,16,15,16,14,16,16,14,16,13,16,16,16,15,16,13,16,15,16,14,9,16,16,16,16,16,16,16,16,16,13,14,16,16,15,16,16,10,16,15,16,14,16,16,14,16,16,14,16,16,14,15,16,16,16,14,15,14,15,13,16,16,15,17,17,17,17,17,17,14,15,17,17,16,16,17,16,15,17,16,17,11,17,16,17,16,17,16,17,17,16,17,17,16,17,17,16,16,17,17,17,16,14,17,17,17,17,15,16,14,16,15,16,13,16,15,16,14,16,15,16,12,16,15,16,17,17,17,17,17,13,16,15,17,17,17,16,15,17,17,17,16,15,17,17,14,16,17,17,16,17,17,16,15,17,16,14,17,16,15,17,16,17,17,16,17,15,16,17,14,17,16,15,17,16,17,13,17,16,17,17,16,17,14,17,16,17,16,17,16,17,9],b.getBounds=function(a){var b=0|this.blurX,c=0|this.blurY;if(0>=b&&0>=c)return a;var d=Math.pow(this.quality,.2);return(a||new createjs.Rectangle).pad(c*d+1,b*d+1,c*d+1,b*d+1)},b.clone=function(){return new a(this.blurX,this.blurY,this.quality)},b.toString=function(){return"[BlurFilter]"},b._applyFilter=function(b){var c=this._blurX>>1;if(isNaN(c)||0>c)return!1;var d=this._blurY>>1;if(isNaN(d)||0>d)return!1;if(0==c&&0==d)return!1;var e=this.quality;(isNaN(e)||1>e)&&(e=1),e|=0,e>3&&(e=3),1>e&&(e=1);var f=b.data,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=c+c+1|0,w=d+d+1|0,x=0|b.width,y=0|b.height,z=x-1|0,A=y-1|0,B=c+1|0,C=d+1|0,D={r:0,b:0,g:0,a:0},E=D;for(i=1;v>i;i++)E=E.n={r:0,b:0,g:0,a:0};E.n=D;var F={r:0,b:0,g:0,a:0},G=F;for(i=1;w>i;i++)G=G.n={r:0,b:0,g:0,a:0};G.n=F;for(var H=null,I=0|a.MUL_TABLE[c],J=0|a.SHG_TABLE[c],K=0|a.MUL_TABLE[d],L=0|a.SHG_TABLE[d];e-->0;){m=l=0;var M=I,N=J;for(h=y;--h>-1;){for(n=B*(r=f[0|l]),o=B*(s=f[l+1|0]),p=B*(t=f[l+2|0]),q=B*(u=f[l+3|0]),E=D,i=B;--i>-1;)E.r=r,E.g=s,E.b=t,E.a=u,E=E.n;for(i=1;B>i;i++)j=l+((i>z?z:i)<<2)|0,n+=E.r=f[j],o+=E.g=f[j+1],p+=E.b=f[j+2],q+=E.a=f[j+3],E=E.n;for(H=D,g=0;x>g;g++)f[l++]=n*M>>>N,f[l++]=o*M>>>N,f[l++]=p*M>>>N,f[l++]=q*M>>>N,j=m+((j=g+c+1)g;g++){for(l=g<<2|0,n=C*(r=f[l])|0,o=C*(s=f[l+1|0])|0,p=C*(t=f[l+2|0])|0,q=C*(u=f[l+3|0])|0,G=F,i=0;C>i;i++)G.r=r,G.g=s,G.b=t,G.a=u,G=G.n;for(k=x,i=1;d>=i;i++)l=k+g<<2,n+=G.r=f[l],o+=G.g=f[l+1],p+=G.b=f[l+2],q+=G.a=f[l+3],G=G.n,A>i&&(k+=x);if(l=g,H=F,e>0)for(h=0;y>h;h++)j=l<<2,f[j+3]=u=q*M>>>N,u>0?(f[j]=n*M>>>N,f[j+1]=o*M>>>N,f[j+2]=p*M>>>N):f[j]=f[j+1]=f[j+2]=0,j=g+((j=h+C)h;h++)j=l<<2,f[j+3]=u=q*M>>>N,u>0?(u=255/u,f[j]=(n*M>>>N)*u,f[j+1]=(o*M>>>N)*u,f[j+2]=(p*M>>>N)*u):f[j]=f[j+1]=f[j+2]=0,j=g+((j=h+C)d;d+=4)b[d+3]=c[d]||0;return!0},b._prepAlphaMap=function(){if(!this.alphaMap)return!1;if(this.alphaMap==this._alphaMap&&this._mapData)return!0;this._mapData=null;var a,b=this._alphaMap=this.alphaMap,c=b;b instanceof HTMLCanvasElement?a=c.getContext("2d"):(c=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"),c.width=b.width,c.height=b.height,a=c.getContext("2d"),a.drawImage(b,0,0));try{var d=a.getImageData(0,0,b.width,b.height)}catch(e){return!1}return this._mapData=d.data,!0},createjs.AlphaMapFilter=createjs.promote(a,"Filter")}(),this.createjs=this.createjs||{},function(){"use strict";function a(a){this.Filter_constructor(),this.mask=a,this.usesContext=!0,this.FRAG_SHADER_BODY="uniform sampler2D uAlphaSampler;void main(void) {vec4 color = texture2D(uSampler, vRenderCoord);vec4 alphaMap = texture2D(uAlphaSampler, vTextureCoord);gl_FragColor = vec4(color.rgb, color.a * alphaMap.a);}"}var b=createjs.extend(a,createjs.Filter);b.shaderParamSetup=function(a,b,c){this._mapTexture||(this._mapTexture=a.createTexture()),a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,this._mapTexture),b.setTextureParams(a),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,this.mask),a.uniform1i(a.getUniformLocation(c,"uAlphaSampler"),1)},b.applyFilter=function(a,b,c,d,e,f,g,h){return this.mask?(f=f||a,null==g&&(g=b),null==h&&(h=c),f.save(),a!=f?!1:(f.globalCompositeOperation="destination-in",f.drawImage(this.mask,g,h),f.restore(),!0)):!0},b.clone=function(){return new a(this.mask)},b.toString=function(){return"[AlphaMaskFilter]"},createjs.AlphaMaskFilter=createjs.promote(a,"Filter")}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c,d,e,f,g,h){this.Filter_constructor(),this.redMultiplier=null!=a?a:1,this.greenMultiplier=null!=b?b:1,this.blueMultiplier=null!=c?c:1,this.alphaMultiplier=null!=d?d:1,this.redOffset=e||0,this.greenOffset=f||0,this.blueOffset=g||0,this.alphaOffset=h||0,this.FRAG_SHADER_BODY="uniform vec4 uColorMultiplier;uniform vec4 uColorOffset;void main(void) {vec4 color = texture2D(uSampler, vRenderCoord);gl_FragColor = (color * uColorMultiplier) + uColorOffset;}"}var b=createjs.extend(a,createjs.Filter);b.shaderParamSetup=function(a,b,c){a.uniform4f(a.getUniformLocation(c,"uColorMultiplier"),this.redMultiplier,this.greenMultiplier,this.blueMultiplier,this.alphaMultiplier),a.uniform4f(a.getUniformLocation(c,"uColorOffset"),this.redOffset/255,this.greenOffset/255,this.blueOffset/255,this.alphaOffset/255)},b.toString=function(){return"[ColorFilter]"},b.clone=function(){return new a(this.redMultiplier,this.greenMultiplier,this.blueMultiplier,this.alphaMultiplier,this.redOffset,this.greenOffset,this.blueOffset,this.alphaOffset)},b._applyFilter=function(a){for(var b=a.data,c=b.length,d=0;c>d;d+=4)b[d]=b[d]*this.redMultiplier+this.redOffset,b[d+1]=b[d+1]*this.greenMultiplier+this.greenOffset,b[d+2]=b[d+2]*this.blueMultiplier+this.blueOffset,b[d+3]=b[d+3]*this.alphaMultiplier+this.alphaOffset;return!0},createjs.ColorFilter=createjs.promote(a,"Filter")}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c,d){this.setColor(a,b,c,d)}var b=a.prototype;a.DELTA_INDEX=[0,.01,.02,.04,.05,.06,.07,.08,.1,.11,.12,.14,.15,.16,.17,.18,.2,.21,.22,.24,.25,.27,.28,.3,.32,.34,.36,.38,.4,.42,.44,.46,.48,.5,.53,.56,.59,.62,.65,.68,.71,.74,.77,.8,.83,.86,.89,.92,.95,.98,1,1.06,1.12,1.18,1.24,1.3,1.36,1.42,1.48,1.54,1.6,1.66,1.72,1.78,1.84,1.9,1.96,2,2.12,2.25,2.37,2.5,2.62,2.75,2.87,3,3.2,3.4,3.6,3.8,4,4.3,4.7,4.9,5,5.5,6,6.5,6.8,7,7.3,7.5,7.8,8,8.4,8.7,9,9.4,9.6,9.8,10],a.IDENTITY_MATRIX=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1],a.LENGTH=a.IDENTITY_MATRIX.length,b.setColor=function(a,b,c,d){return this.reset().adjustColor(a,b,c,d)},b.reset=function(){return this.copy(a.IDENTITY_MATRIX)},b.adjustColor=function(a,b,c,d){return this.adjustHue(d),this.adjustContrast(b),this.adjustBrightness(a),this.adjustSaturation(c)},b.adjustBrightness=function(a){return 0==a||isNaN(a)?this:(a=this._cleanValue(a,255),this._multiplyMatrix([1,0,0,0,a,0,1,0,0,a,0,0,1,0,a,0,0,0,1,0,0,0,0,0,1]),this)},b.adjustContrast=function(b){if(0==b||isNaN(b))return this;b=this._cleanValue(b,100);var c;return 0>b?c=127+b/100*127:(c=b%1,c=0==c?a.DELTA_INDEX[b]:a.DELTA_INDEX[b<<0]*(1-c)+a.DELTA_INDEX[(b<<0)+1]*c,c=127*c+127),this._multiplyMatrix([c/127,0,0,0,.5*(127-c),0,c/127,0,0,.5*(127-c),0,0,c/127,0,.5*(127-c),0,0,0,1,0,0,0,0,0,1]),this},b.adjustSaturation=function(a){if(0==a||isNaN(a))return this;a=this._cleanValue(a,100);var b=1+(a>0?3*a/100:a/100),c=.3086,d=.6094,e=.082;return this._multiplyMatrix([c*(1-b)+b,d*(1-b),e*(1-b),0,0,c*(1-b),d*(1-b)+b,e*(1-b),0,0,c*(1-b),d*(1-b),e*(1-b)+b,0,0,0,0,0,1,0,0,0,0,0,1]),this},b.adjustHue=function(a){if(0==a||isNaN(a))return this;a=this._cleanValue(a,180)/180*Math.PI;var b=Math.cos(a),c=Math.sin(a),d=.213,e=.715,f=.072;return this._multiplyMatrix([d+b*(1-d)+c*-d,e+b*-e+c*-e,f+b*-f+c*(1-f),0,0,d+b*-d+.143*c,e+b*(1-e)+.14*c,f+b*-f+c*-.283,0,0,d+b*-d+c*-(1-d),e+b*-e+c*e,f+b*(1-f)+c*f,0,0,0,0,0,1,0,0,0,0,0,1]),this},b.concat=function(b){return b=this._fixMatrix(b),b.length!=a.LENGTH?this:(this._multiplyMatrix(b),this)},b.clone=function(){return(new a).copy(this)},b.toArray=function(){for(var b=[],c=0,d=a.LENGTH;d>c;c++)b[c]=this[c];return b},b.copy=function(b){for(var c=a.LENGTH,d=0;c>d;d++)this[d]=b[d];return this},b.toString=function(){return"[ColorMatrix]"},b._multiplyMatrix=function(a){var b,c,d,e=[];for(b=0;5>b;b++){for(c=0;5>c;c++)e[c]=this[c+5*b];for(c=0;5>c;c++){var f=0;for(d=0;5>d;d++)f+=a[c+5*d]*e[d];this[c+5*b]=f}}},b._cleanValue=function(a,b){return Math.min(b,Math.max(-b,a))},b._fixMatrix=function(b){return b instanceof a&&(b=b.toArray()),b.lengtha.LENGTH&&(b=b.slice(0,a.LENGTH)),b},createjs.ColorMatrix=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a){this.Filter_constructor(),this.matrix=a,this.FRAG_SHADER_BODY="uniform mat4 uColorMatrix;uniform vec4 uColorMatrixOffset;void main(void) {vec4 color = texture2D(uSampler, vRenderCoord);mat4 m = uColorMatrix;vec4 newColor = vec4(0,0,0,0);newColor.r = color.r*m[0][0] + color.g*m[0][1] + color.b*m[0][2] + color.a*m[0][3];newColor.g = color.r*m[1][0] + color.g*m[1][1] + color.b*m[1][2] + color.a*m[1][3];newColor.b = color.r*m[2][0] + color.g*m[2][1] + color.b*m[2][2] + color.a*m[2][3];newColor.a = color.r*m[3][0] + color.g*m[3][1] + color.b*m[3][2] + color.a*m[3][3];gl_FragColor = newColor + uColorMatrixOffset;}"}var b=createjs.extend(a,createjs.Filter);b.shaderParamSetup=function(a,b,c){var d=this.matrix,e=new Float32Array([d[0],d[1],d[2],d[3],d[5],d[6],d[7],d[8],d[10],d[11],d[12],d[13],d[15],d[16],d[17],d[18]]);a.uniformMatrix4fv(a.getUniformLocation(c,"uColorMatrix"),!1,e),a.uniform4f(a.getUniformLocation(c,"uColorMatrixOffset"),d[4]/255,d[9]/255,d[14]/255,d[19]/255)},b.toString=function(){return"[ColorMatrixFilter]"},b.clone=function(){return new a(this.matrix)},b._applyFilter=function(a){for(var b,c,d,e,f=a.data,g=f.length,h=this.matrix,i=h[0],j=h[1],k=h[2],l=h[3],m=h[4],n=h[5],o=h[6],p=h[7],q=h[8],r=h[9],s=h[10],t=h[11],u=h[12],v=h[13],w=h[14],x=h[15],y=h[16],z=h[17],A=h[18],B=h[19],C=0;g>C;C+=4)b=f[C],c=f[C+1],d=f[C+2],e=f[C+3],f[C]=b*i+c*j+d*k+e*l+m,f[C+1]=b*n+c*o+d*p+e*q+r,f[C+2]=b*s+c*t+d*u+e*v+w,f[C+3]=b*x+c*y+d*z+e*A+B;return!0},createjs.ColorMatrixFilter=createjs.promote(a,"Filter")}(),this.createjs=this.createjs||{},function(){"use strict";function a(){throw"Touch cannot be instantiated"}a.isSupported=function(){return!!("ontouchstart"in window||window.navigator.msPointerEnabled&&window.navigator.msMaxTouchPoints>0||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints>0)},a.enable=function(b,c,d){return b&&b.canvas&&a.isSupported()?b.__touch?!0:(b.__touch={pointers:{},multitouch:!c,preventDefault:!d,count:0},"ontouchstart"in window?a._IOS_enable(b):(window.navigator.msPointerEnabled||window.navigator.pointerEnabled)&&a._IE_enable(b),!0):!1},a.disable=function(b){b&&("ontouchstart"in window?a._IOS_disable(b):(window.navigator.msPointerEnabled||window.navigator.pointerEnabled)&&a._IE_disable(b),delete b.__touch)},a._IOS_enable=function(b){var c=b.canvas,d=b.__touch.f=function(c){a._IOS_handleEvent(b,c)};c.addEventListener("touchstart",d,!1),c.addEventListener("touchmove",d,!1),c.addEventListener("touchend",d,!1),c.addEventListener("touchcancel",d,!1)},a._IOS_disable=function(a){var b=a.canvas;if(b){var c=a.__touch.f;b.removeEventListener("touchstart",c,!1),b.removeEventListener("touchmove",c,!1),b.removeEventListener("touchend",c,!1),b.removeEventListener("touchcancel",c,!1)}},a._IOS_handleEvent=function(a,b){if(a){a.__touch.preventDefault&&b.preventDefault&&b.preventDefault();for(var c=b.changedTouches,d=b.type,e=0,f=c.length;f>e;e++){var g=c[e],h=g.identifier;g.target==a.canvas&&("touchstart"==d?this._handleStart(a,h,b,g.pageX,g.pageY):"touchmove"==d?this._handleMove(a,h,b,g.pageX,g.pageY):("touchend"==d||"touchcancel"==d)&&this._handleEnd(a,h,b))}}},a._IE_enable=function(b){var c=b.canvas,d=b.__touch.f=function(c){a._IE_handleEvent(b,c)};void 0===window.navigator.pointerEnabled?(c.addEventListener("MSPointerDown",d,!1),window.addEventListener("MSPointerMove",d,!1),window.addEventListener("MSPointerUp",d,!1),window.addEventListener("MSPointerCancel",d,!1),b.__touch.preventDefault&&(c.style.msTouchAction="none")):(c.addEventListener("pointerdown",d,!1),window.addEventListener("pointermove",d,!1),window.addEventListener("pointerup",d,!1),window.addEventListener("pointercancel",d,!1),b.__touch.preventDefault&&(c.style.touchAction="none")),b.__touch.activeIDs={}},a._IE_disable=function(a){var b=a.__touch.f;void 0===window.navigator.pointerEnabled?(window.removeEventListener("MSPointerMove",b,!1),window.removeEventListener("MSPointerUp",b,!1),window.removeEventListener("MSPointerCancel",b,!1),a.canvas&&a.canvas.removeEventListener("MSPointerDown",b,!1)):(window.removeEventListener("pointermove",b,!1),window.removeEventListener("pointerup",b,!1),window.removeEventListener("pointercancel",b,!1),a.canvas&&a.canvas.removeEventListener("pointerdown",b,!1))},a._IE_handleEvent=function(a,b){if(a){a.__touch.preventDefault&&b.preventDefault&&b.preventDefault();var c=b.type,d=b.pointerId,e=a.__touch.activeIDs;if("MSPointerDown"==c||"pointerdown"==c){if(b.srcElement!=a.canvas)return;e[d]=!0,this._handleStart(a,d,b,b.pageX,b.pageY)}else e[d]&&("MSPointerMove"==c||"pointermove"==c?this._handleMove(a,d,b,b.pageX,b.pageY):("MSPointerUp"==c||"MSPointerCancel"==c||"pointerup"==c||"pointercancel"==c)&&(delete e[d],this._handleEnd(a,d,b)))}},a._handleStart=function(a,b,c,d,e){var f=a.__touch;if(f.multitouch||!f.count){var g=f.pointers;g[b]||(g[b]=!0,f.count++,a._handlePointerDown(b,c,d,e))}},a._handleMove=function(a,b,c,d,e){a.__touch.pointers[b]&&a._handlePointerMove(b,c,d,e)},a._handleEnd=function(a,b,c){var d=a.__touch,e=d.pointers;e[b]&&(d.count--,a._handlePointerUp(b,c,!0),delete e[b])},createjs.Touch=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=createjs.EaselJS=createjs.EaselJS||{};a.version="NEXT",a.buildDate="Thu, 14 Sep 2017 22:19:48 GMT"}(); \ No newline at end of file diff --git a/_assets/libs/soundjs-NEXT.min.js b/_assets/libs/soundjs-NEXT.min.js new file mode 100644 index 00000000..89ba7fc4 --- /dev/null +++ b/_assets/libs/soundjs-NEXT.min.js @@ -0,0 +1,18 @@ +/*! +* @license SoundJS +* Visit http://createjs.com/ for documentation, updates and examples. +* +* Copyright (c) 2011-2015 gskinner.com, inc. +* +* Distributed under the terms of the MIT license. +* http://www.opensource.org/licenses/mit-license.html +* +* This notice shall be included in all copies or substantial portions of the Software. +*/ + +/**! + * SoundJS FlashAudioPlugin also includes swfobject (http://code.google.com/p/swfobject/) + */ + +this.createjs=this.createjs||{},function(){var a=createjs.SoundJS=createjs.SoundJS||{};a.version="NEXT",a.buildDate="Thu, 14 Sep 2017 22:19:45 GMT"}(),this.createjs=this.createjs||{},createjs.extend=function(a,b){"use strict";function c(){this.constructor=a}return c.prototype=b.prototype,a.prototype=new c},this.createjs=this.createjs||{},createjs.promote=function(a,b){"use strict";var c=a.prototype,d=Object.getPrototypeOf&&Object.getPrototypeOf(c)||c.__proto__;if(d){c[(b+="_")+"constructor"]=d.constructor;for(var e in d)c.hasOwnProperty(e)&&"function"==typeof d[e]&&(c[b+e]=d[e])}return a},this.createjs=this.createjs||{},createjs.deprecate=function(a,b){"use strict";return function(){var c="Deprecated property or method '"+b+"'. See docs for info.";return console&&(console.warn?console.warn(c):console.log(c)),a&&a.apply(this,arguments)}},this.createjs=this.createjs||{},createjs.indexOf=function(a,b){"use strict";for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1},this.createjs=this.createjs||{},function(){"use strict";createjs.proxy=function(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){return a.apply(b,Array.prototype.slice.call(arguments,0).concat(c))}}}(),this.createjs=this.createjs||{},function(){"use strict";function BrowserDetect(){throw"BrowserDetect cannot be instantiated"}var a=BrowserDetect.agent=window.navigator.userAgent;BrowserDetect.isWindowPhone=a.indexOf("IEMobile")>-1||a.indexOf("Windows Phone")>-1,BrowserDetect.isFirefox=a.indexOf("Firefox")>-1,BrowserDetect.isOpera=null!=window.opera,BrowserDetect.isChrome=a.indexOf("Chrome")>-1,BrowserDetect.isIOS=(a.indexOf("iPod")>-1||a.indexOf("iPhone")>-1||a.indexOf("iPad")>-1)&&!BrowserDetect.isWindowPhone,BrowserDetect.isAndroid=a.indexOf("Android")>-1&&!BrowserDetect.isWindowPhone,BrowserDetect.isBlackberry=a.indexOf("Blackberry")>-1,createjs.BrowserDetect=BrowserDetect}(),this.createjs=this.createjs||{},function(){"use strict";function EventDispatcher(){this._listeners=null,this._captureListeners=null}var a=EventDispatcher.prototype;EventDispatcher.initialize=function(b){b.addEventListener=a.addEventListener,b.on=a.on,b.removeEventListener=b.off=a.removeEventListener,b.removeAllEventListeners=a.removeAllEventListeners,b.hasEventListener=a.hasEventListener,b.dispatchEvent=a.dispatchEvent,b._dispatchEvent=a._dispatchEvent,b.willTrigger=a.willTrigger},a.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},a.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},a.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},a.off=a.removeEventListener,a.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},a.dispatchEvent=function(a,b,c){if("string"==typeof a){var d=this._listeners;if(!(b||d&&d[a]))return!0;a=new createjs.Event(a,b,c)}else a.target&&a.clone&&(a=a.clone());try{a.target=this}catch(e){}if(a.bubbles&&this.parent){for(var f=this,g=[f];f.parent;)g.push(f=f.parent);var h,i=g.length;for(h=i-1;h>=0&&!a.propagationStopped;h--)g[h]._dispatchEvent(a,1+(0==h));for(h=1;i>h&&!a.propagationStopped;h++)g[h]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return!a.defaultPrevented},a.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},a.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},a.toString=function(){return"[EventDispatcher]"},a._dispatchEvent=function(a,b){var c,d,e=2>=b?this._captureListeners:this._listeners;if(a&&e&&(d=e[a.type])&&(c=d.length)){try{a.currentTarget=this}catch(f){}try{a.eventPhase=0|b}catch(f){}a.removed=!1,d=d.slice();for(var g=0;c>g&&!a.immediatePropagationStopped;g++){var h=d[g];h.handleEvent?h.handleEvent(a):h(a),a.removed&&(this.off(a.type,h,1==b),a.removed=!1)}}2===b&&this._dispatchEvent(a,2.1)},createjs.EventDispatcher=EventDispatcher}(),this.createjs=this.createjs||{},function(){"use strict";function Event(a,b,c){this.type=a,this.target=null,this.currentTarget=null,this.eventPhase=0,this.bubbles=!!b,this.cancelable=!!c,this.timeStamp=(new Date).getTime(),this.defaultPrevented=!1,this.propagationStopped=!1,this.immediatePropagationStopped=!1,this.removed=!1}var a=Event.prototype;a.preventDefault=function(){this.defaultPrevented=this.cancelable&&!0},a.stopPropagation=function(){this.propagationStopped=!0},a.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},a.remove=function(){this.removed=!0},a.clone=function(){return new Event(this.type,this.bubbles,this.cancelable)},a.set=function(a){for(var b in a)this[b]=a[b];return this},a.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=Event}(),this.createjs=this.createjs||{},function(){"use strict";function ErrorEvent(a,b,c){this.Event_constructor("error"),this.title=a,this.message=b,this.data=c}var a=createjs.extend(ErrorEvent,createjs.Event);a.clone=function(){return new createjs.ErrorEvent(this.title,this.message,this.data)},createjs.ErrorEvent=createjs.promote(ErrorEvent,"Event")}(),this.createjs=this.createjs||{},function(){"use strict";function ProgressEvent(a,b){this.Event_constructor("progress"),this.loaded=a,this.total=null==b?1:b,this.progress=0==b?0:this.loaded/this.total}var a=createjs.extend(ProgressEvent,createjs.Event);a.clone=function(){return new createjs.ProgressEvent(this.loaded,this.total)},createjs.ProgressEvent=createjs.promote(ProgressEvent,"Event")}(window),this.createjs=this.createjs||{},function(){"use strict";function LoadItem(){this.src=null,this.type=null,this.id=null,this.maintainOrder=!1,this.callback=null,this.data=null,this.method=createjs.Methods.GET,this.values=null,this.headers=null,this.withCredentials=!1,this.mimeType=null,this.crossOrigin=null,this.loadTimeout=b.LOAD_TIMEOUT_DEFAULT}var a=LoadItem.prototype={},b=LoadItem;b.LOAD_TIMEOUT_DEFAULT=8e3,b.create=function(a){if("string"==typeof a){var c=new LoadItem;return c.src=a,c}if(a instanceof b)return a;if(a instanceof Object&&a.src)return null==a.loadTimeout&&(a.loadTimeout=b.LOAD_TIMEOUT_DEFAULT),a;throw new Error("Type not recognized.")},a.set=function(a){for(var b in a)this[b]=a[b];return this},createjs.LoadItem=b}(),this.createjs=this.createjs||{},function(){var a={};a.POST="POST",a.GET="GET",createjs.Methods=a}(),this.createjs=this.createjs||{},function(){var a={};a.BINARY="binary",a.CSS="css",a.FONT="font",a.FONTCSS="fontcss",a.IMAGE="image",a.JAVASCRIPT="javascript",a.JSON="json",a.JSONP="jsonp",a.MANIFEST="manifest",a.SOUND="sound",a.VIDEO="video",a.SPRITESHEET="spritesheet",a.SVG="svg",a.TEXT="text",a.XML="xml",createjs.Types=a}(),function(){var a={};a.a=function(){return a.el("a")},a.svg=function(){return a.el("svg")},a.object=function(){return a.el("object")},a.image=function(){return a.el("image")},a.img=function(){return a.el("img")},a.style=function(){return a.el("style")},a.link=function(){return a.el("link")},a.script=function(){return a.el("script")},a.audio=function(){return a.el("audio")},a.video=function(){return a.el("video")},a.text=function(a){return document.createTextNode(a)},a.el=function(a){return document.createElement(a)},createjs.Elements=a}(),function(){var a={container:null};a.appendToHead=function(b){a.getHead().appendChild(b)},a.appendToBody=function(b){if(null==a.container){a.container=document.createElement("div"),a.container.id="preloadjs-container";var c=a.container.style;c.visibility="hidden",c.position="absolute",c.width=a.container.style.height="10px",c.overflow="hidden",c.transform=c.msTransform=c.webkitTransform=c.oTransform="translate(-10px, -10px)",a.getBody().appendChild(a.container)}a.container.appendChild(b)},a.getHead=function(){return document.head||document.getElementsByTagName("head")[0]},a.getBody=function(){return document.body||document.getElementsByTagName("body")[0]},a.removeChild=function(a){a.parent&&a.parent.removeChild(a)},a.isImageTag=function(a){return a instanceof HTMLImageElement},a.isAudioTag=function(a){return window.HTMLAudioElement?a instanceof HTMLAudioElement:!1},a.isVideoTag=function(a){return window.HTMLVideoElement?a instanceof HTMLVideoElement:!1},createjs.DomUtils=a}(),function(){var a={};a.isBinary=function(a){switch(a){case createjs.Types.IMAGE:case createjs.Types.BINARY:return!0;default:return!1}},a.isText=function(a){switch(a){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!0;default:return!1}},a.getTypeByExtension=function(a){if(null==a)return createjs.Types.TEXT;switch(a.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=a}(),function(){var a={};a.ABSOLUTE_PATT=/^(?:\w+:)?\/{2}/i,a.RELATIVE_PATT=/^[.\/]*?\//i,a.EXTENSION_PATT=/\/?[^\/]+\.(\w{1,5})$/i,a.parseURI=function(b){var c={absolute:!1,relative:!1,protocol:null,hostname:null,port:null,pathname:null,search:null,hash:null,host:null};if(null==b)return c;var d=createjs.Elements.a();d.href=b;for(var e in c)e in d&&(c[e]=d[e]);var f=b.indexOf("?");f>-1&&(b=b.substr(0,f));var g;return a.ABSOLUTE_PATT.test(b)?c.absolute=!0:a.RELATIVE_PATT.test(b)&&(c.relative=!0),(g=b.match(a.EXTENSION_PATT))&&(c.extension=g[1].toLowerCase()),c},a.formatQueryString=function(a,b){if(null==a)throw new Error("You must specify data.");var c=[];for(var d in a)c.push(d+"="+escape(a[d]));return b&&(c=c.concat(b)),c.join("&")},a.buildURI=function(a,b){if(null==b)return a;var c=[],d=a.indexOf("?");if(-1!=d){var e=a.slice(d+1);c=c.concat(e.split("&"))}return-1!=d?a.slice(0,d)+"?"+this.formatQueryString(b,c):a+"?"+this.formatQueryString(b,c)},a.isCrossDomain=function(a){var b=createjs.Elements.a();b.href=a.src;var c=createjs.Elements.a();c.href=location.href;var d=""!=b.hostname&&(b.port!=c.port||b.protocol!=c.protocol||b.hostname!=c.hostname);return d},a.isLocal=function(a){var b=createjs.Elements.a();return b.href=a.src,""==b.hostname&&"file:"==b.protocol},createjs.URLUtils=a}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractLoader(a,b,c){this.EventDispatcher_constructor(),this.loaded=!1,this.canceled=!1,this.progress=0,this.type=c,this.resultFormatter=null,this._item=a?createjs.LoadItem.create(a):null,this._preferXHR=b,this._result=null,this._rawResult=null,this._loadedItems=null,this._tagSrcAttribute=null,this._tag=null}var a=createjs.extend(AbstractLoader,createjs.EventDispatcher),b=AbstractLoader;try{Object.defineProperties(b,{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(c){}a.getItem=function(){return this._item},a.getResult=function(a){return a?this._rawResult:this._result},a.getTag=function(){return this._tag},a.setTag=function(a){this._tag=a},a.load=function(){this._createRequest(),this._request.on("complete",this,this),this._request.on("progress",this,this),this._request.on("loadStart",this,this),this._request.on("abort",this,this),this._request.on("timeout",this,this),this._request.on("error",this,this);var a=new createjs.Event("initialize");a.loader=this._request,this.dispatchEvent(a),this._request.load()},a.cancel=function(){this.canceled=!0,this.destroy()},a.destroy=function(){this._request&&(this._request.removeAllEventListeners(),this._request.destroy()),this._request=null,this._item=null,this._rawResult=null,this._result=null,this._loadItems=null,this.removeAllEventListeners()},a.getLoadedItems=function(){return this._loadedItems},a._createRequest=function(){this._request=this._preferXHR?new createjs.XHRRequest(this._item):new createjs.TagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},a._createTag=function(){return null},a._sendLoadStart=function(){this._isCanceled()||this.dispatchEvent("loadstart")},a._sendProgress=function(a){if(!this._isCanceled()){var b=null;"number"==typeof a?(this.progress=a,b=new createjs.ProgressEvent(this.progress)):(b=a,this.progress=a.loaded/a.total,b.progress=this.progress,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0)),this.hasEventListener("progress")&&this.dispatchEvent(b)}},a._sendComplete=function(){if(!this._isCanceled()){this.loaded=!0;var a=new createjs.Event("complete");a.rawResult=this._rawResult,null!=this._result&&(a.result=this._result),this.dispatchEvent(a)}},a._sendError=function(a){!this._isCanceled()&&this.hasEventListener("error")&&(null==a&&(a=new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY")),this.dispatchEvent(a))},a._isCanceled=function(){return null==window.createjs||this.canceled?!0:!1},a.resultFormatter=null,a.handleEvent=function(a){switch(a.type){case"complete":this._rawResult=a.target._response;var b=this.resultFormatter&&this.resultFormatter(this);b instanceof Function?b.call(this,createjs.proxy(this._resultFormatSuccess,this),createjs.proxy(this._resultFormatFailed,this)):(this._result=b||this._rawResult,this._sendComplete());break;case"progress":this._sendProgress(a);break;case"error":this._sendError(a);break;case"loadstart":this._sendLoadStart();break;case"abort":case"timeout":this._isCanceled()||this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_"+a.type.toUpperCase()+"_ERROR"))}},a._resultFormatSuccess=function(a){this._result=a,this._sendComplete()},a._resultFormatFailed=function(a){this._sendError(a)},a.toString=function(){return"[PreloadJS AbstractLoader]"},createjs.AbstractLoader=createjs.promote(AbstractLoader,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractMediaLoader(a,b,c){this.AbstractLoader_constructor(a,b,c),this.resultFormatter=this._formatResult,this._tagSrcAttribute="src",this.on("initialize",this._updateXHR,this)}var a=createjs.extend(AbstractMediaLoader,createjs.AbstractLoader);a.load=function(){this._tag||(this._tag=this._createTag(this._item.src)),this._tag.preload="auto",this._tag.load(),this.AbstractLoader_load()},a._createTag=function(){},a._createRequest=function(){this._request=this._preferXHR?new createjs.XHRRequest(this._item):new createjs.MediaTagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},a._updateXHR=function(a){a.loader.setResponseType&&a.loader.setResponseType("blob")},a._formatResult=function(a){if(this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.onstalled=null,this._preferXHR){var b=window.URL||window.webkitURL,c=a.getResult(!0);a.getTag().src=b.createObjectURL(c)}return a.getTag()},createjs.AbstractMediaLoader=createjs.promote(AbstractMediaLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";var AbstractRequest=function(a){this._item=a},a=createjs.extend(AbstractRequest,createjs.EventDispatcher);a.load=function(){},a.destroy=function(){},a.cancel=function(){},createjs.AbstractRequest=createjs.promote(AbstractRequest,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function TagRequest(a,b,c){this.AbstractRequest_constructor(a),this._tag=b,this._tagSrcAttribute=c,this._loadedHandler=createjs.proxy(this._handleTagComplete,this),this._addedToDOM=!1}var a=createjs.extend(TagRequest,createjs.AbstractRequest);a.load=function(){this._tag.onload=createjs.proxy(this._handleTagComplete,this),this._tag.onreadystatechange=createjs.proxy(this._handleReadyStateChange,this),this._tag.onerror=createjs.proxy(this._handleError,this);var a=new createjs.Event("initialize");a.loader=this._tag,this.dispatchEvent(a),this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout),this._tag[this._tagSrcAttribute]=this._item.src,null==this._tag.parentNode&&(createjs.DomUtils.appendToBody(this._tag),this._addedToDOM=!0)},a.destroy=function(){this._clean(),this._tag=null,this.AbstractRequest_destroy()},a._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},a._handleError=function(){this._clean(),this.dispatchEvent("error")},a._handleTagComplete=function(){this._rawResult=this._tag,this._result=this.resultFormatter&&this.resultFormatter(this)||this._rawResult,this._clean(),this.dispatchEvent("complete")},a._handleTimeout=function(){this._clean(),this.dispatchEvent(new createjs.Event("timeout"))},a._clean=function(){this._tag.onload=null,this._tag.onreadystatechange=null,this._tag.onerror=null,this._addedToDOM&&null!=this._tag.parentNode&&this._tag.parentNode.removeChild(this._tag),clearTimeout(this._loadTimeout)},a._handleStalled=function(){},createjs.TagRequest=createjs.promote(TagRequest,"AbstractRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function MediaTagRequest(a,b,c){this.AbstractRequest_constructor(a),this._tag=b,this._tagSrcAttribute=c,this._loadedHandler=createjs.proxy(this._handleTagComplete,this)}var a=createjs.extend(MediaTagRequest,createjs.TagRequest);a.load=function(){var a=createjs.proxy(this._handleStalled,this);this._stalledCallback=a;var b=createjs.proxy(this._handleProgress,this);this._handleProgress=b,this._tag.addEventListener("stalled",a),this._tag.addEventListener("progress",b),this._tag.addEventListener&&this._tag.addEventListener("canplaythrough",this._loadedHandler,!1),this.TagRequest_load()},a._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},a._handleStalled=function(){},a._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.ProgressEvent(a.loaded,a.total);this.dispatchEvent(b)}},a._clean=function(){this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.removeEventListener("stalled",this._stalledCallback),this._tag.removeEventListener("progress",this._progressCallback),this.TagRequest__clean()},createjs.MediaTagRequest=createjs.promote(MediaTagRequest,"TagRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function XHRRequest(a){this.AbstractRequest_constructor(a),this._request=null,this._loadTimeout=null,this._xhrLevel=1,this._response=null,this._rawResponse=null,this._canceled=!1,this._handleLoadStartProxy=createjs.proxy(this._handleLoadStart,this),this._handleProgressProxy=createjs.proxy(this._handleProgress,this),this._handleAbortProxy=createjs.proxy(this._handleAbort,this),this._handleErrorProxy=createjs.proxy(this._handleError,this),this._handleTimeoutProxy=createjs.proxy(this._handleTimeout,this),this._handleLoadProxy=createjs.proxy(this._handleLoad,this),this._handleReadyStateChangeProxy=createjs.proxy(this._handleReadyStateChange,this),!this._createXHR(a)}var a=createjs.extend(XHRRequest,createjs.AbstractRequest);XHRRequest.ACTIVEX_VERSIONS=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],a.getResult=function(a){return a&&this._rawResponse?this._rawResponse:this._response},a.cancel=function(){this.canceled=!0,this._clean(),this._request.abort()},a.load=function(){if(null==this._request)return void this._handleError();null!=this._request.addEventListener?(this._request.addEventListener("loadstart",this._handleLoadStartProxy,!1),this._request.addEventListener("progress",this._handleProgressProxy,!1),this._request.addEventListener("abort",this._handleAbortProxy,!1),this._request.addEventListener("error",this._handleErrorProxy,!1),this._request.addEventListener("timeout",this._handleTimeoutProxy,!1),this._request.addEventListener("load",this._handleLoadProxy,!1),this._request.addEventListener("readystatechange",this._handleReadyStateChangeProxy,!1)):(this._request.onloadstart=this._handleLoadStartProxy,this._request.onprogress=this._handleProgressProxy,this._request.onabort=this._handleAbortProxy,this._request.onerror=this._handleErrorProxy,this._request.ontimeout=this._handleTimeoutProxy,this._request.onload=this._handleLoadProxy,this._request.onreadystatechange=this._handleReadyStateChangeProxy),1==this._xhrLevel&&(this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout));try{this._item.values?this._request.send(createjs.URLUtils.formatQueryString(this._item.values)):this._request.send()}catch(a){this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND",null,a))}},a.setResponseType=function(a){"blob"===a&&(a=window.URL?"blob":"arraybuffer",this._responseType=a),this._request.responseType=a},a.getAllResponseHeaders=function(){return this._request.getAllResponseHeaders instanceof Function?this._request.getAllResponseHeaders():null},a.getResponseHeader=function(a){return this._request.getResponseHeader instanceof Function?this._request.getResponseHeader(a):null},a._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.ProgressEvent(a.loaded,a.total);this.dispatchEvent(b)}},a._handleLoadStart=function(){clearTimeout(this._loadTimeout),this.dispatchEvent("loadstart")},a._handleAbort=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED",null,a))},a._handleError=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent(a.message))},a._handleReadyStateChange=function(){4==this._request.readyState&&this._handleLoad()},a._handleLoad=function(){if(!this.loaded){this.loaded=!0;var a=this._checkError();if(a)return void this._handleError(a);if(this._response=this._getResponse(),"arraybuffer"===this._responseType)try{this._response=new Blob([this._response])}catch(b){if(window.BlobBuilder=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,"TypeError"===b.name&&window.BlobBuilder){var c=new BlobBuilder;c.append(this._response),this._response=c.getBlob()}}this._clean(),this.dispatchEvent(new createjs.Event("complete"))}},a._handleTimeout=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT",null,a))},a._checkError=function(){var a=parseInt(this._request.status);return a>=400&&599>=a?new Error(a):0==a&&/^https?:/.test(location.protocol)?new Error(0):null},a._getResponse=function(){if(null!=this._response)return this._response;if(null!=this._request.response)return this._request.response;try{if(null!=this._request.responseText)return this._request.responseText}catch(a){}try{if(null!=this._request.responseXML)return this._request.responseXML}catch(a){}return null},a._createXHR=function(a){var b=createjs.URLUtils.isCrossDomain(a),c={},d=null;if(window.XMLHttpRequest)d=new XMLHttpRequest,b&&void 0===d.withCredentials&&window.XDomainRequest&&(d=new XDomainRequest);else{for(var e=0,f=s.ACTIVEX_VERSIONS.length;f>e;e++){var g=s.ACTIVEX_VERSIONS[e];try{d=new ActiveXObject(g);break}catch(h){}}if(null==d)return!1}null==a.mimeType&&createjs.RequestUtils.isText(a.type)&&(a.mimeType="text/plain; charset=utf-8"),a.mimeType&&d.overrideMimeType&&d.overrideMimeType(a.mimeType),this._xhrLevel="string"==typeof d.responseType?2:1;var i=null;if(i=a.method==createjs.Methods.GET?createjs.URLUtils.buildURI(a.src,a.values):a.src,d.open(a.method||createjs.Methods.GET,i,!0),b&&d instanceof XMLHttpRequest&&1==this._xhrLevel&&(c.Origin=location.origin),a.values&&a.method==createjs.Methods.POST&&(c["Content-Type"]="application/x-www-form-urlencoded"),b||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest"),a.headers)for(var j in a.headers)c[j]=a.headers[j];for(j in c)d.setRequestHeader(j,c[j]);return d instanceof XMLHttpRequest&&void 0!==a.withCredentials&&(d.withCredentials=a.withCredentials),this._request=d,!0},a._clean=function(){clearTimeout(this._loadTimeout),null!=this._request.removeEventListener?(this._request.removeEventListener("loadstart",this._handleLoadStartProxy),this._request.removeEventListener("progress",this._handleProgressProxy),this._request.removeEventListener("abort",this._handleAbortProxy),this._request.removeEventListener("error",this._handleErrorProxy),this._request.removeEventListener("timeout",this._handleTimeoutProxy),this._request.removeEventListener("load",this._handleLoadProxy),this._request.removeEventListener("readystatechange",this._handleReadyStateChangeProxy)):(this._request.onloadstart=null,this._request.onprogress=null,this._request.onabort=null,this._request.onerror=null,this._request.ontimeout=null,this._request.onload=null,this._request.onreadystatechange=null)},a.toString=function(){return"[PreloadJS XHRRequest]"},createjs.XHRRequest=createjs.promote(XHRRequest,"AbstractRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function SoundLoader(a,b){this.AbstractMediaLoader_constructor(a,b,createjs.Types.SOUND),createjs.DomUtils.isAudioTag(a)?this._tag=a:createjs.DomUtils.isAudioTag(a.src)?this._tag=a:createjs.DomUtils.isAudioTag(a.tag)&&(this._tag=createjs.DomUtils.isAudioTag(a)?a:a.src),null!=this._tag&&(this._preferXHR=!1)}var a=createjs.extend(SoundLoader,createjs.AbstractMediaLoader),b=SoundLoader;b.canLoadItem=function(a){return a.type==createjs.Types.SOUND},a._createTag=function(a){var b=createjs.Elements.audio();return b.autoplay=!1,b.preload="none",b.src=a,b},createjs.SoundLoader=createjs.promote(SoundLoader,"AbstractMediaLoader")}(),this.createjs=this.createjs||{},function(){"use strict";var PlayPropsConfig=function(){this.interrupt=null,this.delay=null,this.offset=null,this.loop=null,this.volume=null,this.pan=null,this.startTime=null,this.duration=null},a=PlayPropsConfig.prototype={},b=PlayPropsConfig;b.create=function(a){if("string"==typeof a)return console&&(console.warn||console.log)("Deprecated behaviour. Sound.play takes a configuration object instead of individual arguments. See docs for info."),(new createjs.PlayPropsConfig).set({interrupt:a});if(null==a||a instanceof b||a instanceof Object)return(new createjs.PlayPropsConfig).set(a);if(null==a)throw new Error("PlayProps configuration not recognized.")},a.set=function(a){if(null!=a)for(var b in a)this[b]=a[b];return this},a.toString=function(){return"[PlayPropsConfig]"},createjs.PlayPropsConfig=b}(),this.createjs=this.createjs||{},function(){"use strict";function Sound(){throw"Sound cannot be instantiated"}function a(a,b){this.init(a,b)}var b=Sound;b.INTERRUPT_ANY="any",b.INTERRUPT_EARLY="early",b.INTERRUPT_LATE="late",b.INTERRUPT_NONE="none",b.PLAY_INITED="playInited",b.PLAY_SUCCEEDED="playSucceeded",b.PLAY_INTERRUPTED="playInterrupted",b.PLAY_FINISHED="playFinished",b.PLAY_FAILED="playFailed",b.SUPPORTED_EXTENSIONS=["mp3","ogg","opus","mpeg","wav","m4a","mp4","aiff","wma","mid"],b.EXTENSION_MAP={m4a:"mp4"},b.FILE_PATTERN=/^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?))?([\/.]*?(?:[^?]+)?\/)?((?:[^\/?]+)\.(\w+))(?:\?(\S+)?)?$/,b.defaultInterruptBehavior=b.INTERRUPT_NONE,b.alternateExtensions=[],b.activePlugin=null,b._masterVolume=1,b._getMasterVolume=function(){return this._masterVolume},b.getVolume=createjs.deprecate(b._getMasterVolume,"Sound.getVolume"),b._setMasterVolume=function(a){if(null!=Number(a)&&(a=Math.max(0,Math.min(1,a)),b._masterVolume=a,!this.activePlugin||!this.activePlugin.setVolume||!this.activePlugin.setVolume(a)))for(var c=this._instances,d=0,e=c.length;e>d;d++)c[d].setMasterVolume(a)},b.setVolume=createjs.deprecate(b._setMasterVolume,"Sound.setVolume"),b._masterMute=!1,b._getMute=function(){return this._masterMute},b.getMute=createjs.deprecate(b._getMute,"Sound.getMute"),b._setMute=function(a){if(null!=a&&(this._masterMute=a,!this.activePlugin||!this.activePlugin.setMute||!this.activePlugin.setMute(a)))for(var b=this._instances,c=0,d=b.length;d>c;c++)b[c].setMasterMute(a)},b.setMute=createjs.deprecate(b._setMute,"Sound.setMute"),b._getCapabilities=function(){return null==b.activePlugin?null:b.activePlugin._capabilities},b.getCapabilities=createjs.deprecate(b._getCapabilities,"Sound.getCapabilities"),Object.defineProperties(b,{volume:{get:b._getMasterVolume,set:b._setMasterVolume},muted:{get:b._getMute,set:b._setMute},capabilities:{get:b._getCapabilities}}),b._pluginsRegistered=!1,b._lastID=0,b._instances=[],b._idHash={},b._preloadHash={},b._defaultPlayPropsHash={},b.addEventListener=null,b.removeEventListener=null,b.removeAllEventListeners=null,b.dispatchEvent=null,b.hasEventListener=null,b._listeners=null,createjs.EventDispatcher.initialize(b),b.getPreloadHandlers=function(){return{callback:createjs.proxy(b.initLoad,b),types:["sound"],extensions:b.SUPPORTED_EXTENSIONS}},b._handleLoadComplete=function(a){var c=a.target.getItem().src;if(b._preloadHash[c])for(var d=0,e=b._preloadHash[c].length;e>d;d++){var f=b._preloadHash[c][d];if(b._preloadHash[c][d]=!0,b.hasEventListener("fileload")){var a=new createjs.Event("fileload");a.src=f.src,a.id=f.id,a.data=f.data,a.sprite=f.sprite,b.dispatchEvent(a)}}},b._handleLoadError=function(a){var c=a.target.getItem().src;if(b._preloadHash[c])for(var d=0,e=b._preloadHash[c].length;e>d;d++){var f=b._preloadHash[c][d];if(b._preloadHash[c][d]=!1,b.hasEventListener("fileerror")){var a=new createjs.Event("fileerror");a.src=f.src,a.id=f.id,a.data=f.data,a.sprite=f.sprite,b.dispatchEvent(a)}}},b._registerPlugin=function(a){return a.isSupported()?(b.activePlugin=new a,!0):!1},b.registerPlugins=function(a){b._pluginsRegistered=!0;for(var c=0,d=a.length;d>c;c++)if(b._registerPlugin(a[c]))return!0;return!1},b.initializeDefaultPlugins=function(){return null!=b.activePlugin?!0:b._pluginsRegistered?!1:b.registerPlugins([createjs.WebAudioPlugin,createjs.HTMLAudioPlugin])?!0:!1},b.isReady=function(){return null!=b.activePlugin},b.initLoad=function(a){return"video"==a.type?!0:b._registerSound(a)},b._registerSound=function(c){if(!b.initializeDefaultPlugins())return!1;var d;if(c.src instanceof Object?(d=b._parseSrc(c.src),d.src=c.path+d.src):d=b._parsePath(c.src),null==d)return!1; +c.src=d.src,c.type="sound";var e=c.data,f=null;if(null!=e&&(isNaN(e.channels)?isNaN(e)||(f=parseInt(e)):f=parseInt(e.channels),e.audioSprite))for(var g,h=e.audioSprite.length;h--;)g=e.audioSprite[h],b._idHash[g.id]={src:c.src,startTime:parseInt(g.startTime),duration:parseInt(g.duration)},g.defaultPlayProps&&(b._defaultPlayPropsHash[g.id]=createjs.PlayPropsConfig.create(g.defaultPlayProps));null!=c.id&&(b._idHash[c.id]={src:c.src});var i=b.activePlugin.register(c);return a.create(c.src,f),null!=e&&isNaN(e)?c.data.channels=f||a.maxPerChannel():c.data=f||a.maxPerChannel(),i.type&&(c.type=i.type),c.defaultPlayProps&&(b._defaultPlayPropsHash[c.src]=createjs.PlayPropsConfig.create(c.defaultPlayProps)),i},b.registerSound=function(a,c,d,e,f){var g={src:a,id:c,data:d,defaultPlayProps:f};a instanceof Object&&a.src&&(e=c,g=a),g=createjs.LoadItem.create(g),g.path=e,null==e||g.src instanceof Object||(g.src=e+g.src);var h=b._registerSound(g);if(!h)return!1;if(b._preloadHash[g.src]||(b._preloadHash[g.src]=[]),b._preloadHash[g.src].push(g),1==b._preloadHash[g.src].length)h.on("complete",this._handleLoadComplete,this),h.on("error",this._handleLoadError,this),b.activePlugin.preload(h);else if(1==b._preloadHash[g.src][0])return!0;return g},b.registerSounds=function(a,b){var c=[];a.path&&(b?b+=a.path:b=a.path,a=a.manifest);for(var d=0,e=a.length;e>d;d++)c[d]=createjs.Sound.registerSound(a[d].src,a[d].id,a[d].data,b,a[d].defaultPlayProps);return c},b.removeSound=function(c,d){if(null==b.activePlugin)return!1;c instanceof Object&&c.src&&(c=c.src);var e;if(c instanceof Object?e=b._parseSrc(c):(c=b._getSrcById(c).src,e=b._parsePath(c)),null==e)return!1;c=e.src,null!=d&&(c=d+c);for(var f in b._idHash)b._idHash[f].src==c&&delete b._idHash[f];return a.removeSrc(c),delete b._preloadHash[c],b.activePlugin.removeSound(c),!0},b.removeSounds=function(a,b){var c=[];a.path&&(b?b+=a.path:b=a.path,a=a.manifest);for(var d=0,e=a.length;e>d;d++)c[d]=createjs.Sound.removeSound(a[d].src,b);return c},b.removeAllSounds=function(){b._idHash={},b._preloadHash={},a.removeAll(),b.activePlugin&&b.activePlugin.removeAllSounds()},b.loadComplete=function(a){if(!b.isReady())return!1;var c=b._parsePath(a);return a=c?b._getSrcById(c.src).src:b._getSrcById(a).src,void 0==b._preloadHash[a]?!1:1==b._preloadHash[a][0]},b._parsePath=function(a){"string"!=typeof a&&(a=a.toString());var c=a.match(b.FILE_PATTERN);if(null==c)return!1;for(var d=c[4],e=c[5],f=b.capabilities,g=0;!f[e];)if(e=b.alternateExtensions[g++],g>b.alternateExtensions.length)return null;a=a.replace("."+c[5],"."+e);var h={name:d,src:a,extension:e};return h},b._parseSrc=function(a){var c={name:void 0,src:void 0,extension:void 0},d=b.capabilities;for(var e in a)if(a.hasOwnProperty(e)&&d[e]){c.src=a[e],c.extension=e;break}if(!c.src)return!1;var f=c.src.lastIndexOf("/");return c.name=-1!=f?c.src.slice(f+1):c.src,c},b.play=function(a,c){var d=createjs.PlayPropsConfig.create(c),e=b.createInstance(a,d.startTime,d.duration),f=b._playInstance(e,d);return f||e._playFailed(),e},b.createInstance=function(c,d,e){if(!b.initializeDefaultPlugins())return new createjs.DefaultSoundInstance(c,d,e);var f=b._defaultPlayPropsHash[c];c=b._getSrcById(c);var g=b._parsePath(c.src),h=null;return null!=g&&null!=g.src?(a.create(g.src),null==d&&(d=c.startTime),h=b.activePlugin.create(g.src,d,e||c.duration),f=f||b._defaultPlayPropsHash[g.src],f&&h.applyPlayProps(f)):h=new createjs.DefaultSoundInstance(c,d,e),h.uniqueId=b._lastID++,h},b.stop=function(){for(var a=this._instances,b=a.length;b--;)a[b].stop()},b.setDefaultPlayProps=function(a,c){a=b._getSrcById(a),b._defaultPlayPropsHash[b._parsePath(a.src).src]=createjs.PlayPropsConfig.create(c)},b.getDefaultPlayProps=function(a){return a=b._getSrcById(a),b._defaultPlayPropsHash[b._parsePath(a.src).src]},b._playInstance=function(a,c){var d=b._defaultPlayPropsHash[a.src]||{};if(null==c.interrupt&&(c.interrupt=d.interrupt||b.defaultInterruptBehavior),null==c.delay&&(c.delay=d.delay||0),null==c.offset&&(c.offset=a.position),null==c.loop&&(c.loop=a.loop),null==c.volume&&(c.volume=a.volume),null==c.pan&&(c.pan=a.pan),0==c.delay){var e=b._beginPlaying(a,c);if(!e)return!1}else{var f=setTimeout(function(){b._beginPlaying(a,c)},c.delay);a.delayTimeoutId=f}return this._instances.push(a),!0},b._beginPlaying=function(b,c){if(!a.add(b,c.interrupt))return!1;var d=b._beginPlaying(c);if(!d){var e=createjs.indexOf(this._instances,b);return e>-1&&this._instances.splice(e,1),!1}return!0},b._getSrcById=function(a){return b._idHash[a]||{src:a}},b._playFinished=function(b){a.remove(b);var c=createjs.indexOf(this._instances,b);c>-1&&this._instances.splice(c,1)},createjs.Sound=Sound,a.channels={},a.create=function(b,c){var d=a.get(b);return null==d?(a.channels[b]=new a(b,c),!0):!1},a.removeSrc=function(b){var c=a.get(b);return null==c?!1:(c._removeAll(),delete a.channels[b],!0)},a.removeAll=function(){for(var b in a.channels)a.channels[b]._removeAll();a.channels={}},a.add=function(b,c){var d=a.get(b.src);return null==d?!1:d._add(b,c)},a.remove=function(b){var c=a.get(b.src);return null==c?!1:(c._remove(b),!0)},a.maxPerChannel=function(){return c.maxDefault},a.get=function(b){return a.channels[b]};var c=a.prototype;c.constructor=a,c.src=null,c.max=null,c.maxDefault=100,c.length=0,c.init=function(a,b){this.src=a,this.max=b||this.maxDefault,-1==this.max&&(this.max=this.maxDefault),this._instances=[]},c._get=function(a){return this._instances[a]},c._add=function(a,b){return this._getSlot(b,a)?(this._instances.push(a),this.length++,!0):!1},c._remove=function(a){var b=createjs.indexOf(this._instances,a);return-1==b?!1:(this._instances.splice(b,1),this.length--,!0)},c._removeAll=function(){for(var a=this.length-1;a>=0;a--)this._instances[a].stop()},c._getSlot=function(a){var b,c;if(a!=Sound.INTERRUPT_NONE&&(c=this._get(0),null==c))return!0;for(var d=0,e=this.max;e>d;d++){if(b=this._get(d),null==b)return!0;if(b.playState==Sound.PLAY_FINISHED||b.playState==Sound.PLAY_INTERRUPTED||b.playState==Sound.PLAY_FAILED){c=b;break}a!=Sound.INTERRUPT_NONE&&(a==Sound.INTERRUPT_EARLY&&b.positionc.position)&&(c=b)}return null!=c?(c._interrupt(),this._remove(c),!0):!1},c.toString=function(){return"[Sound SoundChannel]"}}(),this.createjs=this.createjs||{},function(){"use strict";var AbstractSoundInstance=function(a,b,c,d){this.EventDispatcher_constructor(),this.src=a,this.uniqueId=-1,this.playState=null,this.delayTimeoutId=null,this._volume=1,Object.defineProperty(this,"volume",{get:this._getVolume,set:this._setVolume}),this._pan=0,Object.defineProperty(this,"pan",{get:this._getPan,set:this._setPan}),this._startTime=Math.max(0,b||0),Object.defineProperty(this,"startTime",{get:this._getStartTime,set:this._setStartTime}),this._duration=Math.max(0,c||0),Object.defineProperty(this,"duration",{get:this._getDuration,set:this._setDuration}),this._playbackResource=null,Object.defineProperty(this,"playbackResource",{get:this._getPlaybackResource,set:this._setPlaybackResource}),d!==!1&&d!==!0&&this._setPlaybackResource(d),this._position=0,Object.defineProperty(this,"position",{get:this._getPosition,set:this._setPosition}),this._loop=0,Object.defineProperty(this,"loop",{get:this._getLoop,set:this._setLoop}),this._muted=!1,Object.defineProperty(this,"muted",{get:this._getMuted,set:this._setMuted}),this._paused=!1,Object.defineProperty(this,"paused",{get:this._getPaused,set:this._setPaused})},a=createjs.extend(AbstractSoundInstance,createjs.EventDispatcher);a.play=function(a){var b=createjs.PlayPropsConfig.create(a);return this.playState==createjs.Sound.PLAY_SUCCEEDED?(this.applyPlayProps(b),void(this._paused&&this._setPaused(!1))):(this._cleanUp(),createjs.Sound._playInstance(this,b),this)},a.stop=function(){return this._position=0,this._paused=!1,this._handleStop(),this._cleanUp(),this.playState=createjs.Sound.PLAY_FINISHED,this},a.destroy=function(){this._cleanUp(),this.src=null,this.playbackResource=null,this.removeAllEventListeners()},a.applyPlayProps=function(a){return null!=a.offset&&this._setPosition(a.offset),null!=a.loop&&this._setLoop(a.loop),null!=a.volume&&this._setVolume(a.volume),null!=a.pan&&this._setPan(a.pan),null!=a.startTime&&(this._setStartTime(a.startTime),this._setDuration(a.duration)),this},a.toString=function(){return"[AbstractSoundInstance]"},a._getPaused=function(){return this._paused},a._setPaused=function(a){return a!==!0&&a!==!1||this._paused==a||1==a&&this.playState!=createjs.Sound.PLAY_SUCCEEDED?void 0:(this._paused=a,a?this._pause():this._resume(),clearTimeout(this.delayTimeoutId),this)},a._setVolume=function(a){return a==this._volume?this:(this._volume=Math.max(0,Math.min(1,a)),this._muted||this._updateVolume(),this)},a._getVolume=function(){return this._volume},a._setMuted=function(a){return a===!0||a===!1?(this._muted=a,this._updateVolume(),this):void 0},a._getMuted=function(){return this._muted},a._setPan=function(a){return a==this._pan?this:(this._pan=Math.max(-1,Math.min(1,a)),this._updatePan(),this)},a._getPan=function(){return this._pan},a._getPosition=function(){return this._paused||this.playState!=createjs.Sound.PLAY_SUCCEEDED||(this._position=this._calculateCurrentPosition()),this._position},a._setPosition=function(a){return this._position=Math.max(0,a),this.playState==createjs.Sound.PLAY_SUCCEEDED&&this._updatePosition(),this},a._getStartTime=function(){return this._startTime},a._setStartTime=function(a){return a==this._startTime?this:(this._startTime=Math.max(0,a||0),this._updateStartTime(),this)},a._getDuration=function(){return this._duration},a._setDuration=function(a){return a==this._duration?this:(this._duration=Math.max(0,a||0),this._updateDuration(),this)},a._setPlaybackResource=function(a){return this._playbackResource=a,0==this._duration&&this._playbackResource&&this._setDurationFromSource(),this},a._getPlaybackResource=function(){return this._playbackResource},a._getLoop=function(){return this._loop},a._setLoop=function(a){null!=this._playbackResource&&(0!=this._loop&&0==a?this._removeLooping(a):0==this._loop&&0!=a&&this._addLooping(a)),this._loop=a},a._sendEvent=function(a){var b=new createjs.Event(a);this.dispatchEvent(b)},a._cleanUp=function(){clearTimeout(this.delayTimeoutId),this._handleCleanUp(),this._paused=!1,createjs.Sound._playFinished(this)},a._interrupt=function(){this._cleanUp(),this.playState=createjs.Sound.PLAY_INTERRUPTED,this._sendEvent("interrupted")},a._beginPlaying=function(a){return this._setPosition(a.offset),this._setLoop(a.loop),this._setVolume(a.volume),this._setPan(a.pan),null!=a.startTime&&(this._setStartTime(a.startTime),this._setDuration(a.duration)),null!=this._playbackResource&&this._positionc;c++){var e=this._soundInstances[b][c];e.setPlaybackResource(this._audioSources[b]),this._soundInstances[b]=null}},a._handlePreloadError=function(){},a._updateVolume=function(){},createjs.AbstractPlugin=AbstractPlugin}(),this.createjs=this.createjs||{},function(){"use strict";function a(a){this.AbstractLoader_constructor(a,!0,createjs.Types.SOUND)}var b=createjs.extend(a,createjs.AbstractLoader);a.context=null,b.toString=function(){return"[WebAudioLoader]"},b._createRequest=function(){this._request=new createjs.XHRRequest(this._item,!1),this._request.setResponseType("arraybuffer")},b._sendComplete=function(){a.context.decodeAudioData(this._rawResult,createjs.proxy(this._handleAudioDecoded,this),createjs.proxy(this._sendError,this))},b._handleAudioDecoded=function(a){this._result=a,this.AbstractLoader__sendComplete()},createjs.WebAudioLoader=createjs.promote(a,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function WebAudioSoundInstance(a,c,d,e){this.AbstractSoundInstance_constructor(a,c,d,e),this.gainNode=b.context.createGain(),this.panNode=b.context.createPanner(),this.panNode.panningModel=b._panningModel,this.panNode.connect(this.gainNode),this._updatePan(),this.sourceNode=null,this._soundCompleteTimeout=null,this._sourceNodeNext=null,this._playbackStartTime=0,this._endedHandler=createjs.proxy(this._handleSoundComplete,this)}var a=createjs.extend(WebAudioSoundInstance,createjs.AbstractSoundInstance),b=WebAudioSoundInstance;b.context=null,b._scratchBuffer=null,b.destinationNode=null,b._panningModel="equalpower",a.destroy=function(){this.AbstractSoundInstance_destroy(),this.panNode.disconnect(0),this.panNode=null,this.gainNode.disconnect(0),this.gainNode=null},a.toString=function(){return"[WebAudioSoundInstance]"},a._updatePan=function(){this.panNode.setPosition(this._pan,0,-.5)},a._removeLooping=function(){this._sourceNodeNext=this._cleanUpAudioNode(this._sourceNodeNext)},a._addLooping=function(){this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this._sourceNodeNext=this._createAndPlayAudioNode(this._playbackStartTime,0))},a._setDurationFromSource=function(){this._duration=1e3*this.playbackResource.duration},a._handleCleanUp=function(){this.sourceNode&&this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this.sourceNode=this._cleanUpAudioNode(this.sourceNode),this._sourceNodeNext=this._cleanUpAudioNode(this._sourceNodeNext)),0!=this.gainNode.numberOfOutputs&&this.gainNode.disconnect(0),clearTimeout(this._soundCompleteTimeout),this._playbackStartTime=0},a._cleanUpAudioNode=function(a){if(a){if(a.stop(0),a.disconnect(0),createjs.BrowserDetect.isIOS)try{a.buffer=b._scratchBuffer}catch(c){}a=null}return a},a._handleSoundReady=function(){this.gainNode.connect(b.destinationNode);var a=.001*this._duration,c=Math.min(.001*Math.max(0,this._position),a);this.sourceNode=this._createAndPlayAudioNode(b.context.currentTime-a,c),this._playbackStartTime=this.sourceNode.startTime-c,this._soundCompleteTimeout=setTimeout(this._endedHandler,1e3*(a-c)),0!=this._loop&&(this._sourceNodeNext=this._createAndPlayAudioNode(this._playbackStartTime,0))},a._createAndPlayAudioNode=function(a,c){var d=b.context.createBufferSource();d.buffer=this.playbackResource,d.connect(this.panNode);var e=.001*this._duration;return d.startTime=a+e,d.start(d.startTime,c+.001*this._startTime,e-c),d},a._pause=function(){this._position=1e3*(b.context.currentTime-this._playbackStartTime),this.sourceNode=this._cleanUpAudioNode(this.sourceNode),this._sourceNodeNext=this._cleanUpAudioNode(this._sourceNodeNext),0!=this.gainNode.numberOfOutputs&&this.gainNode.disconnect(0),clearTimeout(this._soundCompleteTimeout)},a._resume=function(){this._handleSoundReady()},a._updateVolume=function(){var a=this._muted?0:this._volume;a!=this.gainNode.gain.value&&(this.gainNode.gain.value=a)},a._calculateCurrentPosition=function(){return 1e3*(b.context.currentTime-this._playbackStartTime)},a._updatePosition=function(){this.sourceNode=this._cleanUpAudioNode(this.sourceNode),this._sourceNodeNext=this._cleanUpAudioNode(this._sourceNodeNext),clearTimeout(this._soundCompleteTimeout),this._paused||this._handleSoundReady()},a._handleLoop=function(){this._cleanUpAudioNode(this.sourceNode),this.sourceNode=this._sourceNodeNext,this._playbackStartTime=this.sourceNode.startTime,this._sourceNodeNext=this._createAndPlayAudioNode(this._playbackStartTime,0),this._soundCompleteTimeout=setTimeout(this._endedHandler,this._duration)},a._updateDuration=function(){this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this._pause(),this._resume())},createjs.WebAudioSoundInstance=createjs.promote(WebAudioSoundInstance,"AbstractSoundInstance")}(),this.createjs=this.createjs||{},function(){"use strict";function WebAudioPlugin(){this.AbstractPlugin_constructor(),this._panningModel=b._panningModel,this.context=b.context,this.dynamicsCompressorNode=this.context.createDynamicsCompressor(),this.dynamicsCompressorNode.connect(this.context.destination),this.gainNode=this.context.createGain(),this.gainNode.connect(this.dynamicsCompressorNode),createjs.WebAudioSoundInstance.destinationNode=this.gainNode,this._capabilities=b._capabilities,this._loaderClass=createjs.WebAudioLoader,this._soundInstanceClass=createjs.WebAudioSoundInstance,this._addPropsToClasses()}var a=createjs.extend(WebAudioPlugin,createjs.AbstractPlugin),b=WebAudioPlugin;b._capabilities=null,b._panningModel="equalpower",b.context=null,b._scratchBuffer=null,b._unlocked=!1,b.DEFAULT_SAMPLE_RATE=44100,b.isSupported=function(){var a=createjs.BrowserDetect.isIOS||createjs.BrowserDetect.isAndroid||createjs.BrowserDetect.isBlackberry;return"file:"!=location.protocol||a||this._isFileXHRSupported()?(b._generateCapabilities(),null==b.context?!1:!0):!1},b.playEmptySound=function(){if(null!=b.context){var a=b.context.createBufferSource();a.buffer=b._scratchBuffer,a.connect(b.context.destination),a.start(0,0,0)}},b._isFileXHRSupported=function(){var a=!0,b=new XMLHttpRequest;try{b.open("GET","WebAudioPluginTest.fail",!1)}catch(c){return a=!1}b.onerror=function(){a=!1},b.onload=function(){a=404==this.status||200==this.status||0==this.status&&""!=this.response};try{b.send()}catch(c){a=!1}return a},b._generateCapabilities=function(){if(null==b._capabilities){var a=document.createElement("audio");if(null==a.canPlayType)return null;if(null==b.context&&(b.context=b._createAudioContext(),null==b.context))return null;null==b._scratchBuffer&&(b._scratchBuffer=b.context.createBuffer(1,1,22050)),b._compatibilitySetUp(),"ontouchstart"in window&&"running"!=b.context.state&&(b._unlock(),document.addEventListener("mousedown",b._unlock,!0),document.addEventListener("touchstart",b._unlock,!0),document.addEventListener("touchend",b._unlock,!0)),b._capabilities={panning:!0,volume:!0,tracks:-1};for(var c=createjs.Sound.SUPPORTED_EXTENSIONS,d=createjs.Sound.EXTENSION_MAP,e=0,f=c.length;f>e;e++){var g=c[e],h=d[g]||g;b._capabilities[g]="no"!=a.canPlayType("audio/"+g)&&""!=a.canPlayType("audio/"+g)||"no"!=a.canPlayType("audio/"+h)&&""!=a.canPlayType("audio/"+h)}b.context.destination.numberOfChannels<2&&(b._capabilities.panning=!1)}},b._createAudioContext=function(){var a=window.AudioContext||window.webkitAudioContext;if(null==a)return null;var c=new a;if(/(iPhone|iPad)/i.test(navigator.userAgent)&&c.sampleRate!==b.DEFAULT_SAMPLE_RATE){var d=c.createBuffer(1,1,b.DEFAULT_SAMPLE_RATE),e=c.createBufferSource();e.buffer=d,e.connect(c.destination),e.start(0),e.disconnect(),c.close(),c=new a}return c},b._compatibilitySetUp=function(){if(b._panningModel="equalpower",!b.context.createGain){b.context.createGain=b.context.createGainNode;var a=b.context.createBufferSource();a.__proto__.start=a.__proto__.noteGrainOn,a.__proto__.stop=a.__proto__.noteOff,b._panningModel=0}},b._unlock=function(){b._unlocked||(b.playEmptySound(),"running"==b.context.state&&(document.removeEventListener("mousedown",b._unlock,!0),document.removeEventListener("touchend",b._unlock,!0),document.removeEventListener("touchstart",b._unlock,!0),b._unlocked=!0))},a.toString=function(){return"[WebAudioPlugin]"},a._addPropsToClasses=function(){var a=this._soundInstanceClass;a.context=this.context,a._scratchBuffer=b._scratchBuffer,a.destinationNode=this.gainNode,a._panningModel=this._panningModel,this._loaderClass.context=this.context},a._updateVolume=function(){var a=createjs.Sound._masterMute?0:this._volume;a!=this.gainNode.gain.value&&(this.gainNode.gain.value=a)},createjs.WebAudioPlugin=createjs.promote(WebAudioPlugin,"AbstractPlugin")}(),this.createjs=this.createjs||{},function(){"use strict";function HTMLAudioTagPool(){throw"HTMLAudioTagPool cannot be instantiated"}function a(){this._tags=[]}var b=HTMLAudioTagPool;b._tags={},b._tagPool=new a,b._tagUsed={},b.get=function(a){var c=b._tags[a];return null==c?(c=b._tags[a]=b._tagPool.get(),c.src=a):b._tagUsed[a]?(c=b._tagPool.get(),c.src=a):b._tagUsed[a]=!0,c},b.set=function(a,c){c==b._tags[a]?b._tagUsed[a]=!1:b._tagPool.set(c)},b.remove=function(a){var c=b._tags[a];return null==c?!1:(b._tagPool.set(c),delete b._tags[a],delete b._tagUsed[a],!0)},b.getDuration=function(a){var c=b._tags[a];return null!=c&&c.duration?1e3*c.duration:0},createjs.HTMLAudioTagPool=HTMLAudioTagPool;var c=a.prototype;c.constructor=a,c.get=function(){var a;return a=0==this._tags.length?this._createTag():this._tags.pop(),null==a.parentNode&&document.body.appendChild(a),a},c.set=function(a){var b=createjs.indexOf(this._tags,a);-1==b&&(this._tags.src=null,this._tags.push(a))},c.toString=function(){return"[TagPool]"},c._createTag=function(){var a=document.createElement("audio");return a.autoplay=!1,a.preload="none",a}}(),this.createjs=this.createjs||{},function(){"use strict";function HTMLAudioSoundInstance(a,b,c,d){this.AbstractSoundInstance_constructor(a,b,c,d),this._audioSpriteStopTime=null,this._delayTimeoutId=null,this._endedHandler=createjs.proxy(this._handleSoundComplete,this),this._readyHandler=createjs.proxy(this._handleTagReady,this),this._stalledHandler=createjs.proxy(this._playFailed,this),this._audioSpriteEndHandler=createjs.proxy(this._handleAudioSpriteLoop,this),this._loopHandler=createjs.proxy(this._handleSoundComplete,this),c?this._audioSpriteStopTime=.001*(b+c):this._duration=createjs.HTMLAudioTagPool.getDuration(this.src)}var a=createjs.extend(HTMLAudioSoundInstance,createjs.AbstractSoundInstance);a.setMasterVolume=function(){this._updateVolume()},a.setMasterMute=function(){this._updateVolume()},a.toString=function(){return"[HTMLAudioSoundInstance]"},a._removeLooping=function(){null!=this._playbackResource&&(this._playbackResource.loop=!1,this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1))},a._addLooping=function(){null==this._playbackResource||this._audioSpriteStopTime||(this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1),this._playbackResource.loop=!0)},a._handleCleanUp=function(){var a=this._playbackResource;if(null!=a){a.pause(),a.loop=!1,a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED,this._endedHandler,!1),a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_READY,this._readyHandler,!1),a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED,this._stalledHandler,!1),a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1),a.removeEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE,this._audioSpriteEndHandler,!1);try{a.currentTime=this._startTime}catch(b){}createjs.HTMLAudioTagPool.set(this.src,a),this._playbackResource=null}},a._beginPlaying=function(a){return this._playbackResource=createjs.HTMLAudioTagPool.get(this.src),this.AbstractSoundInstance__beginPlaying(a)},a._handleSoundReady=function(){if(4!==this._playbackResource.readyState){var a=this._playbackResource;return a.addEventListener(createjs.HTMLAudioPlugin._AUDIO_READY,this._readyHandler,!1),a.addEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED,this._stalledHandler,!1),a.preload="auto",void a.load()}this._updateVolume(),this._playbackResource.currentTime=.001*(this._startTime+this._position),this._audioSpriteStopTime?this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE,this._audioSpriteEndHandler,!1):(this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED,this._endedHandler,!1),0!=this._loop&&(this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1),this._playbackResource.loop=!0)),this._playbackResource.play()},a._handleTagReady=function(){this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_READY,this._readyHandler,!1),this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED,this._stalledHandler,!1),this._handleSoundReady()},a._pause=function(){this._playbackResource.pause()},a._resume=function(){this._playbackResource.play()},a._updateVolume=function(){if(null!=this._playbackResource){var a=this._muted||createjs.Sound._masterMute?0:this._volume*createjs.Sound._masterVolume;a!=this._playbackResource.volume&&(this._playbackResource.volume=a)}},a._calculateCurrentPosition=function(){return 1e3*this._playbackResource.currentTime-this._startTime},a._updatePosition=function(){this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1),this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._handleSetPositionSeek,!1);try{this._playbackResource.currentTime=.001*(this._position+this._startTime)}catch(a){this._handleSetPositionSeek(null)}},a._handleSetPositionSeek=function(){null!=this._playbackResource&&(this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._handleSetPositionSeek,!1),this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1))},a._handleAudioSpriteLoop=function(){this._playbackResource.currentTime<=this._audioSpriteStopTime||(this._playbackResource.pause(),0==this._loop?this._handleSoundComplete(null):(this._position=0,this._loop--,this._playbackResource.currentTime=.001*this._startTime,this._paused||this._playbackResource.play(),this._sendEvent("loop")))},a._handleLoop=function(){0==this._loop&&(this._playbackResource.loop=!1,this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1))},a._updateStartTime=function(){this._audioSpriteStopTime=.001*(this._startTime+this._duration),this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED,this._endedHandler,!1),this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE,this._audioSpriteEndHandler,!1))},a._updateDuration=function(){this._audioSpriteStopTime=.001*(this._startTime+this._duration),this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED,this._endedHandler,!1),this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE,this._audioSpriteEndHandler,!1))},a._setDurationFromSource=function(){this._duration=createjs.HTMLAudioTagPool.getDuration(this.src),this._playbackResource=null},createjs.HTMLAudioSoundInstance=createjs.promote(HTMLAudioSoundInstance,"AbstractSoundInstance")}(),this.createjs=this.createjs||{},function(){"use strict";function HTMLAudioPlugin(){this.AbstractPlugin_constructor(),this._capabilities=b._capabilities,this._loaderClass=createjs.SoundLoader,this._soundInstanceClass=createjs.HTMLAudioSoundInstance}var a=createjs.extend(HTMLAudioPlugin,createjs.AbstractPlugin),b=HTMLAudioPlugin;b.MAX_INSTANCES=30,b._AUDIO_READY="canplaythrough",b._AUDIO_ENDED="ended",b._AUDIO_SEEKED="seeked",b._AUDIO_STALLED="stalled",b._TIME_UPDATE="timeupdate",b._capabilities=null,b.isSupported=function(){return b._generateCapabilities(),null!=b._capabilities},b._generateCapabilities=function(){if(null==b._capabilities){var a=document.createElement("audio");if(null==a.canPlayType)return null;b._capabilities={panning:!1,volume:!0,tracks:-1};for(var c=createjs.Sound.SUPPORTED_EXTENSIONS,d=createjs.Sound.EXTENSION_MAP,e=0,f=c.length;f>e;e++){var g=c[e],h=d[g]||g;b._capabilities[g]="no"!=a.canPlayType("audio/"+g)&&""!=a.canPlayType("audio/"+g)||"no"!=a.canPlayType("audio/"+h)&&""!=a.canPlayType("audio/"+h)}}},a.register=function(a){var b=createjs.HTMLAudioTagPool.get(a.src),c=this.AbstractPlugin_register(a);return c.setTag(b),c},a.removeSound=function(a){this.AbstractPlugin_removeSound(a),createjs.HTMLAudioTagPool.remove(a)},a.create=function(a,b,c){var d=this.AbstractPlugin_create(a,b,c);return d.playbackResource=null,d},a.toString=function(){return"[HTMLAudioPlugin]"},a.setVolume=a.getVolume=a.setMute=null,createjs.HTMLAudioPlugin=createjs.promote(HTMLAudioPlugin,"AbstractPlugin")}(); \ No newline at end of file diff --git a/_assets/libs/tweenjs-NEXT.min.js b/_assets/libs/tweenjs-NEXT.min.js new file mode 100644 index 00000000..3fead898 --- /dev/null +++ b/_assets/libs/tweenjs-NEXT.min.js @@ -0,0 +1,12 @@ +/*! +* @license TweenJS +* Visit http://createjs.com/ for documentation, updates and examples. +* +* Copyright (c) 2011-2015 gskinner.com, inc. +* +* Distributed under the terms of the MIT license. +* http://www.opensource.org/licenses/mit-license.html +* +* This notice shall be included in all copies or substantial portions of the Software. +*/ +this.createjs=this.createjs||{},createjs.extend=function(a,b){"use strict";function c(){this.constructor=a}return c.prototype=b.prototype,a.prototype=new c},this.createjs=this.createjs||{},createjs.promote=function(a,b){"use strict";var c=a.prototype,d=Object.getPrototypeOf&&Object.getPrototypeOf(c)||c.__proto__;if(d){c[(b+="_")+"constructor"]=d.constructor;for(var e in d)c.hasOwnProperty(e)&&"function"==typeof d[e]&&(c[b+e]=d[e])}return a},this.createjs=this.createjs||{},createjs.deprecate=function(a,b){"use strict";return function(){var c="Deprecated property or method '"+b+"'. See docs for info.";return console&&(console.warn?console.warn(c):console.log(c)),a&&a.apply(this,arguments)}},this.createjs=this.createjs||{},function(){"use strict";function Event(a,b,c){this.type=a,this.target=null,this.currentTarget=null,this.eventPhase=0,this.bubbles=!!b,this.cancelable=!!c,this.timeStamp=(new Date).getTime(),this.defaultPrevented=!1,this.propagationStopped=!1,this.immediatePropagationStopped=!1,this.removed=!1}var a=Event.prototype;a.preventDefault=function(){this.defaultPrevented=this.cancelable&&!0},a.stopPropagation=function(){this.propagationStopped=!0},a.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},a.remove=function(){this.removed=!0},a.clone=function(){return new Event(this.type,this.bubbles,this.cancelable)},a.set=function(a){for(var b in a)this[b]=a[b];return this},a.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=Event}(),this.createjs=this.createjs||{},function(){"use strict";function EventDispatcher(){this._listeners=null,this._captureListeners=null}var a=EventDispatcher.prototype;EventDispatcher.initialize=function(b){b.addEventListener=a.addEventListener,b.on=a.on,b.removeEventListener=b.off=a.removeEventListener,b.removeAllEventListeners=a.removeAllEventListeners,b.hasEventListener=a.hasEventListener,b.dispatchEvent=a.dispatchEvent,b._dispatchEvent=a._dispatchEvent,b.willTrigger=a.willTrigger},a.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},a.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},a.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},a.off=a.removeEventListener,a.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},a.dispatchEvent=function(a,b,c){if("string"==typeof a){var d=this._listeners;if(!(b||d&&d[a]))return!0;a=new createjs.Event(a,b,c)}else a.target&&a.clone&&(a=a.clone());try{a.target=this}catch(e){}if(a.bubbles&&this.parent){for(var f=this,g=[f];f.parent;)g.push(f=f.parent);var h,i=g.length;for(h=i-1;h>=0&&!a.propagationStopped;h--)g[h]._dispatchEvent(a,1+(0==h));for(h=1;i>h&&!a.propagationStopped;h++)g[h]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return!a.defaultPrevented},a.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},a.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},a.toString=function(){return"[EventDispatcher]"},a._dispatchEvent=function(a,b){var c,d,e=2>=b?this._captureListeners:this._listeners;if(a&&e&&(d=e[a.type])&&(c=d.length)){try{a.currentTarget=this}catch(f){}try{a.eventPhase=0|b}catch(f){}a.removed=!1,d=d.slice();for(var g=0;c>g&&!a.immediatePropagationStopped;g++){var h=d[g];h.handleEvent?h.handleEvent(a):h(a),a.removed&&(this.off(a.type,h,1==b),a.removed=!1)}}2===b&&this._dispatchEvent(a,2.1)},createjs.EventDispatcher=EventDispatcher}(),this.createjs=this.createjs||{},function(){"use strict";function Ticker(){throw"Ticker cannot be instantiated."}Ticker.RAF_SYNCHED="synched",Ticker.RAF="raf",Ticker.TIMEOUT="timeout",Ticker.timingMode=null,Ticker.maxDelta=0,Ticker.paused=!1,Ticker.removeEventListener=null,Ticker.removeAllEventListeners=null,Ticker.dispatchEvent=null,Ticker.hasEventListener=null,Ticker._listeners=null,createjs.EventDispatcher.initialize(Ticker),Ticker._addEventListener=Ticker.addEventListener,Ticker.addEventListener=function(){return!Ticker._inited&&Ticker.init(),Ticker._addEventListener.apply(Ticker,arguments)},Ticker._inited=!1,Ticker._startTime=0,Ticker._pausedTime=0,Ticker._ticks=0,Ticker._pausedTicks=0,Ticker._interval=50,Ticker._lastTime=0,Ticker._times=null,Ticker._tickTimes=null,Ticker._timerId=null,Ticker._raf=!0,Ticker._setInterval=function(a){Ticker._interval=a,Ticker._inited&&Ticker._setupTick()},Ticker.setInterval=createjs.deprecate(Ticker._setInterval,"Ticker.setInterval"),Ticker._getInterval=function(){return Ticker._interval},Ticker.getInterval=createjs.deprecate(Ticker._getInterval,"Ticker.getInterval"),Ticker._setFPS=function(a){Ticker._setInterval(1e3/a)},Ticker.setFPS=createjs.deprecate(Ticker._setFPS,"Ticker.setFPS"),Ticker._getFPS=function(){return 1e3/Ticker._interval},Ticker.getFPS=createjs.deprecate(Ticker._getFPS,"Ticker.getFPS");try{Object.defineProperties(Ticker,{interval:{get:Ticker._getInterval,set:Ticker._setInterval},framerate:{get:Ticker._getFPS,set:Ticker._setFPS}})}catch(a){console.log(a)}Ticker.init=function(){Ticker._inited||(Ticker._inited=!0,Ticker._times=[],Ticker._tickTimes=[],Ticker._startTime=Ticker._getTime(),Ticker._times.push(Ticker._lastTime=0),Ticker.interval=Ticker._interval)},Ticker.reset=function(){if(Ticker._raf){var a=window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame;a&&a(Ticker._timerId)}else clearTimeout(Ticker._timerId);Ticker.removeAllEventListeners("tick"),Ticker._timerId=Ticker._times=Ticker._tickTimes=null,Ticker._startTime=Ticker._lastTime=Ticker._ticks=Ticker._pausedTime=0,Ticker._inited=!1},Ticker.getMeasuredTickTime=function(a){var b=0,c=Ticker._tickTimes;if(!c||c.length<1)return-1;a=Math.min(c.length,a||0|Ticker._getFPS());for(var d=0;a>d;d++)b+=c[d];return b/a},Ticker.getMeasuredFPS=function(a){var b=Ticker._times;return!b||b.length<2?-1:(a=Math.min(b.length-1,a||0|Ticker._getFPS()),1e3/((b[0]-b[a])/a))},Ticker.getTime=function(a){return Ticker._startTime?Ticker._getTime()-(a?Ticker._pausedTime:0):-1},Ticker.getEventTime=function(a){return Ticker._startTime?(Ticker._lastTime||Ticker._startTime)-(a?Ticker._pausedTime:0):-1},Ticker.getTicks=function(a){return Ticker._ticks-(a?Ticker._pausedTicks:0)},Ticker._handleSynch=function(){Ticker._timerId=null,Ticker._setupTick(),Ticker._getTime()-Ticker._lastTime>=.97*(Ticker._interval-1)&&Ticker._tick()},Ticker._handleRAF=function(){Ticker._timerId=null,Ticker._setupTick(),Ticker._tick()},Ticker._handleTimeout=function(){Ticker._timerId=null,Ticker._setupTick(),Ticker._tick()},Ticker._setupTick=function(){if(null==Ticker._timerId){var a=Ticker.timingMode;if(a==Ticker.RAF_SYNCHED||a==Ticker.RAF){var b=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame;if(b)return Ticker._timerId=b(a==Ticker.RAF?Ticker._handleRAF:Ticker._handleSynch),void(Ticker._raf=!0)}Ticker._raf=!1,Ticker._timerId=setTimeout(Ticker._handleTimeout,Ticker._interval)}},Ticker._tick=function(){var a=Ticker.paused,b=Ticker._getTime(),c=b-Ticker._lastTime;if(Ticker._lastTime=b,Ticker._ticks++,a&&(Ticker._pausedTicks++,Ticker._pausedTime+=c),Ticker.hasEventListener("tick")){var d=new createjs.Event("tick"),e=Ticker.maxDelta;d.delta=e&&c>e?e:c,d.paused=a,d.time=b,d.runTime=b-Ticker._pausedTime,Ticker.dispatchEvent(d)}for(Ticker._tickTimes.unshift(Ticker._getTime()-b);Ticker._tickTimes.length>100;)Ticker._tickTimes.pop();for(Ticker._times.unshift(b);Ticker._times.length>100;)Ticker._times.pop()};var b=window,c=b.performance.now||b.performance.mozNow||b.performance.msNow||b.performance.oNow||b.performance.webkitNow;Ticker._getTime=function(){return(c&&c.call(b.performance)||(new Date).getTime())-Ticker._startTime},createjs.Ticker=Ticker}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractTween(a){this.EventDispatcher_constructor(),this.ignoreGlobalPause=!1,this.loop=0,this.useTicks=!1,this.reversed=!1,this.bounce=!1,this.timeScale=1,this.duration=0,this.position=0,this.rawPosition=-1,this._paused=!0,this._next=null,this._prev=null,this._parent=null,this._labels=null,this._labelList=null,a&&(this.useTicks=!!a.useTicks,this.ignoreGlobalPause=!!a.ignoreGlobalPause,this.loop=a.loop===!0?-1:a.loop||0,this.reversed=!!a.reversed,this.bounce=!!a.bounce,this.timeScale=a.timeScale||1,a.onChange&&this.addEventListener("change",a.onChange),a.onComplete&&this.addEventListener("complete",a.onComplete))}var a=createjs.extend(AbstractTween,createjs.EventDispatcher);a._setPaused=function(a){return createjs.Tween._register(this,a),this},a.setPaused=createjs.deprecate(a._setPaused,"AbstractTween.setPaused"),a._getPaused=function(){return this._paused},a.getPaused=createjs.deprecate(a._getPaused,"AbstactTween.getPaused"),a._getCurrentLabel=function(a){var b=this.getLabels();null==a&&(a=this.position);for(var c=0,d=b.length;d>c&&!(aa&&(a=0),0===e){if(j=!0,-1!==g)return j}else{if(h=a/e|0,i=a-h*e,j=-1!==f&&a>=f*e+e,j&&(a=(i=e)*(h=f)+e),a===g)return j;var k=!this.reversed!=!(this.bounce&&h%2);k&&(i=e-i)}this.position=i,this.rawPosition=a,this._updatePosition(c,j),j&&(this.paused=!0),d&&d(this),b||this._runActions(g,a,c,!c&&-1===g),this.dispatchEvent("change"),j&&this.dispatchEvent("complete")},a.calculatePosition=function(a){var b=this.duration,c=this.loop,d=0,e=0;if(0===b)return 0;-1!==c&&a>=c*b+b?(e=b,d=c):0>a?e=0:(d=a/b|0,e=a-d*b);var f=!this.reversed!=!(this.bounce&&d%2);return f?b-e:e},a.getLabels=function(){var a=this._labelList;if(!a){a=this._labelList=[];var b=this._labels;for(var c in b)a.push({label:c,position:b[c]});a.sort(function(a,b){return a.position-b.position})}return a},a.setLabels=function(a){this._labels=a,this._labelList=null},a.addLabel=function(a,b){this._labels||(this._labels={}),this._labels[a]=b;var c=this._labelList;if(c){for(var d=0,e=c.length;e>d&&!(bl&&(h=i,f=l),e>l&&(g=i,e=l)),c)return this._runActionsRange(h,h,c,d);if(e!==f||g!==h||c||d){-1===e&&(e=g=0);var m=b>=a,n=e;do{var o=!j!=!(k&&n%2),p=n===e?g:m?0:i,q=n===f?h:m?i:0;if(o&&(p=i-p,q=i-q),k&&n!==e&&p===q);else if(this._runActionsRange(p,q,c,d||n!==e&&!k))return!0;d=!1}while(m&&++n<=f||!m&&--n>=f)}}},a._runActionsRange=function(){},createjs.AbstractTween=createjs.promote(AbstractTween,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function Tween(b,c){this.AbstractTween_constructor(c),this.pluginData=null,this.target=b,this.passive=!1,this._stepHead=new a(null,0,0,{},null,!0),this._stepTail=this._stepHead,this._stepPosition=0,this._actionHead=null,this._actionTail=null,this._plugins=null,this._pluginIds=null,this._injected=null,c&&(this.pluginData=c.pluginData,c.override&&Tween.removeTweens(b)),this.pluginData||(this.pluginData={}),this._init(c)}function a(a,b,c,d,e,f){this.next=null,this.prev=a,this.t=b,this.d=c,this.props=d,this.ease=e,this.passive=f,this.index=a?a.index+1:0}function b(a,b,c,d,e){this.next=null,this.prev=a,this.t=b,this.d=0,this.scope=c,this.funct=d,this.params=e}var c=createjs.extend(Tween,createjs.AbstractTween);Tween.IGNORE={},Tween._tweens=[],Tween._plugins=null,Tween._tweenHead=null,Tween._tweenTail=null,Tween.get=function(a,b){return new Tween(a,b)},Tween.tick=function(a,b){for(var c=Tween._tweenHead;c;){var d=c._next;b&&!c.ignoreGlobalPause||c._paused||c.advance(c.useTicks?1:a),c=d}},Tween.handleEvent=function(a){"tick"===a.type&&this.tick(a.delta,a.paused)},Tween.removeTweens=function(a){if(a.tweenjs_count){for(var b=Tween._tweenHead;b;){var c=b._next;b.target===a&&Tween._register(b,!0),b=c}a.tweenjs_count=0}},Tween.removeAllTweens=function(){for(var a=Tween._tweenHead;a;){var b=a._next;a._paused=!0,a.target&&(a.target.tweenjs_count=0),a._next=a._prev=null,a=b}Tween._tweenHead=Tween._tweenTail=null},Tween.hasActiveTweens=function(a){return a?!!a.tweenjs_count:!!Tween._tweenHead},Tween._installPlugin=function(a){for(var b=a.priority=a.priority||0,c=Tween._plugins=Tween._plugins||[],d=0,e=c.length;e>d&&!(b0&&this._addStep(+a,this._stepTail.props,null,b),this},c.to=function(a,b,c){(null==b||0>b)&&(b=0);var d=this._addStep(+b,null,c);return this._appendProps(a,d),this},c.label=function(a){return this.addLabel(a,this.duration),this},c.call=function(a,b,c){return this._addAction(c||this.target,a,b||[this])},c.set=function(a,b){return this._addAction(b||this.target,this._set,[a])},c.play=function(a){return this._addAction(a||this,this._set,[{paused:!1}])},c.pause=function(a){return this._addAction(a||this,this._set,[{paused:!0}])},c.w=c.wait,c.t=c.to,c.c=c.call,c.s=c.set,c.toString=function(){return"[Tween]"},c.clone=function(){throw"Tween can not be cloned."},c._addPlugin=function(a){var b=this._pluginIds||(this._pluginIds={}),c=a.ID;if(c&&!b[c]){b[c]=!0;for(var d=this._plugins||(this._plugins=[]),e=a.priority||0,f=0,g=d.length;g>f;f++)if(e=1?f:e,j)for(var l=0,m=j.length;m>l;l++){var n=j[l].change(this,a,k,d,b,c);if(n===Tween.IGNORE)continue a;void 0!==n&&(d=n)}this.target[k]=d}}},c._runActionsRange=function(a,b,c,d){var e=a>b,f=e?this._actionTail:this._actionHead,g=b,h=a;e&&(g=a,h=b);for(var i=this.position;f;){var j=f.t;if((j===b||j>h&&g>j||d&&j===a)&&(f.funct.apply(f.scope,f.params),i!==this.position))return!0;f=e?f.prev:f.next}},c._appendProps=function(a,b,c){var d,e,f,g,h,i=this._stepHead.props,j=this.target,k=Tween._plugins,l=b.prev,m=l.props,n=b.props||(b.props=this._cloneProps(m)),o={};for(d in a)if(a.hasOwnProperty(d)&&(o[d]=n[d]=a[d],void 0===i[d])){if(g=void 0,k)for(e=k.length-1;e>=0;e--)if(f=k[e].init(this,d,g),void 0!==f&&(g=f),g===Tween.IGNORE){delete n[d],delete o[d];break}g!==Tween.IGNORE&&(void 0===g&&(g=j[d]),m[d]=void 0===g?null:g)}for(d in o){f=a[d];for(var p,q=l;(p=q)&&(q=p.prev);)if(q.props!==p.props){if(void 0!==q.props[d])break;q.props[d]=m[d]}}if(c!==!1&&(k=this._plugins))for(e=k.length-1;e>=0;e--)k[e].step(this,b,o);(h=this._injected)&&(this._injected=null,this._appendProps(h,b,!1))},c._injectProp=function(a,b){var c=this._injected||(this._injected={});c[a]=b},c._addStep=function(b,c,d,e){var f=new a(this._stepTail,this.duration,b,c,d,e||!1);return this.duration+=b,this._stepTail=this._stepTail.next=f},c._addAction=function(a,c,d){var e=new b(this._actionTail,this.duration,a,c,d);return this._actionTail?this._actionTail.next=e:this._actionHead=e,this._actionTail=e,this},c._set=function(a){for(var b in a)this[b]=a[b]},c._cloneProps=function(a){var b={};for(var c in a)b[c]=a[c];return b},createjs.Tween=createjs.promote(Tween,"AbstractTween")}(),this.createjs=this.createjs||{},function(){"use strict";function Timeline(a){var b,c;a instanceof Array||null==a&&arguments.length>1?(b=a,c=arguments[1],a=arguments[2]):a&&(b=a.tweens,c=a.labels),this.AbstractTween_constructor(a),this.tweens=[],b&&this.addTween.apply(this,b),this.setLabels(c),this._init(a)}var a=createjs.extend(Timeline,createjs.AbstractTween);a.addTween=function(a){a._parent&&a._parent.removeTween(a);var b=arguments.length;if(b>1){for(var c=0;b>c;c++)this.addTween(arguments[c]);return arguments[b-1]}if(0===b)return null;this.tweens.push(a),a._parent=this,a.paused=!0;var d=a.duration;return a.loop>0&&(d*=a.loop+1),d>this.duration&&(this.duration=d),this.rawPosition>=0&&a.setPosition(this.rawPosition),a},a.removeTween=function(a){var b=arguments.length;if(b>1){for(var c=!0,d=0;b>d;d++)c=c&&this.removeTween(arguments[d]);return c}if(0===b)return!0;for(var e=this.tweens,d=e.length;d--;)if(e[d]===a)return e.splice(d,1),a._parent=null,a.duration>=this.duration&&this.updateDuration(),!0;return!1},a.updateDuration=function(){this.duration=0;for(var a=0,b=this.tweens.length;b>a;a++){var c=this.tweens[a],d=c.duration;c.loop>0&&(d*=c.loop+1),d>this.duration&&(this.duration=d)}},a.toString=function(){return"[Timeline]"},a.clone=function(){throw"Timeline can not be cloned."},a._updatePosition=function(a){for(var b=this.position,c=0,d=this.tweens.length;d>c;c++)this.tweens[c].setPosition(b,!0,a)},a._runActionsRange=function(a,b,c,d){for(var e=this.position,f=0,g=this.tweens.length;g>f;f++)if(this.tweens[f]._runActions(a,b,c,d),e!==this.position)return!0},createjs.Timeline=createjs.promote(Timeline,"AbstractTween")}(),this.createjs=this.createjs||{},function(){"use strict";function Ease(){throw"Ease cannot be instantiated."}Ease.linear=function(a){return a},Ease.none=Ease.linear,Ease.get=function(a){return-1>a?a=-1:a>1&&(a=1),function(b){return 0==a?b:0>a?b*(b*-a+1+a):b*((2-b)*a+(1-a))}},Ease.getPowIn=function(a){return function(b){return Math.pow(b,a)}},Ease.getPowOut=function(a){return function(b){return 1-Math.pow(1-b,a)}},Ease.getPowInOut=function(a){return function(b){return(b*=2)<1?.5*Math.pow(b,a):1-.5*Math.abs(Math.pow(2-b,a))}},Ease.quadIn=Ease.getPowIn(2),Ease.quadOut=Ease.getPowOut(2),Ease.quadInOut=Ease.getPowInOut(2),Ease.cubicIn=Ease.getPowIn(3),Ease.cubicOut=Ease.getPowOut(3),Ease.cubicInOut=Ease.getPowInOut(3),Ease.quartIn=Ease.getPowIn(4),Ease.quartOut=Ease.getPowOut(4),Ease.quartInOut=Ease.getPowInOut(4),Ease.quintIn=Ease.getPowIn(5),Ease.quintOut=Ease.getPowOut(5),Ease.quintInOut=Ease.getPowInOut(5),Ease.sineIn=function(a){return 1-Math.cos(a*Math.PI/2)},Ease.sineOut=function(a){return Math.sin(a*Math.PI/2)},Ease.sineInOut=function(a){return-.5*(Math.cos(Math.PI*a)-1)},Ease.getBackIn=function(a){return function(b){return b*b*((a+1)*b-a)}},Ease.backIn=Ease.getBackIn(1.7),Ease.getBackOut=function(a){return function(b){return--b*b*((a+1)*b+a)+1}},Ease.backOut=Ease.getBackOut(1.7),Ease.getBackInOut=function(a){return a*=1.525,function(b){return(b*=2)<1?.5*b*b*((a+1)*b-a):.5*((b-=2)*b*((a+1)*b+a)+2)}},Ease.backInOut=Ease.getBackInOut(1.7),Ease.circIn=function(a){return-(Math.sqrt(1-a*a)-1)},Ease.circOut=function(a){return Math.sqrt(1- --a*a)},Ease.circInOut=function(a){return(a*=2)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},Ease.bounceIn=function(a){return 1-Ease.bounceOut(1-a)},Ease.bounceOut=function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},Ease.bounceInOut=function(a){return.5>a?.5*Ease.bounceIn(2*a):.5*Ease.bounceOut(2*a-1)+.5},Ease.getElasticIn=function(a,b){var c=2*Math.PI;return function(d){if(0==d||1==d)return d;var e=b/c*Math.asin(1/a);return-(a*Math.pow(2,10*(d-=1))*Math.sin((d-e)*c/b))}},Ease.elasticIn=Ease.getElasticIn(1,.3),Ease.getElasticOut=function(a,b){var c=2*Math.PI;return function(d){if(0==d||1==d)return d;var e=b/c*Math.asin(1/a);return a*Math.pow(2,-10*d)*Math.sin((d-e)*c/b)+1}},Ease.elasticOut=Ease.getElasticOut(1,.3),Ease.getElasticInOut=function(a,b){var c=2*Math.PI;return function(d){var e=b/c*Math.asin(1/a);return(d*=2)<1?-.5*a*Math.pow(2,10*(d-=1))*Math.sin((d-e)*c/b):a*Math.pow(2,-10*(d-=1))*Math.sin((d-e)*c/b)*.5+1}},Ease.elasticInOut=Ease.getElasticInOut(1,.3*1.5),createjs.Ease=Ease}(),this.createjs=this.createjs||{},function(){"use strict";function MotionGuidePlugin(){throw"MotionGuidePlugin cannot be instantiated."}var a=MotionGuidePlugin;a.priority=0,a.ID="MotionGuide",a.install=function(){return createjs.Tween._installPlugin(MotionGuidePlugin),createjs.Tween.IGNORE},a.init=function(b,c){"guide"==c&&b._addPlugin(a)},a.step=function(b,c,d){for(var e in d)if("guide"===e){var f=c.props.guide,g=a._solveGuideData(d.guide,f);f.valid=!g;var h=f.endData;if(b._injectProp("x",h.x),b._injectProp("y",h.y),g||!f.orient)break;var i=void 0===c.prev.props.rotation?b.target.rotation||0:c.prev.props.rotation;if(f.startOffsetRot=i-f.startData.rotation,"fixed"==f.orient)f.endAbsRot=h.rotation+f.startOffsetRot,f.deltaRotation=0;else{var j=void 0===d.rotation?b.target.rotation||0:d.rotation,k=j-f.endData.rotation-f.startOffsetRot,l=k%360;switch(f.endAbsRot=j,f.orient){case"auto":f.deltaRotation=k;break;case"cw":f.deltaRotation=(l+360)%360+360*Math.abs(k/360|0);break;case"ccw":f.deltaRotation=(l-360)%360+-360*Math.abs(k/360|0)}}b._injectProp("rotation",f.endAbsRot)}},a.change=function(b,c,d,e,f){var g=c.props.guide;if(g&&c.props!==c.prev.props&&g!==c.prev.props.guide)return"guide"===d&&!g.valid||"x"==d||"y"==d||"rotation"===d&&g.orient?createjs.Tween.IGNORE:void a._ratioToPositionData(f,g,b.target)},a.debug=function(b,c,d){b=b.guide||b;var e=a._findPathProblems(b);if(e&&console.error("MotionGuidePlugin Error found: \n"+e),!c)return e;var f,g=b.path,h=g.length,i=3,j=9;for(c.save(),c.lineCap="round",c.lineJoin="miter",c.beginPath(),c.moveTo(g[0],g[1]),f=2;h>f;f+=4)c.quadraticCurveTo(g[f],g[f+1],g[f+2],g[f+3]);c.strokeStyle="black",c.lineWidth=1.5*i,c.stroke(),c.strokeStyle="white",c.lineWidth=i,c.stroke(),c.closePath();var k=d.length;if(d&&k){var l={},m={};a._solveGuideData(b,l);for(var f=0;k>f;f++)l.orient="fixed",a._ratioToPositionData(d[f],l,m),c.beginPath(),c.moveTo(m.x,m.y),c.lineTo(m.x+Math.cos(.0174533*m.rotation)*j,m.y+Math.sin(.0174533*m.rotation)*j),c.strokeStyle="black",c.lineWidth=1.5*i,c.stroke(),c.strokeStyle="red",c.lineWidth=i,c.stroke(),c.closePath()}return c.restore(),e},a._solveGuideData=function(b,c){var d=void 0;if(d=a.debug(b))return d;{var e=c.path=b.path;c.orient=b.orient}c.subLines=[],c.totalLength=0,c.startOffsetRot=0,c.deltaRotation=0,c.startData={ratio:0},c.endData={ratio:1},c.animSpan=1;var f,g,h,i,j,k,l,m,n,o=e.length,p=10,q={};for(f=e[0],g=e[1],l=2;o>l;l+=4){h=e[l],i=e[l+1],j=e[l+2],k=e[l+3];var r={weightings:[],estLength:0,portion:0},s=f,t=g;for(m=1;p>=m;m++){a._getParamsForCurve(f,g,h,i,j,k,m/p,!1,q);var u=q.x-s,v=q.y-t;n=Math.sqrt(u*u+v*v),r.weightings.push(n),r.estLength+=n,s=q.x,t=q.y}for(c.totalLength+=r.estLength,m=0;p>m;m++)n=r.estLength,r.weightings[m]=r.weightings[m]/n;c.subLines.push(r),f=j,g=k}n=c.totalLength;var w=c.subLines.length;for(l=0;w>l;l++)c.subLines[l].portion=c.subLines[l].estLength/n;var x=isNaN(b.start)?0:b.start,y=isNaN(b.end)?1:b.end;a._ratioToPositionData(x,c,c.startData),a._ratioToPositionData(y,c,c.endData),c.startData.ratio=x,c.endData.ratio=y,c.animSpan=c.endData.ratio-c.startData.ratio},a._ratioToPositionData=function(b,c,d){var e,f,g,h,i,j=c.subLines,k=0,l=10,m=b*c.animSpan+c.startData.ratio;for(f=j.length,e=0;f>e;e++){if(h=j[e].portion,k+h>=m){i=e;break}k+=h}void 0===i&&(i=f-1,k-=h);var n=j[i].weightings,o=h;for(f=n.length,e=0;f>e&&(h=n[e]*o,!(k+h>=m));e++)k+=h;i=4*i+2,g=e/l+(m-k)/h*(1/l);var p=c.path;return a._getParamsForCurve(p[i-2],p[i-1],p[i],p[i+1],p[i+2],p[i+3],g,c.orient,d),c.orient&&(b>=.99999&&1.00001>=b&&void 0!==c.endAbsRot?d.rotation=c.endAbsRot:d.rotation+=c.startOffsetRot+b*c.deltaRotation),d},a._getParamsForCurve=function(a,b,c,d,e,f,g,h,i){var j=1-g;i.x=j*j*a+2*j*g*c+g*g*e,i.y=j*j*b+2*j*g*d+g*g*f,h&&(i.rotation=57.2957795*Math.atan2((d-b)*j+(f-d)*g,(c-a)*j+(e-c)*g))},a._findPathProblems=function(a){var b=a.path,c=b&&b.length||0;if(6>c||(c-2)%4){var d=" Cannot parse 'path' array due to invalid number of entries in path. ";return d+="There should be an odd number of points, at least 3 points, and 2 entries per point (x & y). ",d+="See 'CanvasRenderingContext2D.quadraticCurveTo' for details as 'path' models a quadratic bezier.\n\n",d+="Only [ "+c+" ] values found. Expected: "+Math.max(4*Math.ceil((c-2)/4)+2,6)}for(var e=0;c>e;e++)if(isNaN(b[e]))return"All data in path array must be numeric";var f=a.start;if(isNaN(f)&&void 0!==f)return"'start' out of bounds. Expected 0 to 1, got: "+f;var g=a.end;if(isNaN(g)&&void 0!==g)return"'end' out of bounds. Expected 0 to 1, got: "+g;var h=a.orient;return h&&"fixed"!=h&&"auto"!=h&&"cw"!=h&&"ccw"!=h?'Invalid orientation value. Expected ["fixed", "auto", "cw", "ccw", undefined], got: '+h:void 0},createjs.MotionGuidePlugin=MotionGuidePlugin}(),this.createjs=this.createjs||{},function(){"use strict";var a=createjs.TweenJS=createjs.TweenJS||{};a.version="NEXT",a.buildDate="Thu, 14 Sep 2017 22:19:45 GMT"}(); \ No newline at end of file diff --git a/examples/assets/CabinBoy.mp3 b/_assets/static/CabinBoy.mp3 similarity index 100% rename from examples/assets/CabinBoy.mp3 rename to _assets/static/CabinBoy.mp3 diff --git a/_assets/static/ManifestTest.json b/_assets/static/ManifestTest.json new file mode 100644 index 00000000..9a6208ab --- /dev/null +++ b/_assets/static/ManifestTest.json @@ -0,0 +1,14 @@ +maps({ + "path": "examples/assets/", + "manifest": [ + {"id":"Texas.jpg", "src":"Texas.jpg"}, + {"id":"scriptExample", "src":"scriptExample.js"}, + {"id":"grant.xml", "src":"grant.xml"}, + {"id":"gbot.svg", "src":"gbot.svg"}, + {"id":"grant.json", "src":"grant.json"}, + {"id":"font.css", "src":"font.css"}, + {"id":"Thunder.mp3", "src":"Thunder.mp3"}, + {"id":"jsonpSample.json", "callback":"x", "type":"jsonp", "src":"jsonpSample.json"}, + {"id":"Autumn.png", "src":"Autumn.png"}, + ] +}); diff --git a/_assets/static/MediaGridManifest.json b/_assets/static/MediaGridManifest.json new file mode 100644 index 00000000..98469013 --- /dev/null +++ b/_assets/static/MediaGridManifest.json @@ -0,0 +1,16 @@ +loadMediaGrid({ + "path": "../_assets/", + "manifest": [ + {"id":"art/Texas.jpg", "src":"art/Texas.jpg"}, + {"id":"NoFileHere.png", "src":"NoFileHere.png"}, + {"id":"static/bg.css", "src":"static/bg.css"}, + {"id":"static/alert1.js", "src":"static/alert1.js"}, + {"id":"static/grant.xml", "src":"static/grant.xml"}, + {"id":"art/gbot.svg", "src":"art/gbot.svg"}, + {"id":"static/grant.json", "src":"static/grant.json"}, + {"id":"static/font.css", "src":"static/font.css"}, + {"id":"audio/Thunder.mp3", "src":"audio/Thunder.mp3"}, + {"id":"//gskinner.com/assets/createjs/mapsJSONP.json", "callback":"maps", "type":"jsonp", "src":"//gskinner.com/assets/createjs/mapsJSONP.json"}, + {"id":"art/Autumn.png", "src":"art/Autumn.png"} + ] +}); diff --git a/examples/assets/alert1.js b/_assets/static/alert1.js similarity index 100% rename from examples/assets/alert1.js rename to _assets/static/alert1.js diff --git a/examples/assets/bg.css b/_assets/static/bg.css similarity index 100% rename from examples/assets/bg.css rename to _assets/static/bg.css diff --git a/examples/assets/demoStyles.css b/_assets/static/demoStyles.css similarity index 100% rename from examples/assets/demoStyles.css rename to _assets/static/demoStyles.css diff --git a/examples/assets/font.css b/_assets/static/font.css similarity index 100% rename from examples/assets/font.css rename to _assets/static/font.css diff --git a/examples/assets/grant.json b/_assets/static/grant.json similarity index 78% rename from examples/assets/grant.json rename to _assets/static/grant.json index 7100d008..92f7f61b 100644 --- a/examples/assets/grant.json +++ b/_assets/static/grant.json @@ -7,5 +7,5 @@ "height": 361 }, "animations": {"jump": [26, 63], "run": [0, 25]}, - "images": ["assets/runningGrant.png"] + "images": ["../_assets/art/runningGrant.png"] } \ No newline at end of file diff --git a/examples/assets/grant.xml b/_assets/static/grant.xml similarity index 100% rename from examples/assets/grant.xml rename to _assets/static/grant.xml diff --git a/_assets/static/grantp.json b/_assets/static/grantp.json new file mode 100644 index 00000000..7f06aebc --- /dev/null +++ b/_assets/static/grantp.json @@ -0,0 +1,13 @@ +grantp( + { + "frames": { + "width": 200, + "numFrames": 64, + "regX": 2, + "regY": 2, + "height": 361 + }, + "animations": {"jump": [26, 63], "run": [0, 25]}, + "images": ["../_assets/art/runningGrant.png"] + } +) \ No newline at end of file diff --git a/_assets/static/jsonpSample.json b/_assets/static/jsonpSample.json new file mode 100644 index 00000000..52de3e54 --- /dev/null +++ b/_assets/static/jsonpSample.json @@ -0,0 +1,4 @@ +x({ + "test":"foo", + "bar":[] +}) diff --git a/_assets/static/manifest.json b/_assets/static/manifest.json new file mode 100644 index 00000000..06a904c4 --- /dev/null +++ b/_assets/static/manifest.json @@ -0,0 +1,9 @@ +{ + "path": "../_assets/art/", + "manifest": [ + "image0.jpg", + "image1.jpg", + "image2.jpg", + {"id":"image3", "src":"image3.jpg"} + ] +} \ No newline at end of file diff --git a/_assets/static/manifestp.json b/_assets/static/manifestp.json new file mode 100644 index 00000000..e2952b8c --- /dev/null +++ b/_assets/static/manifestp.json @@ -0,0 +1,9 @@ +loadManifest({ + "path": "../_assets/art/", + "manifest": [ + "image0.jpg", + "image1.jpg", + "image2.jpg", + {"id":"image3", "src":"image3.jpg"} + ] +}) \ No newline at end of file diff --git a/_assets/static/scriptExample.js b/_assets/static/scriptExample.js new file mode 100644 index 00000000..33b57452 --- /dev/null +++ b/_assets/static/scriptExample.js @@ -0,0 +1,3 @@ +(function(){ + window.foo = true; +}()) diff --git a/_assets/static/video.mp4 b/_assets/static/video.mp4 new file mode 100644 index 00000000..0a06f863 Binary files /dev/null and b/_assets/static/video.mp4 differ diff --git a/bower.json b/bower.json index 3892ef23..e2ea30e4 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "PreloadJS", - "version": "0.4.1", + "version": "1.0.0", "homepage": "https://github.com/CreateJS/PreloadJS", "authors": [ "gskinner", @@ -8,19 +8,28 @@ "wdamien" ], "description": "PreloadJS makes preloading assets & getting aggregate progress events easier in JavaScript. It uses XHR2 when available, and falls back to tag-based loading when not. Part of the CreateJS suite of libraries.", - "main": "lib/preloadjs-0.4.1.combined.js", + "main": "lib/preloadjs.js", "keywords": [ - "preload", "xhr", "createjs" + "preload", + "xhr", + "createjs" ], "license": "MIT", "ignore": [ "**/.*", + "_assets", "node_modules", "bower_components", + ".bower.json", "build", "docs", "examples", "extras", - "src" + "icon.png", + "LICENSE.txt", + "README.md", + "src", + "tests", + "VERSIONS.txt" ] } diff --git a/build/BANNER b/build/BANNER new file mode 100644 index 00000000..b2fdd050 --- /dev/null +++ b/build/BANNER @@ -0,0 +1,27 @@ +/*! +* <%= pkg.name %> +* 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. +*/ diff --git a/build/Gruntfile.js b/build/Gruntfile.js index 0369eae1..dd7a6247 100644 --- a/build/Gruntfile.js +++ b/build/Gruntfile.js @@ -8,10 +8,11 @@ module.exports = function (grunt) { // Default values version: 'NEXT', + fileVersion: '-<%= version %>', name: 'preloadjs', // Setup doc names / paths. - docsName: '<%= pkg.name %>_docs-<%= version %>', + docsName: '<%= pkg.name %>_docs<%= fileVersion %>', docsZip: "<%= docsName %>.zip", // Setup Uglify for JS minification. @@ -24,21 +25,52 @@ module.exports = function (grunt) { "DEBUG": false } }, + mangle: { + except: getExclusions() + } }, build: { files: { - 'output/<%= pkg.name.toLowerCase() %>-<%= version %>.min.js': getConfigValue('source'), + 'output/<%= pkg.name.toLowerCase() %><%= fileVersion %>.min.js': getConfigValue('source'), } } }, concat: { options: { - separator: '' + separator: '', + process: function(src, filepath) { + // Remove a few things from each file, they will be added back at the end. + + // Strip the license header. + var file = src.replace(/^(\/\*\s)[\s\S]+?\*\//, ""); + + // Strip namespace (Breaks Preload, and maybe other libs, leaving out for now) + // file = file.replace(/(this.createjs)\s*=\s*\1.*?(});?/, ""); + + // Strip namespace label + file = file.replace(/\/\/\s*namespace:/, ""); + + // Strip @module + file = file.replace(/\/\*\*[\s\S]+?@module[\s\S]+?\*\//, ""); + + // Clean up white space + file = file.replace(/^\s*/, ""); + file = file.replace(/\s*$/, ""); + + // Append on the class name + file = + "\n\n//##############################################################################\n"+ + "// " + path.basename(filepath) + "\n" + + "//##############################################################################\n\n"+ + file; + + return file; + } }, build: { files: { - 'output/<%= pkg.name.toLowerCase() %>-<%= version %>.combined.js': getCombinedSource() + 'output/<%= pkg.name.toLowerCase() %><%= fileVersion %>.js': getCombinedSource() } } }, @@ -75,6 +107,12 @@ module.exports = function (grunt) { } }, + clean: { + docs: { + src: ["<%= docsFolder %>/assets/scss"] + } + }, + copy: { docsZip: { files: [ @@ -88,7 +126,7 @@ module.exports = function (grunt) { }, src: { files: [ - {expand: true, cwd:'./output/', src: '*<%=version %>*.js', dest: '../lib/'} + {expand: true, cwd:'./output/', src: '*<%=fileVersion %>*.js', dest: '../lib/'} ] } }, @@ -98,6 +136,24 @@ module.exports = function (grunt) { file: '../src/preloadjs/version.js', version: '<%= version %>' } + }, + + clearversion: { + preload: { + file: '../src/preloadjs/version.js' + } + }, + + sass: { + docs: { + options: { + style: 'compressed', + sourcemap:"none" + }, + files: { + 'createjsTheme/assets/css/main.css': 'createjsTheme/assets/scss/main.scss' + } + } } } ); @@ -162,14 +218,46 @@ module.exports = function (grunt) { return clean; } + function getExclusions() { + var list = getConfigValue("source"); + var files = []; + for (var i= 0, l=list.length; i/"); @@ -184,7 +272,7 @@ module.exports = function (grunt) { * Build the docs using YUIdocs. */ grunt.registerTask('docs', [ - "setDocsBase", "yuidoc", "resetBase", "compress", "copy:docsZip" + "sass", "setDocsBase", "yuidoc", "resetBase", "clean:docs", "compress", "copy:docsZip" ]); /** @@ -192,30 +280,50 @@ module.exports = function (grunt) { */ grunt.registerTask('setVersion', function () { grunt.config.set('version', grunt.config.get('pkg').version); + grunt.config.set('fileVersion', ''); }); /** * Task for exporting a next build. * */ - grunt.registerTask('next', [ - "coreBuild" + grunt.registerTask('next', function() { + grunt.config("buildArgs", this.args || []); + getBuildArgs(); + grunt.task.run(["coreBuild", "clearBuildArgs"]); + }); + + /** + * Task for exporting only the next lib. + * + */ + grunt.registerTask('nextlib', [ + "updateversion", "combine", "uglify", "clearversion", "copy:src" ]); + /** Aliased task for WebStorm quick-run */ + grunt.registerTask('_next_preload', ["next"]); + /** * Task for exporting a release build (version based on package.json) * */ - grunt.registerTask('build', [ - "setVersion", "coreBuild", "updatebower", "copy:docsSite" - ]); + grunt.registerTask('build', function() { + grunt.config("buildArgs", this.args || []); + getBuildArgs(); + grunt.task.run(["setVersion", "coreBuild", "updatebower", "copy:docsSite", "clearBuildArgs"]); + }); + + grunt.registerTask('clearBuildArgs', function() { + grunt.config("buildArgs", []); + }); /** * Main build task, always runs after next or build. * */ grunt.registerTask('coreBuild', [ - "updateversion", "combine", "uglify", "docs", "copy:src" + "updateversion", "combine", "uglify", "clearversion", "docs", "copy:src" ]); /** @@ -225,4 +333,5 @@ module.exports = function (grunt) { grunt.registerTask('combine', 'Combine all source into a single, un-minified file.', [ "concat" ]); + }; diff --git a/build/LICENSE b/build/LICENSE index 09fe251b..3e32a9c4 100644 --- a/build/LICENSE +++ b/build/LICENSE @@ -2,7 +2,7 @@ * @license <%= pkg.name %> * Visit http://createjs.com/ for documentation, updates and examples. * -* Copyright (c) 2011-2013 gskinner.com, inc. +* Copyright (c) 2011-2015 gskinner.com, inc. * * Distributed under the terms of the MIT license. * http://www.opensource.org/licenses/mit-license.html diff --git a/build/README.md b/build/README.md index 0d2b16b7..a17b3d33 100644 --- a/build/README.md +++ b/build/README.md @@ -6,7 +6,13 @@ Note that this requires a familiarity with using the command line. The example c ### Install dependencies -Node (0.10.2 or greater is required): +sass (3.3 or greater is required): + + # ruby is required for sass. Check http://sass-lang.com/install for dependencies. + # Install (or update) sass + gem install sass; + +Node (0.10.x or greater is required): # check the version via the command line node -v @@ -61,4 +67,5 @@ The same as the NEXT process, but will not minify the source code. All code form * grunt next - Build everything using the NEXT version. * grunt combine - Build a NEXT version, but leave comments and formatting intact. * grunt docs - Build only the docs -* grunt uglify - Create the PreloadJS min file. (Will use NEXT as the version) +* grunt exportScriptTags - Export valid + +*/ + +// Default Font +$fontFamily-default: 'effra', sans-serif; +// Weights: 400, 400 italic, 700 + + +// Secondary Font +$fontFamily-secondary: 'Proxima Nova', sans-serif; +// Weights: 400, 500 + +// Monospace Font +@import url("https://fonts.googleapis.com/css?family=Source+Code+Pro&subset=latin,latin-ext"); +$fontFamily-monospace: 'Source Code Pro', monospace; +// Weights: 400 + + + +//******************************************* +// +// SIZE RAMP +// Define your font sizes below +// +//******************************************* +$fontSize-smallest: 1.5rem; +$fontSize-smaller: 1.6rem; +$fontSize-small: 2.2rem; +$fontSize-default: 2.8rem; +$fontSize-large: 3.8rem; +$fontSize-larger: 5rem; +$fontSize-largest: 9rem; +$fontSize-display: 12rem; + + + +//******************************************* +// +// MODULAR SCALE +// +// 16px @ 1:1.333 +// +// Pixels Ems +// 1,192.803 74.55 +// 894.826 55.927 +// 671.287 41.955 +// 503.591 31.474 +// 377.788 23.612 +// 283.412 17.713 +// 212.612 13.288 +// 159.499 9.969 +// 119.654 7.478 +// 89.763 5.61 +// 67.339 4.209 +// 50.517 3.157 +// 37.897 2.369 +// 28.430 1.777 +// 21.328 1.333 +// 16.000 1 +// 12.003 0.75 +// 9.005 0.563 +// 6.755 0.422 +// 5.068 0.317 +// 3.802 0.238 +// 2.852 0.178 +// 2.140 0.134 +// 1.605 0.1 +// 1.204 0.075 +// +// (source: http://modularscale.com/) +// +//******************************************* diff --git a/build/createjsTheme/assets/scss/settings/layout.scss b/build/createjsTheme/assets/scss/settings/layout.scss new file mode 100644 index 00000000..8284e2a1 --- /dev/null +++ b/build/createjsTheme/assets/scss/settings/layout.scss @@ -0,0 +1,24 @@ +//******************************************* +// +// LAYOUT SETTINGS +// Default grid units settings used for layout by gBootstrap +// +// Sections +// 1) GRID UNITS +// +//******************************************* + + + +//******************************************* +// +// GRID UNITS +// +//******************************************* +$gridUnit-smallest: 0.9rem; +$gridUnit-smaller: 1.6rem; +$gridUnit-small: 2.1rem; +$gridUnit-default: 2.8rem; +$gridUnit-large: 3.8rem; +$gridUnit-larger: 5rem; +$gridUnit-largest: 9rem; \ No newline at end of file diff --git a/build/createjsTheme/assets/scss/settings/path.scss b/build/createjsTheme/assets/scss/settings/path.scss new file mode 100644 index 00000000..ab5da454 --- /dev/null +++ b/build/createjsTheme/assets/scss/settings/path.scss @@ -0,0 +1,29 @@ +//******************************************* +// +// PATH SETTINGS +// Variables for defining file paths in your project +// +// Contents +// 1) MY PROJECT +// 2) PROJECT ASSETS +// +//******************************************* + + + +//******************************************* +// +// MY PROJECT +// +//******************************************* +$path-myProject: "../../"; + + + +//******************************************* +// +// PROJECT ASSETS +// +//******************************************* +$path-fonts: $path-myProject + "assets/fonts/"; +$path-images: $path-myProject + "assets/images/"; diff --git a/build/createjsTheme/assets/scss/settings/transition.scss b/build/createjsTheme/assets/scss/settings/transition.scss new file mode 100644 index 00000000..ca4aef4a --- /dev/null +++ b/build/createjsTheme/assets/scss/settings/transition.scss @@ -0,0 +1,57 @@ +//******************************************* +// +// TRANSITION SETTINGS +// Default transition settings used by gBootstrap +// +// Contents +// 1) DURATIONS +// 2) EASING +// 3) COMBINATIONS +// +//******************************************* + + + +//******************************************* +// +// DURATIONS +// +//******************************************* +$duration-short: 0.1s; +$duration-default: 0.2s; +$duration-long: 0.4s; +$duration-longer: 0.6s; +// $duration-longest: 0.8s; + + +//******************************************* +// +// EASING +// +//******************************************* +$ease-default: cubic-bezier( 0.6, 0.18, 0.32, 0.95 ); +$ease-inOut: cubic-bezier( 0.55, 0, 0.45, 1 ); +$ease-out: cubic-bezier( 0.4, 0.18, 0.32, 1 ); + + + +//******************************************* +// +// COMBINATIONS +// +//******************************************* +$transition-short-default: $duration-short $ease-default; +$transition-short-out: $duration-short $ease-out; +$transition-short-inOut: $duration-short $ease-inOut; + +$transition-default-default: $duration-default $ease-default; +$transition-default-inOut: $duration-default $ease-inOut; +$transition-default-out: $duration-default $ease-out; + +$transition-long-default: $duration-long $ease-default; +$transition-long-inOut: $duration-long $ease-inOut; +$transition-long-out: $duration-long $ease-out; + +$transition-longer-default: $duration-longer $ease_default; +$transition-longer-out: $duration-longer $ease_out; + diff --git a/build/createjsTheme/assets/scss/utilities/breakpoint.scss b/build/createjsTheme/assets/scss/utilities/breakpoint.scss new file mode 100755 index 00000000..8f4f4410 --- /dev/null +++ b/build/createjsTheme/assets/scss/utilities/breakpoint.scss @@ -0,0 +1,144 @@ +//******************************************* +// +// BREAKPOINT UTILITY +// +// Description +// - Utilities for creating breakpoints +// +// Contents +// 1) WIDTH +// 2) HEIGHT +// 3) ASPEECT RATIO +// 4) ORIENTATION +// 5) PIXEL DENSITY +// +// Notes +// - Default prefix favors mobile and portrait first design principles. +// +// Acknowledgements: +// Chris Coyier: http://css-tricks.com/media-queries-sass-3-2-and-codekit/ +// +//******************************************* + + + +//******************************************* +// +// WIDTH OR HEIGHT +// +// Notes +// - also accepts orientation, and prefix params (min-, max-, min-device-, max-device-) +// - supports end range +// +//******************************************* + +@mixin bp ($bp, $prefix: min-, $bpEndRange: null, $orientation: null, $direction: width, $endRangePrefix: max-) { + + // Define focus direction of breakpoint statement (width or height) + @if $direction == "height" { + $prefix: $prefix + "height: "; + } @else { + $prefix: $prefix + "width: "; + } + + // Re-define orientation variable if value exists + @if $orientation != null { + $orientation: "orientation:" + $orientation; + } + + // Output statement for single condition value (includes orientation if applied) + @if $bpEndRange == null { + + @if $orientation == null { // Checks to see if there is an orientation value + @media ($prefix $bp) { @content }; + } @else { + @media ($prefix $bp) and ($orientation) { @content; } + } + + // Output statement for end range condition value (includes orientation if applied) + } @else { + + // Define focus direction of breakpoint end range statement (width or height) + @if $direction == "height" { + $endRangePrefix: $endRangePrefix + "height: "; + } @else { + $endRangePrefix: $endRangePrefix + "width: "; + } + + @if $orientation == null { // Checks to see if there is an orientation value + @media ($prefix $bp) and ($endRangePrefix $bpEndRange) { @content }; + } @else { + @media ($prefix $bp) and ($endRangePrefix $bpEndRange) and ($orientation) { @content; } + } + + } +} + + +//******************************************* +// +// ASPECT RATIO +// +// Notes +// - $aspectRatio syntax '16/9' +// +//******************************************* +// Aspect Ratio with width limitation +@mixin bpAspectRatio ($aspectRatio: null, $width: null) { + @if $aspectRatio != null { + @if $width == null { + @media (max-aspect-ratio: $aspectRatio) { @content; } + } @else { + @media (max-aspect-ratio: $aspectRatio) and (min-width: $width) { @content; } + } + } +} + + + +//******************************************* +// +// ORIENTATION +// +//******************************************* +@mixin bpOrientation ($orientation: portrait, $width: null, $prefix: min-) { + $width-prefix: $prefix + "width: "; + @if $width == null { + @media (orientation: $orientation) { @content; } + } @else { + @media (orientation: $orientation) and ($width-prefix $width) { @content; } + } +} + + + +//******************************************* +// +// PIXEL DENSITIES +// +// Common Device Pixel Ratios +// 1.25, 1.3, 1.5, 2 +// +//******************************************* +@mixin bpPixelDensity ($pd: 2) { + // 1.25 + @if $pd == 1.25 { + @media (-webkit-min-device-pixel-ratio: $pd), + (min-resolution: 120dpi) { @content; } + } + // 1.3 + @if $pd == 1.3 { + @media (-webkit-min-device-pixel-ratio: $pd), + (min-resolution: 124.8dpi) { @content; } + } + // 1.5 + @if $pd == 1.5 { + @media (-webkit-min-device-pixel-ratio: $pd), + (min-resolution: 144dpi) { @content; } + } + // 2 + @if $pd == 2 { + @media (-webkit-min-device-pixel-ratio: $pd), + (min-resolution: 192dpi) { @content; } + } +} \ No newline at end of file diff --git a/build/createjsTheme/assets/scss/utilities/clearfix.scss b/build/createjsTheme/assets/scss/utilities/clearfix.scss new file mode 100644 index 00000000..cf99750a --- /dev/null +++ b/build/createjsTheme/assets/scss/utilities/clearfix.scss @@ -0,0 +1,28 @@ +//******************************************* +// +// CLEAR FIX UTILITIES +// +// Details +// - Utility for clearing floats +// +// Contents +// 1) CLEARFIX +// +//******************************************* + + + +//******************************************* +// +// CLEARFIX +// +//******************************************* +%clearfix { + zoom: 1; // For IE 6/7 (trigger hasLayout) + &::before, + &::after { + content: ""; + display: table; + } + &::after { clear: both; } +} diff --git a/build/createjsTheme/layouts/main.handlebars b/build/createjsTheme/layouts/main.handlebars index b9af452f..71f49b0c 100755 --- a/build/createjsTheme/layouts/main.handlebars +++ b/build/createjsTheme/layouts/main.handlebars @@ -35,7 +35,7 @@ {{>options}}
-
+
{{>layout_content}}
diff --git a/build/createjsTheme/partials/props.handlebars b/build/createjsTheme/partials/props.handlebars index 8385ad17..a94b44d9 100755 --- a/build/createjsTheme/partials/props.handlebars +++ b/build/createjsTheme/partials/props.handlebars @@ -18,6 +18,10 @@ static {{/if}} + {{#if readonly}} + readonly + {{/if}} +
{{#if overwritten_from}}

Inherited from diff --git a/build/package.json b/build/package.json index 34354974..380e4973 100644 --- a/build/package.json +++ b/build/package.json @@ -1,18 +1,20 @@ { - "name": "PreloadJS", - "version": "0.4.1", - "description": "PreloadJS Docs", - "url": "http://www.createjs.com/#!/PreloadJS", - "logo": "assets/docs-icon-PreloadJS.png", - "devDependencies": { - "grunt": "~0.4.1", - "grunt-contrib-concat": "~0.3.0", - "grunt-contrib-uglify": "~0.2.1", - "grunt-contrib-yuidoc": "~0.4.0", - "grunt-contrib-compress": "~0.5.0", - "grunt-contrib-copy": "~0.4.1", - "lodash": "~0.9.0", - "grunt-hub":"" - }, - "engine": "node >= 0.10.22" + "name": "PreloadJS", + "version": "1.0.0", + "description": "PreloadJS Docs", + "url": "http://www.createjs.com/preloadjs", + "logo": "assets/docs-icon-PreloadJS.png", + "repository": "git@github.com:CreateJS/PreloadJS.git", + "devDependencies": { + "grunt": "~0.4.5", + "grunt-contrib-concat": "~0.5.0", + "grunt-contrib-uglify": "~0.6.0", + "grunt-contrib-yuidoc": "~0.5.2", + "grunt-contrib-compress": "~0.12.0", + "grunt-contrib-copy": "~0.7.0", + "grunt-contrib-sass": "^0.8.1", + "grunt-contrib-clean":"^0.4.0", + "lodash": "~0.9.2" + }, + "engine": "node >= 0.10.22" } diff --git a/build/tasks/updateversion.js b/build/tasks/updateversion.js index 9a7ae8d3..eec62239 100644 --- a/build/tasks/updateversion.js +++ b/build/tasks/updateversion.js @@ -1,36 +1,36 @@ module.exports = function (grunt) { grunt.registerMultiTask('updateversion', function() { - var data = this.data; - var file = data.file; - var version = data.version; + var newValues = {date:new Date().toUTCString(), version:this.data.version}; + replaceMetaData(this.data.file, newValues); + }); + grunt.registerMultiTask('clearversion', function() { + // Don't clear the version when building everything (the combined build will run this after its done) + var buildArgs = grunt.config("buildArgs"); + if (buildArgs && buildArgs[0] == "all") { + return; + } + replaceMetaData(this.data.file, {date:"", version:""}); + }); + + function replaceMetaData(file, values) { if (!grunt.file.exists(file)) { grunt.log.error(file+' not found.'); return; } - var contents = grunt.file.read(file); - var pattern = /\/\*version\*\/"([\w.]+)"/g; - - var newValues = {date:new Date().toUTCString(), version:version}; - var newFile = replaceMetaData(contents, newValues); - grunt.file.write(file, newFile); - }); + var str = grunt.file.read(file); - function replaceMetaData(data, values) { - var finalResult = ""; - var newData = data; for(var n in values) { - var pattern = new RegExp("(\/\\*"+n+"\\*\/\")(.*)(\";)", "i"); - var result = pattern.test(data); + var pattern = new RegExp("(\/\\*="+n+"\\*\/\")(.*)(\";)", "g"); + var result = pattern.test(str); if (result) { - finalResult = newData.replace(pattern, "$1"+values[n]+"$3"); - newData = finalResult; + str = str.replace(pattern, "$1"+values[n]+"$3"); } else { grunt.log.error("Error -- Unable to resolve value:"+ pattern); } } - return finalResult; + grunt.file.write(file, str); } } diff --git a/build/updates/README.md b/build/updates/README.md new file mode 100644 index 00000000..ea33056c --- /dev/null +++ b/build/updates/README.md @@ -0,0 +1,11 @@ +## Important ## + +The current YUIDocs does not support @readonly on properties (only attributes). This folder contains an updated +`builder.js`, which injects this support. + +Copy `builder.js` into + > node_modules/grunt-contrib-yuidoc/node-modules/yuidocjs/lib + +Without this file, properties will not show the "readonly" flag. + +Last tested with YUIDocs 0.5.2 \ No newline at end of file diff --git a/build/updates/builder.js b/build/updates/builder.js new file mode 100644 index 00000000..63c8e6d7 --- /dev/null +++ b/build/updates/builder.js @@ -0,0 +1,1663 @@ +/* +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://yuilibrary.com/license/ +*/ +var marked = require('marked'), + fs = require('graceful-fs'), + noop = function () {}, + path = require('path'), + TEMPLATE; + +/** +* Takes the `JSON` data from the `DocParser` class, creates and parses markdown and handlebars +based templates to generate static HTML content +* @class DocBuilder +* @module yuidoc +*/ + +YUI.add('doc-builder', function (Y) { + /*jshint onevar:false */ + + var fixType = Y.Lang.fixType, + print = function (items) { + var out = '

    '; + + Y.each(items, function (i, k) { + out += '
  • '; + if (Y.Lang.isObject(i)) { + if (!i.path) { + out += k + '/' + print(i); + } else { + out += '' + k + ''; + } + } + out += '
  • '; + }); + + out += '
'; + return out; + }; + + Y.Handlebars.registerHelper('buildFileTree', function (items) { + return print(items); + }); + + var DEFAULT_THEME = path.join(__dirname, '../', 'themes', 'default'), + themeDir = DEFAULT_THEME; + + Y.DocBuilder = function (options, data) { + this.options = options; + if (options.helpers) { + this._addHelpers(options.helpers); + } + if (options.themedir) { + themeDir = options.themedir; + } + + this.data = data; + Y.log('Building..', 'info', 'builder'); + this.files = 0; + var self = this; + + Y.Handlebars.registerHelper('crossLink', function (item, options) { + var str = ''; + if (!item) { + item = ''; + } + //console.log('CrossLink:', item); + if (item.indexOf('|') > 0) { + var parts = item.split('|'), + p = []; + Y.each(parts, function (i) { + p.push(self._parseCrossLink.call(self, i)); + }); + str = p.join(' | '); + } else { + str = self._parseCrossLink.call(self, item, false, options.fn(this)); + } + return str; + }); + + Y.Handlebars.registerHelper('crossLinkModule', function (item, options) { + var str = item; + if (self.data.modules[item]) { + var content = options.fn(this); + if (content === "") { + content = item; + } + str = '' + content + ''; + } + return str; + }); + + Y.Handlebars.registerHelper('crossLinkRaw', function (item) { + var str = ''; + if (!item) { + item = ''; + } + if (item.indexOf('|') > 0) { + var parts = item.split('|'), + p = []; + Y.each(parts, function (i) { + p.push(self._parseCrossLink.call(self, i, true)); + }); + str = p.join(' | '); + } else { + str = self._parseCrossLink.call(self, item, true); + } + return str; + }); + + this.cacheTemplates = true; + if (options.cacheTemplates === false) { + this.cacheTemplates = false; + } + }; + + Y.DocBuilder.prototype = { + /** + * Register a `Y.Handlebars` helper method + * @method _addHelpers + * @param {Object} helpers Object containing a hash of names and functions + */ + _addHelpers: function (helpers) { + Y.log('Importing helpers: ' + helpers, 'info', 'builder'); + helpers.forEach(function (imp) { + if (!Y.Files.exists(imp) || Y.Files.exists(path.join(process.cwd(), imp))) { + imp = path.join(process.cwd(), imp); + } + var h = require(imp); + Object.keys(h).forEach(function (name) { + Y.Handlebars.registerHelper(name, h[name]); + }); + }); + }, + /** + * Wrapper around the Markdown parser so it can be normalized or even side stepped + * @method markdown + * @private + * @param {String} md The Markdown string to parse + * @return {HTML} The rendered HTML + */ + markdown: function (md) { + var html = marked(md, this.options.markdown); + //Only reprocess if helpers were asked for + if (this.options.helpers || (html.indexOf('{{#crossLink') > -1)) { + //console.log('MD: ', html); + try { + // marked auto-escapes quotation marks (and unfortunately + // does not expose the escaping function) + html = html.replace(/"/g, "\""); + html = (Y.Handlebars.compile(html))({}); + } catch (hError) { + //Remove all the extra escapes + html = html.replace(/\\{/g, '{').replace(/\\}/g, '}'); + Y.log('Failed to parse Handlebars, probably an unknown helper, skipping..', 'warn', 'builder'); + } + //console.log('HB: ', html); + } + return html; + }, + + /** + * Parse the item to be cross linked and return an HREF linked to the item + * @method _parseCrossLink + * @private + * @param {String} item The item to crossLink + * @param {Boolean} [raw=false] Do not wrap it in HTML + * @param {String} [content] crossLink helper content + */ + _parseCrossLink: function (item, raw, content) { + var self = this; + var base = '../', + baseItem, + newWin = false, + className = 'crosslink'; + + item = fixType(item); + + item = baseItem = Y.Lang.trim(item.replace('{', '').replace('}', '')); + //Remove Cruft + item = item.replace('*', '').replace('[', '').replace(']', ''); + var link = false, + href; + + if (self.data.classes[item]) { + link = true; + } else { + if (self.data.classes[item.replace('.', '')]) { + link = true; + item = item.replace('.', ''); + } + } + if (self.options.externalData) { + if (self.data.classes[item]) { + if (self.data.classes[item].external) { + href = self.data.classes[item].path; + base = self.options.externalData.base; + className += ' external'; + newWin = true; + link = true; + } + } + } + + if (item.indexOf('/') > -1) { + //We have a class + method to parse + var parts = item.split('/'), + cls = parts[0], + method = parts[1], + type = 'method'; + + if (method.indexOf(':') > -1) { + parts = method.split(':'); + method = parts[0]; + type = parts[1]; + if (type.indexOf('attr') === 0) { + type = 'attribute'; + } + } + + if (cls && method) { + if (self.data.classes[cls]) { + self.data.classitems.forEach(function (i) { + if (i.itemtype === type && i.name === method && i.class === cls) { + link = true; + baseItem = method; + var t = type; + if (t === 'attribute') { + t = 'attr'; + } + href = Y.webpath(base, 'classes', cls + '.html#' + t + '_' + method); + } + }); + } + } + + } + + if (item === 'Object' || item === 'Array') { + link = false; + } + if (!href) { + href = Y.webpath(base, 'classes', item + '.html'); + if (base.match(/^https?:\/\//)) { + href = base + Y.webpath('classes', item + '.html'); + } + } + if (!link && self.options.linkNatives) { + if (self.NATIVES && self.NATIVES[item]) { + href = self.NATIVES_LINKER(item); + if (href) { + className += ' external'; + newWin = true; + link = true; + } + } + } + if (link) { + if (content !== undefined) { + content = content.trim(); + } + if (!content) { + content = baseItem; + } + item = '' + content + ''; + } + return (raw) ? href : item; + }, + /** + * List of native types to cross link to MDN + * @property NATIVES + * @type Object + */ + NATIVES: { + 'Array': 1, + 'Boolean': 1, + 'Date': 1, + 'decodeURI': 1, + 'decodeURIComponent': 1, + 'encodeURI': 1, + 'encodeURIComponent': 1, + 'eval': 1, + 'Error': 1, + 'EvalError': 1, + 'Function': 1, + 'Infinity': 1, + 'isFinite': 1, + 'isNaN': 1, + 'Math': 1, + 'NaN': 1, + 'Number': 1, + 'Object': 1, + 'parseFloat': 1, + 'parseInt': 1, + 'RangeError': 1, + 'ReferenceError': 1, + 'RegExp': 1, + 'String': 1, + 'SyntaxError': 1, + 'TypeError': 1, + 'undefined': 1, + 'URIError': 1, + 'HTMLElement': 'https:/' + '/developer.mozilla.org/en/Document_Object_Model_(DOM)/', + 'HTMLCollection': 'https:/' + '/developer.mozilla.org/en/Document_Object_Model_(DOM)/', + 'DocumentFragment': 'https:/' + '/developer.mozilla.org/en/Document_Object_Model_(DOM)/', + 'HTMLDocument': 'https:/' + '/developer.mozilla.org/en/Document_Object_Model_(DOM)/' + }, + /** + * Function to link an external type uses `NATIVES` object + * @method NATIVES_LINKER + * @private + * @param {String} name The name of the type to link + * @return {String} The combined URL + */ + NATIVES_LINKER: function (name) { + var url = 'https:/' + '/developer.mozilla.org/en/JavaScript/Reference/Global_Objects/'; + if (this.NATIVES[name] !== 1) { + url = this.NATIVES[name]; + } + return url + name; + }, + /** + * Mixes the various external data soures together into the local data, augmenting + * it with flags. + * @method _mixExternal + * @private + */ + _mixExternal: function () { + var self = this; + Y.log('External data received, mixing', 'info', 'builder'); + self.options.externalData.forEach(function (exData) { + + ['files', 'classes', 'modules'].forEach(function (k) { + Y.each(exData[k], function (item, key) { + item.external = true; + var file = item.name; + if (!item.file) { + file = self.filterFileName(item.name); + } + + if (item.type) { + item.type = fixType(item.type); + } + + item.path = exData.base + path.join(k, file + '.html'); + + self.data[k][key] = item; + }); + }); + Y.each(exData.classitems, function (item) { + item.external = true; + item.path = exData.base + path.join('files', self.filterFileName(item.file) + '.html'); + if (item.type) { + item.type = fixType(item.type); + } + if (item.params) { + item.params.forEach(function (p) { + if (p.type) { + p.type = fixType(p.type); + } + }); + } + if (item["return"]) { + item["return"].type = fixType(item["return"].type); + } + self.data.classitems.push(item); + }); + }); + }, + /** + * Fetches the remote data and fires the callback when it's all complete + * @method mixExternal + * @param {Callback} cb The callback to execute when complete + * @async + */ + mixExternal: function (cb) { + var self = this, + info = self.options.external; + + if (!info) { + cb(); + return; + } + if (!info.merge) { + info.merge = 'mix'; + } + if (!info.data) { + Y.log('External config found but no data path defined, skipping import.', 'warn', 'builder'); + cb(); + return; + } + if (!Y.Lang.isArray(info.data)) { + info.data = [info.data]; + } + Y.log('Importing external documentation data.', 'info', 'builder'); + + var stack = new Y.Parallel(); + info.data.forEach(function (i) { + var base; + if (i.match(/^https?:\/\//)) { + base = i.replace('data.json', ''); + Y.use('io-base', stack.add(function () { + Y.log('Fetching: ' + i, 'info', 'builder'); + Y.io(i, { + on: { + complete: stack.add(function (id, e) { + Y.log('Received: ' + i, 'info', 'builder'); + var data = JSON.parse(e.responseText); + data.base = base; + //self.options.externalData = Y.mix(self.options.externalData || {}, data); + if (!self.options.externalData) { + self.options.externalData = []; + } + self.options.externalData.push(data); + }) + } + }); + })); + } else { + base = path.dirname(path.resolve(i)); + var data = Y.Files.getJSON(i); + data.base = base; + //self.options.externalData = Y.mix(self.options.externalData || {}, data); + if (!self.options.externalData) { + self.options.externalData = []; + } + self.options.externalData.push(data); + } + }); + + stack.done(function () { + Y.log('Finished fetching remote data', 'info', 'builder'); + self._mixExternal(); + cb(); + }); + }, + /** + * File counter + * @property files + * @type Number + */ + files: null, + /** + * Holder for project meta data + * @property _meta + * @type Object + * @private + */ + _meta: null, + /** + * Prep the meta data to be fed to Selleck + * @method getProjectMeta + * @return {Object} The project metadata + */ + getProjectMeta: function () { + var obj = { + meta: { + yuiSeedUrl: 'http://yui.yahooapis.com/3.5.0/build/yui/yui-min.js', + yuiGridsUrl: 'http://yui.yahooapis.com/3.5.0/build/cssgrids/cssgrids-min.css' + } + }; + if (!this._meta) { + try { + var meta, + theme = path.join(themeDir, 'theme.json'); + if (Y.Files.exists(theme)) { + Y.log('Loading theme from ' + theme, 'info', 'builder'); + meta = Y.Files.getJSON(theme); + } else if (DEFAULT_THEME !== themeDir) { + theme = path.join(DEFAULT_THEME, 'theme.json'); + if (Y.Files.exists(theme)) { + Y.log('Loading theme from ' + theme, 'info', 'builder'); + meta = Y.Files.getJSON(theme); + } + } + + if (meta) { + obj.meta = meta; + this._meta = meta; + } + } catch (e) { + console.error('Error', e); + } + } else { + obj.meta = this._meta; + } + Y.each(this.data.project, function (v, k) { + var key = k.substring(0, 1).toUpperCase() + k.substring(1, k.length); + obj.meta['project' + key] = v; + }); + return obj; + }, + /** + * Populate the meta data for classes + * @method populateClasses + * @param {Object} opts The original options + * @return {Object} The modified options + */ + populateClasses: function (opts) { + opts.meta.classes = []; + Y.each(this.data.classes, function (v) { + if (v.external) { + return; + } + opts.meta.classes.push({ + displayName: v.name, + name: v.name, + namespace: v.namespace, + module: v.module, + description: v.description, + access: v.access || 'public' + }); + }); + opts.meta.classes.sort(this.nameSort); + return opts; + }, + /** + * Populate the meta data for modules + * @method populateModules + * @param {Object} opts The original options + * @return {Object} The modified options + */ + populateModules: function (opts) { + var self = this; + opts.meta.modules = []; + opts.meta.allModules = []; + Y.each(this.data.modules, function (v) { + if (v.external) { + return; + } + opts.meta.allModules.push({ + displayName: v.displayName || v.name, + name: self.filterFileName(v.name), + description: v.description + }); + if (!v.is_submodule) { + var o = { + displayName: v.displayName || v.name, + name: self.filterFileName(v.name) + }; + if (v.submodules) { + o.submodules = []; + Y.each(v.submodules, function (i, k) { + var moddef = self.data.modules[k]; + if (moddef) { + o.submodules.push({ + displayName: k, + description: moddef.description + }); + // } else { + // Y.log('Submodule data missing: ' + k + ' for ' + v.name, 'warn', 'builder'); + } + }); + o.submodules.sort(self.nameSort); + } + opts.meta.modules.push(o); + } + }); + opts.meta.modules.sort(this.nameSort); + opts.meta.allModules.sort(this.nameSort); + return opts; + }, + /** + * Populate the meta data for files + * @method populateFiles + * @param {Object} opts The original options + * @return {Object} The modified options + */ + populateFiles: function (opts) { + var self = this; + opts.meta.files = []; + Y.each(this.data.files, function (v) { + if (v.external) { + return; + } + opts.meta.files.push({ + displayName: v.name, + name: self.filterFileName(v.name), + path: v.path || v.name + }); + }); + + var tree = {}; + var files = []; + Y.each(this.data.files, function (v) { + if (v.external) { + return; + } + files.push(v.name); + }); + files.sort(); + Y.each(files, function (v) { + var p = v.split('/'), + par; + p.forEach(function (i, k) { + if (!par) { + if (!tree[i]) { + tree[i] = {}; + } + par = tree[i]; + } else { + if (!par[i]) { + par[i] = {}; + } + if (k + 1 === p.length) { + par[i] = { + path: v, + name: self.filterFileName(v) + }; + } + par = par[i]; + } + }); + }); + + opts.meta.fileTree = tree; + + return opts; + }, + /** + * Parses file and line number from an item object and build's an HREF + * @method addFoundAt + * @param {Object} a The item to parse + * @return {String} The parsed HREF + */ + addFoundAt: function (a) { + var self = this; + if (a.file && a.line && !self.options.nocode) { + a.foundAt = '../files/' + self.filterFileName(a.file) + '.html#l' + a.line; + if (a.path) { + a.foundAt = a.path + '#l' + a.line; + } + } + return a; + }, + /** + * Augments the **DocParser** meta data to provide default values for certain keys as well as parses all descriptions + * with the `Markdown Parser` + * @method augmentData + * @param {Object} o The object to recurse and augment + * @return {Object} The augmented object + */ + augmentData: function (o) { + var self = this; + o = self.addFoundAt(o); + Y.each(o, function (i, k1) { + if (i && i.forEach) { + Y.each(i, function (a, k) { + if (!(a instanceof Object)) { + return; + } + if (!a.type) { + a.type = 'Object'; //Default type is Object + } + if (a.final === '') { + a.final = true; + } + if (!a.description) { + a.description = ' '; + } else { + //a.description = markdown(a.description, true, self.defaultTags); + a.description = self.markdown(a.description); + } + if (a.example) { + a.example = self.markdown(a.example); + } + a = self.addFoundAt(a); + + Y.each(a, function (c, d) { + if (c.forEach || (c instanceof Object)) { + c = self.augmentData(c); + a[d] = c; + } + }); + + o[k1][k] = a; + }); + } else if (i instanceof Object) { + i = self.addFoundAt(i); + Y.each(i, function (v, k) { + if (k === 'final') { + o[k1][k] = true; + } + if (k === 'description' || k === 'example') { + if (k1 === 'return') { + o[k1][k] = self.markdown(v); + } else if (v.forEach || (v instanceof Object)) { + o[k1][k] = self.augmentData(v); + } else { + //o[k1][k] = markdown(v, true, self.defaultTags); + o[k1][k] = self.markdown(v); + } + } + }); + } else if (k1 === 'description' || k1 === 'example') { + //o[k1] = markdown(i, true, self.defaultTags); + o[k1] = self.markdown(i); + } + }); + return o; + }, + /** + * Makes the default directories needed + * @method makeDirs + * @param {Callback} cb The callback to execute after it's completed + */ + makeDirs: function (cb) { + var self = this; + var dirs = ['classes', 'modules', 'files']; + if (self.options.dumpview) { + dirs.push('json'); + } + var writeRedirect = function (dir, file, cb) { + Y.Files.exists(file, function (x) { + if (x) { + var out = path.join(dir, 'index.html'); + fs.createReadStream(file).pipe(fs.createWriteStream(out)); + } + cb(); + }); + }; + var defaultIndex = path.join(themeDir, 'assets', 'index.html'); + var stack = new Y.Parallel(); + Y.log('Making default directories: ' + dirs.join(','), 'info', 'builder'); + dirs.forEach(function (d) { + var dir = path.join(self.options.outdir, d); + Y.Files.exists(dir, stack.add(function (x) { + if (!x) { + fs.mkdir(dir, 0777, stack.add(function () { + writeRedirect(dir, defaultIndex, stack.add(noop)); + })); + } else { + writeRedirect(dir, defaultIndex, stack.add(noop)); + } + })); + }); + stack.done(function () { + if (cb) { + cb(); + } + }); + }, + + + _resolveUrl: function (url, opts) { + if (!url) { + return null; + } + if (url.indexOf("://") >= 0) { + return url; + } + return path.join(opts.meta.projectRoot, url); + }, + + /** + * Parses `
` tags and adds the __prettyprint__ `className` to them
+         * @method _parseCode
+         * @private
+         * @param {HTML} html The HTML to parse
+         * @return {HTML} The parsed HTML
+         */
+        _parseCode: function (html) {
+            html = html || '';
+            //html = html.replace(/
/g, '
');
+            html = html.replace(/
' + Y.escapeHTML(code) + '';
+            });
+
+            html = html.replace(/__\{\{SELLECK_BACKTICK\}\}__/g, '`');
+
+            return html;
+        },
+        /**
+        * Ported from [Selleck](https://github.com/rgrove/selleck)
+        Renders the handlebars templates with the default View class.
+        * @method render
+        * @param {HTML} source The default template to parse
+        * @param {Class} view The default view handler
+        * @param {HTML} [layout=null] The HTML from the layout to use.
+        * @param {Object} [partials=object] List of partials to include in this template
+        * @param {Callback} callback
+        * @param {Error} callback.err
+        * @param {HTML} callback.html The assembled template markup
+        */
+        render: function (source, view, layout, partials, callback) {
+            var html = [];
+
+            // function buffer(line) {
+            //     html.push(line);
+            // }
+
+            // Allow callback as third or fourth param.
+            if (typeof partials === 'function') {
+                callback = partials;
+                partials = {};
+            } else if (typeof layout === 'function') {
+                callback = layout;
+                layout = null;
+            }
+            var parts = Y.merge(partials || {}, {
+                layout_content: source
+            });
+            Y.each(parts, function (source, name) {
+                Y.Handlebars.registerPartial(name, source);
+            });
+
+            if (!TEMPLATE || !this.cacheTemplates) {
+                TEMPLATE = Y.Handlebars.compile(layout);
+            }
+
+
+            var _v = {};
+            for (var k in view) {
+                if (Y.Lang.isFunction(view[k])) {
+                    _v[k] = view[k]();
+                } else {
+                    _v[k] = view[k];
+                }
+            }
+            html = TEMPLATE(_v);
+            //html = html.replace(/{{//g, '{{/');
+
+
+            //html = (Y.Handlebars.compile(html))({});
+
+            html = this._inlineCode(html);
+            callback(null, html);
+        },
+        /**
+         * Render the index file
+         * @method renderIndex
+         * @param {Function} cb The callback fired when complete
+         * @param {String} cb.html The HTML to render this view
+         * @param {Object} cv.view The View Data
+         */
+        renderIndex: function (cb) {
+            var self = this;
+
+            Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function (err, opts) {
+                opts.meta.title = self.data.project.name;
+                opts.meta.projectRoot = './';
+                opts.meta.projectAssets = './assets';
+                opts.meta.projectLogo = self._resolveUrl(self.data.project.logo, opts);
+                opts = self.populateClasses(opts);
+                opts = self.populateModules(opts);
+
+                var view = new Y.DocView(opts.meta);
+                self.render('{{>index}}', view, opts.layouts.main, opts.partials, function (err, html) {
+                    self.files++;
+                    cb(html, view);
+                });
+            });
+        },
+        /**
+         * Generates the index.html file
+         * @method writeIndex
+         * @param {Callback} cb The callback to execute after it's completed
+         */
+        writeIndex: function (cb) {
+            var self = this,
+                stack = new Y.Parallel();
+
+            Y.log('Preparing index.html', 'info', 'builder');
+            self.renderIndex(stack.add(function (html, view) {
+                stack.html = html;
+                stack.view = view;
+                if (self.options.dumpview) {
+                    Y.Files.writeFile(path.join(self.options.outdir, 'json', 'index.json'), JSON.stringify(view), stack.add(noop));
+                }
+                Y.Files.writeFile(path.join(self.options.outdir, 'index.html'), html, stack.add(noop));
+            }));
+
+            stack.done(function ( /* html, view */ ) {
+                Y.log('Writing index.html', 'info', 'builder');
+                cb(stack.html, stack.view);
+            });
+        },
+        /**
+         * Render a module
+         * @method renderModule
+         * @param {Function} cb The callback fired when complete
+         * @param {String} cb.html The HTML to render this view
+         * @param {Object} cv.view The View Data
+         */
+        renderModule: function (cb, data, layout) {
+            var self = this;
+            var stack = new Y.Parallel();
+
+            data.displayName = data.name;
+            data.name = self.filterFileName(data.name);
+            Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function (err, opts) {
+                opts.meta = Y.merge(opts.meta, data);
+
+                //opts.meta.htmlTitle = v.name + ': ' + self.data.project.name;
+                opts.meta.title = self.data.project.name;
+
+                opts.meta.moduleName = data.displayName || data.name;
+                opts.meta.moduleDescription = self._parseCode(self.markdown(data.description || ' '));
+                opts.meta.file = data.file;
+                opts.meta.line = data.line;
+                opts.meta = self.addFoundAt(opts.meta);
+                opts.meta.projectRoot = '../';
+                opts.meta.projectAssets = '../assets';
+                opts.meta.projectLogo = self._resolveUrl(self.data.project.logo, opts);
+                opts = self.populateClasses(opts);
+                opts = self.populateModules(opts);
+                opts = self.populateFiles(opts);
+
+                if (data.classes && Object.keys(data.classes).length) {
+                    opts.meta.moduleClasses = [];
+                    Y.each(Object.keys(data.classes), function (name) {
+                        var i = self.data.classes[name];
+                        if (i) {
+                            opts.meta.moduleClasses.push({
+                                name: i.name,
+                                displayName: i.name
+                            });
+                        }
+                    });
+                    opts.meta.moduleClasses.sort(self.nameSort);
+                }
+                if (data.example && data.example.length) {
+                    if (data.example.forEach) {
+                        var e = '';
+                        data.example.forEach(function (v) {
+                            e += self._parseCode(self.markdown(v));
+                        });
+                        data.example = e;
+                    } else {
+                        data.example = self._parseCode(self.markdown(data.example));
+                    }
+                    opts.meta.example = data.example;
+                }
+                if (data.submodules && Object.keys(data.submodules).length) {
+                    opts.meta.subModules = [];
+                    Y.each(Object.keys(data.submodules), function (name) {
+                        var i = self.data.modules[name];
+                        if (i) {
+                            opts.meta.subModules.push({
+                                name: i.name,
+                                displayName: i.name,
+                                description: i.description
+                            });
+                        }
+                    });
+                    opts.meta.subModules.sort(self.nameSort);
+                }
+
+                var view = new Y.DocView(opts.meta);
+                var mainLayout = opts.layouts[layout];
+                self.render('{{>module}}', view, mainLayout, opts.partials, stack.add(function (err, html) {
+                    self.files++;
+                    stack.html = html;
+                    stack.view = view;
+                }));
+            });
+
+            stack.done(function () {
+                cb(stack.html, stack.view);
+            });
+        },
+        /**
+         * Generates the module files under "out"/modules/
+         * @method writeModules
+         * @param {Callback} cb The callback to execute after it's completed
+         */
+        writeModules: function (cb, layout) {
+            layout = layout || 'main';
+            var self = this,
+                stack = new Y.Parallel();
+            stack.html = [];
+            stack.view = [];
+
+            var counter = 0;
+            Object.keys(self.data.modules).forEach(function (k) {
+                if (!self.data.modules[k].external) {
+                    counter++;
+                }
+            });
+            Y.log('Rendering and writing ' + counter + ' modules pages.', 'info', 'builder');
+            Y.each(self.data.modules, function (v) {
+                if (v.external) {
+                    return;
+                }
+                self.renderModule(function (html, view) {
+                    stack.html.push(html);
+                    stack.view.push(view);
+                    if (self.options.dumpview) {
+                        Y.Files.writeFile(
+                            path.join(self.options.outdir, 'json', 'module_' + v.name + '.json'),
+                            JSON.stringify(view),
+                            stack.add(noop)
+                        );
+                    }
+                    Y.Files.writeFile(path.join(self.options.outdir, 'modules', v.name + '.html'), html, stack.add(noop));
+                }, v, layout);
+            });
+            stack.done(function () {
+                Y.log('Finished writing module files', 'info', 'builder');
+                cb(stack.html, stack.view);
+            });
+        },
+        /**
+         * Checks an array of items (class items) to see if an item is in that list
+         * @method hasProperty
+         * @param {Array} a The Array of items to check
+         * @param {Object} b The object to find
+         * @return Boolean
+         */
+        hasProperty: function (a, b) {
+            var other = false;
+            Y.some(a, function (i, k) {
+                if ((i.itemtype === b.itemtype) && (i.name === b.name)) {
+                    other = k;
+                    return true;
+                }
+            });
+            return other;
+        },
+        /**
+         * Counter for stepping into merges
+         * @private
+         * @property _mergeCounter
+         * @type Number
+         */
+        _mergeCounter: null,
+        /**
+         * Merge superclass data into a child class
+         * @method mergeExtends
+         * @param {Object} info The item to extend
+         * @param {Array} classItems The list of items to merge in
+         * @param {Boolean} first Set for the first call
+         */
+        mergeExtends: function (info, classItems, first) {
+            var self = this;
+            self._mergeCounter = (first) ? 0 : (self._mergeCounter + 1);
+
+            if (self._mergeCounter === 100) {
+                throw ('YUIDoc detected a loop extending class ' + info.name);
+            }
+            if (info.extends || info.uses) {
+                var hasItems = {};
+                hasItems[info.extends] = 1;
+                if (info.uses) {
+                    info.uses.forEach(function (v) {
+                        hasItems[v] = 1;
+                    });
+                }
+                self.data.classitems.forEach(function (v) {
+                    //console.error(v.class, '==', info.extends);
+                    if (hasItems[v.class]) {
+                        if (!v.static) {
+                            var q,
+                                override = self.hasProperty(classItems, v);
+                            if (override === false) {
+                                //This method was extended from the parent class but not over written
+                                //console.error('Merging extends from', v.class, 'onto', info.name);
+                                q = Y.merge({}, v);
+                                q.extended_from = v.class;
+                                classItems.push(q);
+                            } else {
+                                //This method was extended from the parent and overwritten in this class
+                                q = Y.merge({}, v);
+                                q = self.augmentData(q);
+                                classItems[override].overwritten_from = q;
+                            }
+                        }
+                    }
+                });
+                if (self.data.classes[info.extends]) {
+                    if (self.data.classes[info.extends].extends || self.data.classes[info.extends].uses) {
+                        //console.error('Stepping down to:', self.data.classes[info.extends]);
+                        classItems = self.mergeExtends(self.data.classes[info.extends], classItems);
+                    }
+                }
+            }
+            return classItems;
+        },
+        /**
+         * Render the class file
+         * @method renderClass
+         * @param {Function} cb The callback fired when complete
+         * @param {String} cb.html The HTML to render this view
+         * @param {Object} cv.view The View Data
+         */
+        renderClass: function (cb, data, layout) {
+            var self = this;
+            var stack = new Y.Parallel();
+
+            Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function (err, opts) {
+                //console.log(opts);
+                if (err) {
+                    console.log(err);
+                }
+                opts.meta = Y.merge(opts.meta, data);
+
+                opts.meta.title = self.data.project.name;
+                opts.meta.moduleName = data.name;
+                opts.meta.file = data.file;
+                opts.meta.line = data.line;
+                opts.meta = self.addFoundAt(opts.meta);
+                opts.meta.projectRoot = '../';
+                opts.meta.projectAssets = '../assets';
+                opts.meta.projectLogo = self._resolveUrl(self.data.project.logo, opts);
+
+                opts = self.populateClasses(opts);
+                opts = self.populateModules(opts);
+                opts = self.populateFiles(opts);
+
+                opts.meta.classDescription = self._parseCode(self.markdown(data.description || ' '));
+
+                opts.meta.methods = [];
+                opts.meta.properties = [];
+                opts.meta.attrs = [];
+                opts.meta.events = [];
+                opts.meta.extension_for = null;
+                if (data.uses) {
+                    opts.meta.uses = data.uses;
+                }
+                if (data.entension_for && data.extension_for.length) {
+                    opts.meta.extension_for = data.extension_for;
+                }
+
+                if (data.extends) {
+                    opts.meta.extends = data.extends;
+                }
+
+                var classItems = [];
+                self.data.classitems.forEach(function (i) {
+                    if (i.class === data.name) {
+                        classItems.push(i);
+                    }
+                });
+
+                classItems = self.mergeExtends(data, classItems, true);
+
+                if (data.is_constructor) {
+                    var i = Y.mix({}, data);
+                    i = self.augmentData(i);
+                    i.paramsList = [];
+                    if (i.params) {
+                        i.params.forEach(function (p) {
+                            var name = p.name;
+                            if (p.optional) {
+                                name = '[' + name + ((p.optdefault) ? '=' + p.optdefault : '') + ']';
+                            }
+                            i.paramsList.push(name);
+                        });
+                    }
+                    //i.methodDescription = self._parseCode(markdown(i.description));
+                    i.hasAccessType = i.access;
+                    i.hasParams = i.paramsList.length;
+                    if (i.paramsList.length) {
+                        i.paramsList = i.paramsList.join(', ');
+                    } else {
+                        i.paramsList = ' ';
+                    }
+                    i.returnType = ' ';
+                    if (i["return"]) {
+                        i.hasReturn = true;
+                        i.returnType = i["return"].type;
+                    }
+                    //console.error(i);
+                    opts.meta.is_constructor = [i];
+                    if (i.example && i.example.length) {
+                        if (i.example.forEach) {
+                            var e = '';
+                            i.example.forEach(function (v) {
+                                e += self._parseCode(self.markdown(v));
+                            });
+                            i.example = e;
+                        } else {
+                            i.example = self._parseCode(self.markdown(i.example));
+                        }
+                    }
+                }
+
+                classItems.forEach(function (i) {
+                    var e;
+                    switch (i.itemtype) {
+                    case 'method':
+                        i = self.augmentData(i);
+                        i.paramsList = [];
+                        if (i.params && i.params.forEach) {
+                            i.params.forEach(function (p) {
+                                var name = p.name;
+                                if (p.optional) {
+                                    name = '[' + name + ((p.optdefault) ? '=' + p.optdefault : '') + ']';
+                                }
+                                i.paramsList.push(name);
+                            });
+                        }
+                        //i.methodDescription = self._parseCode(markdown(i.description || ''));
+                        i.methodDescription = self._parseCode(i.description);
+                        if (i.example && i.example.length) {
+                            if (i.example.forEach) {
+                                e = '';
+                                i.example.forEach(function (v) {
+                                    e += self._parseCode(self.markdown(v));
+                                });
+                                i.example = e;
+                            } else {
+                                i.example = self._parseCode(self.markdown(i.example));
+                            }
+                        }
+                        i.hasAccessType = i.access;
+                        i.hasParams = i.paramsList.length;
+                        if (i.paramsList.length) {
+                            i.paramsList = i.paramsList.join(', ');
+                        } else {
+                            i.paramsList = ' ';
+                        }
+                        i.returnType = ' ';
+                        if (i["return"]) {
+                            i.hasReturn = true;
+                            i.returnType = i["return"].type;
+                        }
+
+                        // If this item is provided by a module other
+                        // than the module that provided the original
+                        // class, add the original module name to the
+                        // item's `providedBy` property so we can
+                        // indicate the relationship.
+                        if ((i.submodule || i.module) !== (data.submodule || data.module)) {
+                            i.providedBy = (i.submodule || i.module);
+                        }
+
+                        opts.meta.methods.push(i);
+                        break;
+                    case 'property':
+                        i = self.augmentData(i);
+                        //i.propertyDescription = self._parseCode(markdown(i.description || ''));
+                        i.propertyDescription = self._parseCode(i.description);
+                        if (!i.type) {
+                            i.type = 'unknown';
+                        }
+                        if (i.final === '') {
+                            i.final = true;
+                        }
+						if (i.readonly === '') {
+							  i.readonly = true;
+						}
+                        if (i.example && i.example.length) {
+                            if (i.example.forEach) {
+                                e = '';
+                                i.example.forEach(function (v) {
+                                    e += self._parseCode(self.markdown(v));
+                                });
+                                i.example = e;
+                            } else {
+                                i.example = self._parseCode(self.markdown(i.example));
+                            }
+                        }
+
+                        // If this item is provided by a module other
+                        // than the module that provided the original
+                        // class, add the original module name to the
+                        // item's `providedBy` property so we can
+                        // indicate the relationship.
+                        if ((i.submodule || i.module) !== (data.submodule || data.module)) {
+                            i.providedBy = (i.submodule || i.module);
+                        }
+
+                        opts.meta.properties.push(i);
+                        break;
+
+                    case 'attribute': // fallthru
+                    case 'config':
+                        i = self.augmentData(i);
+                        //i.attrDescription = self._parseCode(markdown(i.description || ''));
+                        i.attrDescription = self._parseCode(i.description);
+
+                        if (i.itemtype === 'config') {
+                            i.config = true;
+                        } else {
+                            i.emit = self.options.attributesEmit;
+                        }
+                        if (i.readonly === '') {
+                            i.readonly = true;
+                        }
+
+                        if (i.example && i.example.length) {
+                            if (i.example.forEach) {
+                                e = '';
+                                i.example.forEach(function (v) {
+                                    e += self._parseCode(self.markdown(v));
+                                });
+                                i.example = e;
+                            } else {
+                                i.example = self._parseCode(self.markdown(i.example));
+                            }
+                        }
+
+                        // If this item is provided by a module other
+                        // than the module that provided the original
+                        // class, add the original module name to the
+                        // item's `providedBy` property so we can
+                        // indicate the relationship.
+                        if ((i.submodule || i.module) !== (data.submodule || data.module)) {
+                            i.providedBy = (i.submodule || i.module);
+                        }
+
+                        opts.meta.attrs.push(i);
+                        break;
+                    case 'event':
+                        i = self.augmentData(i);
+                        //i.eventDescription = self._parseCode(markdown(i.description || ''));
+                        i.eventDescription = self._parseCode(i.description);
+
+                        if (i.example && i.example.length) {
+                            if (i.example.forEach) {
+                                e = '';
+                                i.example.forEach(function (v) {
+                                    e += self._parseCode(self.markdown(v));
+                                });
+                                i.example = e;
+                            } else {
+                                i.example = self._parseCode(self.markdown(i.example));
+                            }
+                        }
+
+                        // If this item is provided by a module other
+                        // than the module that provided the original
+                        // class, add the original module name to the
+                        // item's `providedBy` property so we can
+                        // indicate the relationship.
+                        if ((i.submodule || i.module) !== (data.submodule || data.module)) {
+                            i.providedBy = (i.submodule || i.module);
+                        }
+
+                        opts.meta.events.push(i);
+                        break;
+                    }
+                });
+
+                opts.meta.attrs.sort(self.nameSort);
+                opts.meta.events.sort(self.nameSort);
+                opts.meta.methods.sort(self.nameSort);
+                opts.meta.properties.sort(self.nameSort);
+
+                if (!opts.meta.methods.length) {
+                    delete opts.meta.methods;
+                }
+                if (!opts.meta.properties.length) {
+                    delete opts.meta.properties;
+                }
+                if (!opts.meta.attrs.length) {
+                    delete opts.meta.attrs;
+                }
+                if (!opts.meta.events.length) {
+                    delete opts.meta.events;
+                }
+
+                var view = new Y.DocView(opts.meta);
+                var mainLayout = opts.layouts[layout];
+                self.render('{{>classes}}', view, mainLayout, opts.partials, stack.add(function (err, html) {
+                    self.files++;
+                    stack.html = html;
+                    stack.view = view;
+                    stack.opts = opts;
+                }));
+            });
+
+            stack.done(function () {
+                cb(stack.html, stack.view, stack.opts);
+            });
+        },
+        /**
+         * Generates the class files under "out"/classes/
+         * @method writeClasses
+         * @param {Callback} cb The callback to execute after it's completed
+         */
+        writeClasses: function (cb, layout) {
+            layout = layout || 'main';
+            var self = this,
+                stack = new Y.Parallel();
+            stack.html = [];
+            stack.view = [];
+
+            var counter = 0;
+            Object.keys(self.data.classes).forEach(function (k) {
+                if (!self.data.classes[k].external) {
+                    counter++;
+                }
+            });
+            Y.log('Rendering and writing ' + counter + ' class pages.', 'info', 'builder');
+            Y.each(self.data.classes, function (v) {
+                if (v.external) {
+                    return;
+                }
+                self.renderClass(stack.add(function (html, view) {
+                    stack.html.push(html);
+                    stack.view.push(view);
+                    if (self.options.dumpview) {
+                        Y.Files.writeFile(
+                            path.join(self.options.outdir, 'json', 'classes_' + v.name + '.json'),
+                            JSON.stringify(view),
+                            stack.add(noop)
+                        );
+                    }
+                    Y.Files.writeFile(path.join(self.options.outdir, 'classes', v.name + '.html'), html, stack.add(noop));
+                }), v, layout);
+            });
+            stack.done(function () {
+                Y.log('Finished writing class files', 'info', 'builder');
+                cb(stack.html, stack.view);
+            });
+        },
+        /**
+         * Sort method of array of objects with a property called __name__
+         * @method nameSort
+         * @param {Object} a First object to compare
+         * @param {Object} b Second object to compare
+         * @return {Number} 1, -1 or 0 for sorting.
+         */
+        nameSort: function (a, b) {
+            if (!a.name || !b.name) {
+                return 0;
+            }
+            var an = a.name.toLowerCase(),
+                bn = b.name.toLowerCase(),
+                ret = 0;
+
+            if (an < bn) {
+                ret = -1;
+            }
+            if (an > bn) {
+                ret = 1;
+            }
+            return ret;
+        },
+        /**
+         * Generates the syntax files under `"out"/files/`
+         * @method writeFiles
+         * @param {Callback} cb The callback to execute after it's completed
+         */
+        writeFiles: function (cb, layout) {
+            layout = layout || 'main';
+            var self = this,
+                stack = new Y.Parallel();
+            stack.html = [];
+            stack.view = [];
+
+            var counter = 0;
+            Object.keys(self.data.files).forEach(function (k) {
+                if (!self.data.files[k].external) {
+                    counter++;
+                }
+            });
+            Y.log('Rendering and writing ' + counter + ' source files.', 'info', 'builder');
+            Y.each(self.data.files, function (v) {
+                if (v.external) {
+                    return;
+                }
+                self.renderFile(stack.add(function (html, view, data) {
+                    if (!view || !data) {
+                        return;
+                    }
+                    stack.html.push(html);
+                    stack.view.push(view);
+                    if (self.options.dumpview) {
+                        Y.Files.writeFile(
+                            path.join(self.options.outdir, 'json', 'files_' + self.filterFileName(data.name) + '.json'),
+                            JSON.stringify(view),
+                            stack.add(noop)
+                        );
+                    }
+                    Y.Files.writeFile(
+                        path.join(self.options.outdir, 'files', self.filterFileName(data.name) + '.html'),
+                        html,
+                        stack.add(noop)
+                    );
+                }), v, layout);
+            });
+            stack.done(function () {
+                Y.log('Finished writing source files', 'info', 'builder');
+                cb(stack.html, stack.view);
+            });
+        },
+        /**
+         * Render the source file
+         * @method renderFile
+         * @param {Function} cb The callback fired when complete
+         * @param {String} cb.html The HTML to render this view
+         * @param {Object} cv.view The View Data
+         */
+        renderFile: function (cb, data, layout) {
+            var self = this;
+
+            Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function (err, opts) {
+                if (err) {
+                    console.log(err);
+                }
+                if (!data.name) {
+                    return;
+                }
+
+                opts.meta = Y.merge(opts.meta, data);
+
+                opts.meta.title = self.data.project.name;
+                opts.meta.moduleName = data.name;
+                opts.meta.projectRoot = '../';
+                opts.meta.projectAssets = '../assets';
+                opts.meta.projectLogo = self._resolveUrl(self.data.project.logo, opts);
+
+                opts = self.populateClasses(opts);
+                opts = self.populateModules(opts);
+                opts = self.populateFiles(opts);
+
+                opts.meta.fileName = data.name;
+                fs.readFile(opts.meta.fileName, Y.charset, Y.rbind(function (err, str, opts, data) {
+                    if (err) {
+                        Y.log(err, 'error', 'builder');
+                        cb(err);
+                        return;
+                    }
+
+                    if (typeof self.options.tabspace === 'string') {
+                        str = str.replace(/\t/g, self.options.tabspace);
+                    }
+
+                    opts.meta.fileData = str;
+                    var view = new Y.DocView(opts.meta, 'index');
+                    var mainLayout = opts.layouts[layout];
+                    self.render('{{>files}}', view, mainLayout, opts.partials, function (err, html) {
+                        self.files++;
+                        cb(html, view, data);
+                    });
+
+                }, this, opts, data));
+            });
+
+        },
+        /**
+         * Write the API meta data used for the AutoComplete widget
+         * @method writeAPIMeta
+         * @param {Callback} cb The callback to execute when complete
+         * @async
+         */
+        writeAPIMeta: function (cb) {
+            Y.log('Writing API Meta Data', 'info', 'builder');
+            var self = this;
+            this.renderAPIMeta(function (js) {
+                fs.writeFile(path.join(self.options.outdir, 'api.js'), js, Y.charset, cb);
+            });
+        },
+        /**
+         * Render the API meta and return the Javascript
+         * @method renderAPIMeta
+         * @param {Callback} cb The callback
+         * @async
+         */
+        renderAPIMeta: function (cb) {
+
+            var opts = {
+                meta: {}
+            };
+            opts = this.populateClasses(opts);
+            opts = this.populateModules(opts);
+
+            ['classes', 'modules'].forEach(function (id) {
+                opts.meta[id].forEach(function (v, k) {
+                    opts.meta[id][k] = v.name;
+                    if (v.submodules) {
+                        v.submodules.forEach(function (s) {
+                            opts.meta[id].push(s.displayName);
+                        });
+                    }
+                });
+                opts.meta[id].sort();
+            });
+
+            var apijs = 'YUI.add("yuidoc-meta", function(Y) {\n' +
+                '   Y.YUIDoc = { meta: ' + JSON.stringify(opts.meta, null, 4) + ' };\n' +
+                '});';
+
+            cb(apijs);
+        },
+        /**
+         * Normalizes a file path to a writable filename:
+         *
+         *    var path = 'lib/file.js';
+         *    returns 'lib_file.js';
+         *
+         * @method filterFileName
+         * @param {String} f The filename to normalize
+         * @return {String} The filtered file path
+         */
+        filterFileName: function (f) {
+            return f.replace(/[\/\\]/g, '_');
+        },
+        /**
+         * Compiles the templates from the meta-data provided by DocParser
+         * @method compile
+         * @param {Callback} cb The callback to execute after it's completed
+         */
+        compile: function (cb) {
+            var self = this;
+            var starttime = (new Date()).getTime();
+            Y.log('Compiling Templates', 'info', 'builder');
+
+            this.mixExternal(function () {
+                self.makeDirs(function () {
+                    Y.log('Copying Assets', 'info', 'builder');
+                    if (!Y.Files.isDirectory(path.join(self.options.outdir, 'assets'))) {
+                        fs.mkdirSync(path.join(self.options.outdir, 'assets'), 0777);
+                    }
+                    Y.Files.copyAssets([
+                            path.join(DEFAULT_THEME, 'assets'),
+                            path.join(themeDir, 'assets')
+                        ],
+                        path.join(self.options.outdir, 'assets'),
+                        false,
+                        function () {
+                            var cstack = new Y.Parallel();
+
+                            self.writeModules(cstack.add(function () {
+                                self.writeClasses(cstack.add(function () {
+                                    if (!self.options.nocode) {
+                                        self.writeFiles(cstack.add(noop));
+                                    }
+                                }));
+                            }));
+                            /*
+                        self.writeModules(cstack.add(noop));
+                        self.writeClasses(cstack.add(noop));
+                        if (!self.options.nocode) {
+                            self.writeFiles(cstack.add(noop));
+                        }
+                        */
+                            self.writeIndex(cstack.add(noop));
+                            self.writeAPIMeta(cstack.add(noop));
+
+                            cstack.done(function () {
+                                var endtime = (new Date()).getTime();
+                                var timer = ((endtime - starttime) / 1000) + ' seconds';
+                                Y.log('Finished writing ' + self.files + ' files in ' + timer, 'info', 'builder');
+                                if (cb) {
+                                    cb();
+                                }
+                            });
+                        });
+                });
+            });
+        }
+    };
+});
diff --git a/docs/PreloadJS_docs-0.4.1.zip b/docs/PreloadJS_docs-0.4.1.zip
deleted file mode 100644
index 502caf26..00000000
Binary files a/docs/PreloadJS_docs-0.4.1.zip and /dev/null differ
diff --git a/docs/PreloadJS_docs.zip b/docs/PreloadJS_docs.zip
new file mode 100644
index 00000000..79aeee86
Binary files /dev/null and b/docs/PreloadJS_docs.zip differ
diff --git a/docs/preloadjs_docs-NEXT.zip b/docs/preloadjs_docs-NEXT.zip
index 470017c1..e0ae1de2 100644
Binary files a/docs/preloadjs_docs-NEXT.zip and b/docs/preloadjs_docs-NEXT.zip differ
diff --git a/examples/CustomLoader.html b/examples/CustomLoader.html
new file mode 100644
index 00000000..bfb34363
--- /dev/null
+++ b/examples/CustomLoader.html
@@ -0,0 +1,92 @@
+
+
+
+	PreloadJS: Custom Loader
+
+	
+	
+	
+	
+
+
+
+	
+
+    
+
+    
+
+
+
diff --git a/examples/FontLoader.html b/examples/FontLoader.html
new file mode 100644
index 00000000..0c99579e
--- /dev/null
+++ b/examples/FontLoader.html
@@ -0,0 +1,140 @@
+
+
+
+	PreloadJS: Font Loading
+
+	
+	
+	
+	
+
+
+
+	
+
+    
+
+    
+    
+
+    
+
+    Load CSS Source |
+    Load CSS Source List |
+    Load Manual List |
+    Load CSS Tag |
+    Load Google Fonts
+
+    
+    
+ Hello World! +
+
+ Hello World (bold)! +
+
+ Hello World (google)! +
+
+ +
+ + + diff --git a/examples/MediaGrid.html b/examples/MediaGrid.html index c261a52e..d13644be 100644 --- a/examples/MediaGrid.html +++ b/examples/MediaGrid.html @@ -3,9 +3,12 @@ PreloadJS: Multimedia Preload Example - + + + + - - - -
- Click an item to load it. +
+

Example: Media Grid

+ +

PreloadJS can load a variety of media. In this example, click each + example to load its related item. + Once the item is loaded, it will display (image, svg), play (sound), + apply to the document (css), or display + an alert (script). Note that when loading images, sounds, css, scripts, + or svg locally, you need to ensure + that PreloadJS uses tag loading to avoid cross-origin errors. Other + media types will not load locally.

+
+ +
+ Click an item to load it. +
+ +
+
+
-
-
- -
- -
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+
+
- + + + - - - - - - - - - + + } + } + diff --git a/examples/PluginSample.html b/examples/PluginSample.html index 5ee6f845..187f430b 100644 --- a/examples/PluginSample.html +++ b/examples/PluginSample.html @@ -3,7 +3,10 @@ PreloadJS: Plugin Sample - + + + + - - -
- - - -
-
-
-
- -
+
+

Preload Queue

+ +

Click "load another" to add another image the the overall queue. As + images are added, the preload progress reflects + the overall loaded progress. Click "load all" to queue everything at + once. + Note that when loading images and sounds locally, you need to ensure + that PreloadJS uses tag loading to avoid + cross-origin errors.

+
+ +
+ + + + +
+ - -
+
+ +
+ + +
+
+
+ + + + + + + - - - - - - - - - - - - - + function loadAll() { + while (manifest.length > 0) { + loadAnother(); + } + } + + function loadAnother() { + // Get the next manifest item, and load it + var item = manifest.shift(); + preload.loadFile(item); + + // If we have no more items, disable the UI. + if (manifest.length == 0) { + $("#loadAnotherBtn").attr("disabled", "disabled"); + $("#loadAllBtn").attr("disabled", "disabled"); + $("#reloadBtn").css("display", "inline"); + } + + // Create a new loader display item + var div = $("#template").clone(); + div.attr("id", ""); // Wipe out the ID + div.addClass("box") + $("#container").append(div); + map[item] = div; // Store a reference to each item by its src + } + + // File complete handler + function handleFileLoad(event) { + var div = map[event.item.id]; + div.addClass("complete"); + + // Get a reference to the loaded image () + var img = event.result; + + // Resize it to fit inside the item + var r = img.width / img.height; + var ir = w / h + if (r > ir) { + img.width = w; + img.height = w / r; + } else { + img.height = h; + img.width = h; + } + div.append(img); // Add it to the DOM + } + + // File progress handler + function handleFileProgress(event) { + var div = map[event.item.id]; // Lookup the related item + div.children("DIV").width(event.progress * div.width()); // Set the width the progress. + } + + // Overall progress handler + function handleOverallProgress(event) { + $("#mainProgress > .progress").width(preload.progress * $("#mainProgress").width()); + } + + // An error happened on a file + function handleFileError(event) { + var div = map[event.item.id]; + div.addClass("error"); + } + - \ No newline at end of file + diff --git a/examples/SpriteSheet.html b/examples/SpriteSheet.html index 784bccd4..c2d48385 100644 --- a/examples/SpriteSheet.html +++ b/examples/SpriteSheet.html @@ -1,184 +1,155 @@ -EaselJS: Sprite Sheet Example - + EaselJS: Sprite Sheet Example + + + - -
- - - -
- -
- - - - - - - - - - - - - - - - +
+

Sprite Sheets

+ +

An example of the SpriteSheetLoader, which automatically parses loaded JSON, and will internally preload + associated images and instantiate a SpriteSheet instance before the complete event is fired.

+

Some browsers can not load images or access pixel data when running local files, and may throw a security + error or not work unless the content is running on a server.

+
+ +
+ +
+ + + + + + + + - \ No newline at end of file + diff --git a/examples/assets/MediaGridManifest.json b/examples/assets/MediaGridManifest.json deleted file mode 100644 index 793bf94a..00000000 --- a/examples/assets/MediaGridManifest.json +++ /dev/null @@ -1,15 +0,0 @@ -maps({ - "path": "assets/", - "manifest": [ - {"id":"Texas.jpg", "src":"Texas.jpg"}, - {"id":"bg.css", "src":"bg.css"}, - {"id":"alert1.js", "src":"alert1.js"}, - {"id":"grant.xml", "src":"grant.xml"}, - {"id":"gbot.svg", "src":"gbot.svg"}, - {"id":"grant.json", "src":"grant.json"}, - {"id":"font.css", "src":"font.css"}, - {"id":"Thunder.mp3|Thunder.ogg", "src":"Thunder.mp3|Thunder.ogg"}, - {"id":"http://gskinner.com/assets/createjs/mapsJSONP.json", "callback":"maps", "type":"jsonp", "src":"http://gskinner.com/assets/createjs/mapsJSONP.json"}, - {"id":"Autumn.png", "src":"Autumn.png"}, - ] -}); diff --git a/examples/assets/basepath_old/createjs/icon_128x128.png b/examples/assets/basepath_old/createjs/icon_128x128.png deleted file mode 100644 index a1df4864..00000000 Binary files a/examples/assets/basepath_old/createjs/icon_128x128.png and /dev/null differ diff --git a/examples/assets/basepath_old/createjs/icon_16x16.png b/examples/assets/basepath_old/createjs/icon_16x16.png deleted file mode 100644 index f0ce2941..00000000 Binary files a/examples/assets/basepath_old/createjs/icon_16x16.png and /dev/null differ diff --git a/examples/assets/basepath_old/createjs/icon_48x48.png b/examples/assets/basepath_old/createjs/icon_48x48.png deleted file mode 100644 index ffb54475..00000000 Binary files a/examples/assets/basepath_old/createjs/icon_48x48.png and /dev/null differ diff --git a/examples/assets/basepath_old/easeljs/icon_128x128.png b/examples/assets/basepath_old/easeljs/icon_128x128.png deleted file mode 100644 index e47eb38c..00000000 Binary files a/examples/assets/basepath_old/easeljs/icon_128x128.png and /dev/null differ diff --git a/examples/assets/basepath_old/easeljs/icon_16x16.png b/examples/assets/basepath_old/easeljs/icon_16x16.png deleted file mode 100644 index e4fb85a9..00000000 Binary files a/examples/assets/basepath_old/easeljs/icon_16x16.png and /dev/null differ diff --git a/examples/assets/basepath_old/easeljs/icon_48x48.png b/examples/assets/basepath_old/easeljs/icon_48x48.png deleted file mode 100644 index 9010b751..00000000 Binary files a/examples/assets/basepath_old/easeljs/icon_48x48.png and /dev/null differ diff --git a/examples/assets/basepath_old/manifest.json b/examples/assets/basepath_old/manifest.json deleted file mode 100644 index cc9862cf..00000000 --- a/examples/assets/basepath_old/manifest.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "manifest": [ - "icon_16x16.png", - "icon_48x48.png", - "icon_128x128.png" - ] -} \ No newline at end of file diff --git a/examples/assets/basepath_old/manifest_basepath.json b/examples/assets/basepath_old/manifest_basepath.json deleted file mode 100644 index 8ff74c54..00000000 --- a/examples/assets/basepath_old/manifest_basepath.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "basePath": "assets/basepath/easeljs/", - "manifest": [ - "icon_16x16.png", - "icon_48x48.png", - "icon_128x128.png" - ] -} \ No newline at end of file diff --git a/examples/assets/basepath_old/preloadjs/icon_128x128.png b/examples/assets/basepath_old/preloadjs/icon_128x128.png deleted file mode 100644 index e0753e6b..00000000 Binary files a/examples/assets/basepath_old/preloadjs/icon_128x128.png and /dev/null differ diff --git a/examples/assets/basepath_old/preloadjs/icon_16x16.png b/examples/assets/basepath_old/preloadjs/icon_16x16.png deleted file mode 100644 index 14fcb351..00000000 Binary files a/examples/assets/basepath_old/preloadjs/icon_16x16.png and /dev/null differ diff --git a/examples/assets/basepath_old/preloadjs/icon_48x48.png b/examples/assets/basepath_old/preloadjs/icon_48x48.png deleted file mode 100644 index 10082426..00000000 Binary files a/examples/assets/basepath_old/preloadjs/icon_48x48.png and /dev/null differ diff --git a/examples/assets/easeljs-NEXT.min.js b/examples/assets/easeljs-NEXT.min.js deleted file mode 100644 index eb8288bc..00000000 --- a/examples/assets/easeljs-NEXT.min.js +++ /dev/null @@ -1,14 +0,0 @@ -/*! -* @license EaselJS -* Visit http://createjs.com/ for documentation, updates and examples. -* -* Copyright (c) 2011-2013 gskinner.com, inc. -* -* Distributed under the terms of the MIT license. -* http://www.opensource.org/licenses/mit-license.html -* -* This notice shall be included in all copies or substantial portions of the Software. -*/ -this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c){this.initialize(a,b,c)},b=a.prototype;b.type=null,b.target=null,b.currentTarget=null,b.eventPhase=0,b.bubbles=!1,b.cancelable=!1,b.timeStamp=0,b.defaultPrevented=!1,b.propagationStopped=!1,b.immediatePropagationStopped=!1,b.removed=!1,b.initialize=function(a,b,c){this.type=a,this.bubbles=b,this.cancelable=c,this.timeStamp=(new Date).getTime()},b.preventDefault=function(){this.defaultPrevented=!0},b.stopPropagation=function(){this.propagationStopped=!0},b.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},b.remove=function(){this.removed=!0},b.clone=function(){return new a(this.type,this.bubbles,this.cancelable)},b.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){},b=a.prototype;a.initialize=function(a){a.addEventListener=b.addEventListener,a.on=b.on,a.removeEventListener=a.off=b.removeEventListener,a.removeAllEventListeners=b.removeAllEventListeners,a.hasEventListener=b.hasEventListener,a.dispatchEvent=b.dispatchEvent,a._dispatchEvent=b._dispatchEvent,a.willTrigger=b.willTrigger},b._listeners=null,b._captureListeners=null,b.initialize=function(){},b.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},b.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},b.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},b.off=b.removeEventListener,b.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},b.dispatchEvent=function(a,b){if("string"==typeof a){var c=this._listeners;if(!c||!c[a])return!1;a=new createjs.Event(a)}if(a.target=b||this,a.bubbles&&this.parent){for(var d=this,e=[d];d.parent;)e.push(d=d.parent);var f,g=e.length;for(f=g-1;f>=0&&!a.propagationStopped;f--)e[f]._dispatchEvent(a,1+(0==f));for(f=1;g>f&&!a.propagationStopped;f++)e[f]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return a.defaultPrevented},b.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},b.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},b.toString=function(){return"[EventDispatcher]"},b._dispatchEvent=function(a,b){var c,d=1==b?this._captureListeners:this._listeners;if(a&&d){var e=d[a.type];if(!e||!(c=e.length))return;a.currentTarget=this,a.eventPhase=b,a.removed=!1,e=e.slice();for(var f=0;c>f&&!a.immediatePropagationStopped;f++){var g=e[f];g.handleEvent?g.handleEvent(a):g(a),a.removed&&(this.off(a.type,g,1==b),a.removed=!1)}}},createjs.EventDispatcher=a}(),this.createjs=this.createjs||{},function(){"use strict";createjs.indexOf=function(a,b){for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1}}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){throw"UID cannot be instantiated"};a._nextID=0,a.get=function(){return a._nextID++},createjs.UID=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){throw"Ticker cannot be instantiated."};a.RAF_SYNCHED="synched",a.RAF="raf",a.TIMEOUT="timeout",a.useRAF=!1,a.timingMode=null,a.maxDelta=0,a.removeEventListener=null,a.removeAllEventListeners=null,a.dispatchEvent=null,a.hasEventListener=null,a._listeners=null,createjs.EventDispatcher.initialize(a),a._addEventListener=a.addEventListener,a.addEventListener=function(){return!a._inited&&a.init(),a._addEventListener.apply(a,arguments)},a._paused=!1,a._inited=!1,a._startTime=0,a._pausedTime=0,a._ticks=0,a._pausedTicks=0,a._interval=50,a._lastTime=0,a._times=null,a._tickTimes=null,a._timerId=null,a._raf=!0,a.init=function(){a._inited||(a._inited=!0,a._times=[],a._tickTimes=[],a._startTime=a._getTime(),a._times.push(a._lastTime=0),a.setInterval(a._interval))},a.reset=function(){if(a._raf){var b=window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame;b&&b(a._timerId)}else clearTimeout(a._timerId);a.removeAllEventListeners("tick")},a.setInterval=function(b){a._interval=b,a._inited&&a._setupTick()},a.getInterval=function(){return a._interval},a.setFPS=function(b){a.setInterval(1e3/b)},a.getFPS=function(){return 1e3/a._interval},a.getMeasuredTickTime=function(b){var c=0,d=a._tickTimes;if(d.length<1)return-1;b=Math.min(d.length,b||0|a.getFPS());for(var e=0;b>e;e++)c+=d[e];return c/b},a.getMeasuredFPS=function(b){var c=a._times;return c.length<2?-1:(b=Math.min(c.length-1,b||0|a.getFPS()),1e3/((c[0]-c[b])/b))},a.setPaused=function(b){a._paused=b},a.getPaused=function(){return a._paused},a.getTime=function(b){return a._getTime()-a._startTime-(b?a._pausedTime:0)},a.getEventTime=function(b){return(a._lastTime||a._startTime)-(b?a._pausedTime:0)},a.getTicks=function(b){return a._ticks-(b?a._pausedTicks:0)},a._handleSynch=function(){var b=a._getTime()-a._startTime;a._timerId=null,a._setupTick(),b-a._lastTime>=.97*(a._interval-1)&&a._tick()},a._handleRAF=function(){a._timerId=null,a._setupTick(),a._tick()},a._handleTimeout=function(){a._timerId=null,a._setupTick(),a._tick()},a._setupTick=function(){if(null==a._timerId){var b=a.timingMode||a.useRAF&&a.RAF_SYNCHED;if(b==a.RAF_SYNCHED||b==a.RAF){var c=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame;if(c)return a._timerId=c(b==a.RAF?a._handleRAF:a._handleSynch),a._raf=!0,void 0}a._raf=!1,a._timerId=setTimeout(a._handleTimeout,a._interval)}},a._tick=function(){var b=a._getTime()-a._startTime,c=b-a._lastTime,d=a._paused;if(a._ticks++,d&&(a._pausedTicks++,a._pausedTime+=c),a._lastTime=b,a.hasEventListener("tick")){var e=new createjs.Event("tick"),f=a.maxDelta;e.delta=f&&c>f?f:c,e.paused=d,e.time=b,e.runTime=b-a._pausedTime,a.dispatchEvent(e)}for(a._tickTimes.unshift(a._getTime()-b);a._tickTimes.length>100;)a._tickTimes.pop();for(a._times.unshift(b);a._times.length>100;)a._times.pop()};var b=window.performance&&(performance.now||performance.mozNow||performance.msNow||performance.oNow||performance.webkitNow);a._getTime=function(){return b&&b.call(performance)||(new Date).getTime()},createjs.Ticker=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c,d,e,f,g,h,i,j){this.initialize(a,b,c,d,e,f,g,h,i,j)},b=a.prototype=new createjs.Event;b.stageX=0,b.stageY=0,b.rawX=0,b.rawY=0,b.nativeEvent=null,b.pointerID=0,b.primary=!1,b.addEventListener=null,b.removeEventListener=null,b.removeAllEventListeners=null,b.dispatchEvent=null,b.hasEventListener=null,b._listeners=null,createjs.EventDispatcher.initialize(b),b._get_localX=function(){return this.currentTarget.globalToLocal(this.rawX,this.rawY).x},b._get_localY=function(){return this.currentTarget.globalToLocal(this.rawX,this.rawY).y};try{Object.defineProperties(b,{localX:{get:b._get_localX},localY:{get:b._get_localY}})}catch(c){}b.Event_initialize=b.initialize,b.initialize=function(a,b,c,d,e,f,g,h,i,j){this.Event_initialize(a,b,c),this.stageX=d,this.stageY=e,this.nativeEvent=f,this.pointerID=g,this.primary=h,this.rawX=null==i?d:i,this.rawY=null==j?e:j},b.clone=function(){return new a(this.type,this.bubbles,this.cancelable,this.stageX,this.stageY,this.target,this.nativeEvent,this.pointerID,this.primary,this.rawX,this.rawY)},b.toString=function(){return"[MouseEvent (type="+this.type+" stageX="+this.stageX+" stageY="+this.stageY+")]"},createjs.MouseEvent=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c,d,e,f){this.initialize(a,b,c,d,e,f)},b=a.prototype;a.identity=null,a.DEG_TO_RAD=Math.PI/180,b.a=1,b.b=0,b.c=0,b.d=1,b.tx=0,b.ty=0,b.alpha=1,b.shadow=null,b.compositeOperation=null,b.initialize=function(a,b,c,d,e,f){return this.a=null==a?1:a,this.b=b||0,this.c=c||0,this.d=null==d?1:d,this.tx=e||0,this.ty=f||0,this},b.prepend=function(a,b,c,d,e,f){var g=this.tx;if(1!=a||0!=b||0!=c||1!=d){var h=this.a,i=this.c;this.a=h*a+this.b*c,this.b=h*b+this.b*d,this.c=i*a+this.d*c,this.d=i*b+this.d*d}return this.tx=g*a+this.ty*c+e,this.ty=g*b+this.ty*d+f,this},b.append=function(a,b,c,d,e,f){var g=this.a,h=this.b,i=this.c,j=this.d;return this.a=a*g+b*i,this.b=a*h+b*j,this.c=c*g+d*i,this.d=c*h+d*j,this.tx=e*g+f*i+this.tx,this.ty=e*h+f*j+this.ty,this},b.prependMatrix=function(a){return this.prepend(a.a,a.b,a.c,a.d,a.tx,a.ty),this.prependProperties(a.alpha,a.shadow,a.compositeOperation),this},b.appendMatrix=function(a){return this.append(a.a,a.b,a.c,a.d,a.tx,a.ty),this.appendProperties(a.alpha,a.shadow,a.compositeOperation),this},b.prependTransform=function(b,c,d,e,f,g,h,i,j){if(f%360)var k=f*a.DEG_TO_RAD,l=Math.cos(k),m=Math.sin(k);else l=1,m=0;return(i||j)&&(this.tx-=i,this.ty-=j),g||h?(g*=a.DEG_TO_RAD,h*=a.DEG_TO_RAD,this.prepend(l*d,m*d,-m*e,l*e,0,0),this.prepend(Math.cos(h),Math.sin(h),-Math.sin(g),Math.cos(g),b,c)):this.prepend(l*d,m*d,-m*e,l*e,b,c),this},b.appendTransform=function(b,c,d,e,f,g,h,i,j){if(f%360)var k=f*a.DEG_TO_RAD,l=Math.cos(k),m=Math.sin(k);else l=1,m=0;return g||h?(g*=a.DEG_TO_RAD,h*=a.DEG_TO_RAD,this.append(Math.cos(h),Math.sin(h),-Math.sin(g),Math.cos(g),b,c),this.append(l*d,m*d,-m*e,l*e,0,0)):this.append(l*d,m*d,-m*e,l*e,b,c),(i||j)&&(this.tx-=i*this.a+j*this.c,this.ty-=i*this.b+j*this.d),this},b.rotate=function(a){var b=Math.cos(a),c=Math.sin(a),d=this.a,e=this.c,f=this.tx;return this.a=d*b-this.b*c,this.b=d*c+this.b*b,this.c=e*b-this.d*c,this.d=e*c+this.d*b,this.tx=f*b-this.ty*c,this.ty=f*c+this.ty*b,this},b.skew=function(b,c){return b*=a.DEG_TO_RAD,c*=a.DEG_TO_RAD,this.append(Math.cos(c),Math.sin(c),-Math.sin(b),Math.cos(b),0,0),this},b.scale=function(a,b){return this.a*=a,this.d*=b,this.c*=a,this.b*=b,this.tx*=a,this.ty*=b,this},b.translate=function(a,b){return this.tx+=a,this.ty+=b,this},b.identity=function(){return this.alpha=this.a=this.d=1,this.b=this.c=this.tx=this.ty=0,this.shadow=this.compositeOperation=null,this},b.invert=function(){var a=this.a,b=this.b,c=this.c,d=this.d,e=this.tx,f=a*d-b*c;return this.a=d/f,this.b=-b/f,this.c=-c/f,this.d=a/f,this.tx=(c*this.ty-d*e)/f,this.ty=-(a*this.ty-b*e)/f,this},b.isIdentity=function(){return 0==this.tx&&0==this.ty&&1==this.a&&0==this.b&&0==this.c&&1==this.d},b.transformPoint=function(a,b,c){return c=c||{},c.x=a*this.a+b*this.c+this.tx,c.y=a*this.b+b*this.d+this.ty,c},b.decompose=function(b){null==b&&(b={}),b.x=this.tx,b.y=this.ty,b.scaleX=Math.sqrt(this.a*this.a+this.b*this.b),b.scaleY=Math.sqrt(this.c*this.c+this.d*this.d);var c=Math.atan2(-this.c,this.d),d=Math.atan2(this.b,this.a);return c==d?(b.rotation=d/a.DEG_TO_RAD,this.a<0&&this.d>=0&&(b.rotation+=b.rotation<=0?180:-180),b.skewX=b.skewY=0):(b.skewX=c/a.DEG_TO_RAD,b.skewY=d/a.DEG_TO_RAD),b},b.reinitialize=function(a,b,c,d,e,f,g,h,i){return this.initialize(a,b,c,d,e,f),this.alpha=null==g?1:g,this.shadow=h,this.compositeOperation=i,this},b.copy=function(a){return this.reinitialize(a.a,a.b,a.c,a.d,a.tx,a.ty,a.alpha,a.shadow,a.compositeOperation)},b.appendProperties=function(a,b,c){return this.alpha*=a,this.shadow=b||this.shadow,this.compositeOperation=c||this.compositeOperation,this},b.prependProperties=function(a,b,c){return this.alpha*=a,this.shadow=this.shadow||b,this.compositeOperation=this.compositeOperation||c,this},b.clone=function(){return(new a).copy(this)},b.toString=function(){return"[Matrix2D (a="+this.a+" b="+this.b+" c="+this.c+" d="+this.d+" tx="+this.tx+" ty="+this.ty+")]"},a.identity=new a,createjs.Matrix2D=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b){this.initialize(a,b)},b=a.prototype;b.x=0,b.y=0,b.initialize=function(a,b){return this.x=null==a?0:a,this.y=null==b?0:b,this},b.copy=function(a){return this.initialize(a.x,a.y)},b.clone=function(){return new a(this.x,this.y)},b.toString=function(){return"[Point (x="+this.x+" y="+this.y+")]"},createjs.Point=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c,d){this.initialize(a,b,c,d)},b=a.prototype;b.x=0,b.y=0,b.width=0,b.height=0,b.initialize=function(a,b,c,d){return this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0,this},b.copy=function(a){return this.initialize(a.x,a.y,a.width,a.height)},b.clone=function(){return new a(this.x,this.y,this.width,this.height)},b.toString=function(){return"[Rectangle (x="+this.x+" y="+this.y+" width="+this.width+" height="+this.height+")]"},createjs.Rectangle=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c,d,e,f,g){this.initialize(a,b,c,d,e,f,g)},b=a.prototype;b.target=null,b.overLabel=null,b.outLabel=null,b.downLabel=null,b.play=!1,b._isPressed=!1,b._isOver=!1,b.initialize=function(a,b,c,d,e,f,g){a.addEventListener&&(this.target=a,a.cursor="pointer",this.overLabel=null==c?"over":c,this.outLabel=null==b?"out":b,this.downLabel=null==d?"down":d,this.play=e,this.setEnabled(!0),this.handleEvent({}),f&&(g&&(f.actionsEnabled=!1,f.gotoAndStop&&f.gotoAndStop(g)),a.hitArea=f))},b.setEnabled=function(a){var b=this.target;a?(b.addEventListener("rollover",this),b.addEventListener("rollout",this),b.addEventListener("mousedown",this),b.addEventListener("pressup",this)):(b.removeEventListener("rollover",this),b.removeEventListener("rollout",this),b.removeEventListener("mousedown",this),b.removeEventListener("pressup",this))},b.toString=function(){return"[ButtonHelper]"},b.handleEvent=function(a){var b,c=this.target,d=a.type;"mousedown"==d?(this._isPressed=!0,b=this.downLabel):"pressup"==d?(this._isPressed=!1,b=this._isOver?this.overLabel:this.outLabel):"rollover"==d?(this._isOver=!0,b=this._isPressed?this.downLabel:this.overLabel):(this._isOver=!1,b=this._isPressed?this.overLabel:this.outLabel),this.play?c.gotoAndPlay&&c.gotoAndPlay(b):c.gotoAndStop&&c.gotoAndStop(b)},createjs.ButtonHelper=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c,d){this.initialize(a,b,c,d)},b=a.prototype;a.identity=null,b.color=null,b.offsetX=0,b.offsetY=0,b.blur=0,b.initialize=function(a,b,c,d){this.color=a,this.offsetX=b,this.offsetY=c,this.blur=d},b.toString=function(){return"[Shadow]"},b.clone=function(){return new a(this.color,this.offsetX,this.offsetY,this.blur)},a.identity=new a("transparent",0,0,0),createjs.Shadow=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a){this.initialize(a)},b=a.prototype=new createjs.EventDispatcher;b.complete=!0,b.framerate=0,b._animations=null,b._frames=null,b._images=null,b._data=null,b._loadCount=0,b._frameHeight=0,b._frameWidth=0,b._numFrames=0,b._regX=0,b._regY=0,b.initialize=function(a){var b,c,d,e;if(null!=a){if(this.framerate=a.framerate||0,a.images&&(c=a.images.length)>0)for(e=this._images=[],b=0;c>b;b++){var f=a.images[b];if("string"==typeof f){var g=f;f=document.createElement("img"),f.src=g}e.push(f),f.getContext||f.complete||(this._loadCount++,this.complete=!1,function(a){f.onload=function(){a._handleImageLoad()}}(this))}if(null==a.frames);else if(a.frames instanceof Array)for(this._frames=[],e=a.frames,b=0,c=e.length;c>b;b++){var h=e[b];this._frames.push({image:this._images[h[4]?h[4]:0],rect:new createjs.Rectangle(h[0],h[1],h[2],h[3]),regX:h[5]||0,regY:h[6]||0})}else d=a.frames,this._frameWidth=d.width,this._frameHeight=d.height,this._regX=d.regX||0,this._regY=d.regY||0,this._numFrames=d.count,0==this._loadCount&&this._calculateFrames();if(this._animations=[],null!=(d=a.animations)){this._data={};var i;for(i in d){var j={name:i},k=d[i];if("number"==typeof k)e=j.frames=[k];else if(k instanceof Array)if(1==k.length)j.frames=[k[0]];else for(j.speed=k[3],j.next=k[2],e=j.frames=[],b=k[0];b<=k[1];b++)e.push(b);else{j.speed=k.speed,j.next=k.next;var l=k.frames;e=j.frames="number"==typeof l?[l]:l.slice(0)}(j.next===!0||void 0===j.next)&&(j.next=i),(j.next===!1||e.length<2&&j.next==i)&&(j.next=null),j.speed||(j.speed=1),this._animations.push(i),this._data[i]=j}}}},b.getNumFrames=function(a){if(null==a)return this._frames?this._frames.length:this._numFrames;var b=this._data[a];return null==b?0:b.frames.length},b.getAnimations=function(){return this._animations.slice(0)},b.getAnimation=function(a){return this._data[a]},b.getFrame=function(a){var b;return this._frames&&(b=this._frames[a])?b:null},b.getFrameBounds=function(a,b){var c=this.getFrame(a);return c?(b||new createjs.Rectangle).initialize(-c.regX,-c.regY,c.rect.width,c.rect.height):null},b.toString=function(){return"[SpriteSheet]"},b.clone=function(){var b=new a;return b.complete=this.complete,b._animations=this._animations,b._frames=this._frames,b._images=this._images,b._data=this._data,b._frameHeight=this._frameHeight,b._frameWidth=this._frameWidth,b._numFrames=this._numFrames,b._loadCount=this._loadCount,b},b._handleImageLoad=function(){0==--this._loadCount&&(this._calculateFrames(),this.complete=!0,this.dispatchEvent("complete"))},b._calculateFrames=function(){if(!this._frames&&0!=this._frameWidth){this._frames=[];for(var a=0,b=this._frameWidth,c=this._frameHeight,d=0,e=this._images;d0?Math.min(this._numFrames-a,g*h):g*h,j=0;i>j;j++)this._frames.push({image:f,rect:new createjs.Rectangle(j%g*b,(0|j/g)*c,b,c),regX:this._regX,regY:this._regY});a+=i}this._numFrames=a}},createjs.SpriteSheet=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b,c){this.f=a,this.params=b,this.path=null==c?!0:c}a.prototype.exec=function(a){this.f.apply(a,this.params)};var b=function(){this.initialize()},c=b.prototype;b.getRGB=function(a,b,c,d){return null!=a&&null==c&&(d=b,c=255&a,b=255&a>>8,a=255&a>>16),null==d?"rgb("+a+","+b+","+c+")":"rgba("+a+","+b+","+c+","+d+")"},b.getHSL=function(a,b,c,d){return null==d?"hsl("+a%360+","+b+"%,"+c+"%)":"hsla("+a%360+","+b+"%,"+c+"%,"+d+")"},b.Command=a,b.BASE_64={A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8,J:9,K:10,L:11,M:12,N:13,O:14,P:15,Q:16,R:17,S:18,T:19,U:20,V:21,W:22,X:23,Y:24,Z:25,a:26,b:27,c:28,d:29,e:30,f:31,g:32,h:33,i:34,j:35,k:36,l:37,m:38,n:39,o:40,p:41,q:42,r:43,s:44,t:45,u:46,v:47,w:48,x:49,y:50,z:51,0:52,1:53,2:54,3:55,4:56,5:57,6:58,7:59,8:60,9:61,"+":62,"/":63},b.STROKE_CAPS_MAP=["butt","round","square"],b.STROKE_JOINTS_MAP=["miter","round","bevel"];var d=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");if(d.getContext){var e=b._ctx=d.getContext("2d");b.beginCmd=new a(e.beginPath,[],!1),b.fillCmd=new a(e.fill,[],!1),b.strokeCmd=new a(e.stroke,[],!1),d.width=d.height=1}c._strokeInstructions=null,c._strokeStyleInstructions=null,c._strokeIgnoreScale=!1,c._fillInstructions=null,c._fillMatrix=null,c._instructions=null,c._oldInstructions=null,c._activeInstructions=null,c._active=!1,c._dirty=!1,c.initialize=function(){this.clear(),this._ctx=b._ctx},c.isEmpty=function(){return!(this._instructions.length||this._oldInstructions.length||this._activeInstructions.length)},c.draw=function(a){this._dirty&&this._updateInstructions();for(var b=this._instructions,c=0,d=b.length;d>c;c++)b[c].exec(a)},c.drawAsPath=function(a){this._dirty&&this._updateInstructions();for(var b,c=this._instructions,d=0,e=c.length;e>d;d++)((b=c[d]).path||0==d)&&b.exec(a)},c.moveTo=function(b,c){return this._activeInstructions.push(new a(this._ctx.moveTo,[b,c])),this},c.lineTo=function(b,c){return this._dirty=this._active=!0,this._activeInstructions.push(new a(this._ctx.lineTo,[b,c])),this},c.arcTo=function(b,c,d,e,f){return this._dirty=this._active=!0,this._activeInstructions.push(new a(this._ctx.arcTo,[b,c,d,e,f])),this},c.arc=function(b,c,d,e,f,g){return this._dirty=this._active=!0,null==g&&(g=!1),this._activeInstructions.push(new a(this._ctx.arc,[b,c,d,e,f,g])),this},c.quadraticCurveTo=function(b,c,d,e){return this._dirty=this._active=!0,this._activeInstructions.push(new a(this._ctx.quadraticCurveTo,[b,c,d,e])),this},c.bezierCurveTo=function(b,c,d,e,f,g){return this._dirty=this._active=!0,this._activeInstructions.push(new a(this._ctx.bezierCurveTo,[b,c,d,e,f,g])),this},c.rect=function(b,c,d,e){return this._dirty=this._active=!0,this._activeInstructions.push(new a(this._ctx.rect,[b,c,d,e])),this},c.closePath=function(){return this._active&&(this._dirty=!0,this._activeInstructions.push(new a(this._ctx.closePath,[]))),this},c.clear=function(){return this._instructions=[],this._oldInstructions=[],this._activeInstructions=[],this._strokeStyleInstructions=this._strokeInstructions=this._fillInstructions=this._fillMatrix=null,this._active=this._dirty=this._strokeIgnoreScale=!1,this},c.beginFill=function(b){return this._active&&this._newPath(),this._fillInstructions=b?[new a(this._setProp,["fillStyle",b],!1)]:null,this._fillMatrix=null,this},c.beginLinearGradientFill=function(b,c,d,e,f,g){this._active&&this._newPath();for(var h=this._ctx.createLinearGradient(d,e,f,g),i=0,j=b.length;j>i;i++)h.addColorStop(c[i],b[i]);return this._fillInstructions=[new a(this._setProp,["fillStyle",h],!1)],this._fillMatrix=null,this},c.beginRadialGradientFill=function(b,c,d,e,f,g,h,i){this._active&&this._newPath();for(var j=this._ctx.createRadialGradient(d,e,f,g,h,i),k=0,l=b.length;l>k;k++)j.addColorStop(c[k],b[k]);return this._fillInstructions=[new a(this._setProp,["fillStyle",j],!1)],this._fillMatrix=null,this},c.beginBitmapFill=function(b,c,d){this._active&&this._newPath(),c=c||"";var e=this._ctx.createPattern(b,c);return this._fillInstructions=[new a(this._setProp,["fillStyle",e],!1)],this._fillMatrix=d?[d.a,d.b,d.c,d.d,d.tx,d.ty]:null,this},c.endFill=function(){return this.beginFill()},c.setStrokeStyle=function(c,d,e,f,g){return this._active&&this._newPath(),this._strokeStyleInstructions=[new a(this._setProp,["lineWidth",null==c?"1":c],!1),new a(this._setProp,["lineCap",null==d?"butt":isNaN(d)?d:b.STROKE_CAPS_MAP[d]],!1),new a(this._setProp,["lineJoin",null==e?"miter":isNaN(e)?e:b.STROKE_JOINTS_MAP[e]],!1),new a(this._setProp,["miterLimit",null==f?"10":f],!1)],this._strokeIgnoreScale=g,this},c.beginStroke=function(b){return this._active&&this._newPath(),this._strokeInstructions=b?[new a(this._setProp,["strokeStyle",b],!1)]:null,this},c.beginLinearGradientStroke=function(b,c,d,e,f,g){this._active&&this._newPath();for(var h=this._ctx.createLinearGradient(d,e,f,g),i=0,j=b.length;j>i;i++)h.addColorStop(c[i],b[i]);return this._strokeInstructions=[new a(this._setProp,["strokeStyle",h],!1)],this},c.beginRadialGradientStroke=function(b,c,d,e,f,g,h,i){this._active&&this._newPath();for(var j=this._ctx.createRadialGradient(d,e,f,g,h,i),k=0,l=b.length;l>k;k++)j.addColorStop(c[k],b[k]);return this._strokeInstructions=[new a(this._setProp,["strokeStyle",j],!1)],this},c.beginBitmapStroke=function(b,c){this._active&&this._newPath(),c=c||"";var d=this._ctx.createPattern(b,c);return this._strokeInstructions=[new a(this._setProp,["strokeStyle",d],!1)],this},c.endStroke=function(){return this.beginStroke(),this},c.curveTo=c.quadraticCurveTo,c.drawRect=c.rect,c.drawRoundRect=function(a,b,c,d,e){return this.drawRoundRectComplex(a,b,c,d,e,e,e,e),this},c.drawRoundRectComplex=function(b,c,d,e,f,g,h,i){var j=(e>d?d:e)/2,k=0,l=0,m=0,n=0;0>f&&(f*=k=-1),f>j&&(f=j),0>g&&(g*=l=-1),g>j&&(g=j),0>h&&(h*=m=-1),h>j&&(h=j),0>i&&(i*=n=-1),i>j&&(i=j),this._dirty=this._active=!0;var o=this._ctx.arcTo,p=this._ctx.lineTo;return this._activeInstructions.push(new a(this._ctx.moveTo,[b+d-g,c]),new a(o,[b+d+g*l,c-g*l,b+d,c+g,g]),new a(p,[b+d,c+e-h]),new a(o,[b+d+h*m,c+e+h*m,b+d-h,c+e,h]),new a(p,[b+i,c+e]),new a(o,[b-i*n,c+e+i*n,b,c+e-i,i]),new a(p,[b,c+f]),new a(o,[b-f*k,c-f*k,b+f,c,f]),new a(this._ctx.closePath)),this},c.drawCircle=function(a,b,c){return this.arc(a,b,c,0,2*Math.PI),this},c.drawEllipse=function(b,c,d,e){this._dirty=this._active=!0;var f=.5522848,g=d/2*f,h=e/2*f,i=b+d,j=c+e,k=b+d/2,l=c+e/2;return this._activeInstructions.push(new a(this._ctx.moveTo,[b,l]),new a(this._ctx.bezierCurveTo,[b,l-h,k-g,c,k,c]),new a(this._ctx.bezierCurveTo,[k+g,c,i,l-h,i,l]),new a(this._ctx.bezierCurveTo,[i,l+h,k+g,j,k,j]),new a(this._ctx.bezierCurveTo,[k-g,j,b,l+h,b,l])),this},c.inject=function(b,c){return this._dirty=this._active=!0,this._activeInstructions.push(new a(b,[c])),this},c.drawPolyStar=function(b,c,d,e,f,g){this._dirty=this._active=!0,null==f&&(f=0),f=1-f,null==g?g=0:g/=180/Math.PI;var h=Math.PI/e;this._activeInstructions.push(new a(this._ctx.moveTo,[b+Math.cos(g)*d,c+Math.sin(g)*d]));for(var i=0;e>i;i++)g+=h,1!=f&&this._activeInstructions.push(new a(this._ctx.lineTo,[b+Math.cos(g)*d*f,c+Math.sin(g)*d*f])),g+=h,this._activeInstructions.push(new a(this._ctx.lineTo,[b+Math.cos(g)*d,c+Math.sin(g)*d]));return this},c.decodePath=function(a){for(var c=[this.moveTo,this.lineTo,this.quadraticCurveTo,this.bezierCurveTo,this.closePath],d=[2,2,4,6,0],e=0,f=a.length,g=[],h=0,i=0,j=b.BASE_64;f>e;){var k=a.charAt(e),l=j[k],m=l>>3,n=c[m];if(!n||3&l)throw"bad path data (@"+e+"): "+k;var o=d[m];m||(h=i=0),g.length=0,e++;for(var p=(1&l>>2)+2,q=0;o>q;q++){var r=j[a.charAt(e)],s=r>>5?-1:1;r=(31&r)<<6|j[a.charAt(e+1)],3==p&&(r=r<<6|j[a.charAt(e+2)]),r=s*r/10,q%2?h=r+=h:i=r+=i,g[q]=r,e+=p}n.apply(this,g)}return this},c.clone=function(){var a=new b;return a._instructions=this._instructions.slice(),a._activeInstructions=this._activeInstructions.slice(),a._oldInstructions=this._oldInstructions.slice(),this._fillInstructions&&(a._fillInstructions=this._fillInstructions.slice()),this._strokeInstructions&&(a._strokeInstructions=this._strokeInstructions.slice()),this._strokeStyleInstructions&&(a._strokeStyleInstructions=this._strokeStyleInstructions.slice()),a._active=this._active,a._dirty=this._dirty,a._fillMatrix=this._fillMatrix,a._strokeIgnoreScale=this._strokeIgnoreScale,a},c.toString=function(){return"[Graphics]"},c.mt=c.moveTo,c.lt=c.lineTo,c.at=c.arcTo,c.bt=c.bezierCurveTo,c.qt=c.quadraticCurveTo,c.a=c.arc,c.r=c.rect,c.cp=c.closePath,c.c=c.clear,c.f=c.beginFill,c.lf=c.beginLinearGradientFill,c.rf=c.beginRadialGradientFill,c.bf=c.beginBitmapFill,c.ef=c.endFill,c.ss=c.setStrokeStyle,c.s=c.beginStroke,c.ls=c.beginLinearGradientStroke,c.rs=c.beginRadialGradientStroke,c.bs=c.beginBitmapStroke,c.es=c.endStroke,c.dr=c.drawRect,c.rr=c.drawRoundRect,c.rc=c.drawRoundRectComplex,c.dc=c.drawCircle,c.de=c.drawEllipse,c.dp=c.drawPolyStar,c.p=c.decodePath,c._updateInstructions=function(){this._instructions=this._oldInstructions.slice(),this._instructions.push(b.beginCmd),this._appendInstructions(this._fillInstructions),this._appendInstructions(this._strokeInstructions),this._appendInstructions(this._strokeInstructions&&this._strokeStyleInstructions),this._appendInstructions(this._activeInstructions),this._fillInstructions&&this._appendDraw(b.fillCmd,this._fillMatrix),this._strokeInstructions&&this._appendDraw(b.strokeCmd,this._strokeIgnoreScale&&[1,0,0,1,0,0])},c._appendInstructions=function(a){a&&this._instructions.push.apply(this._instructions,a)},c._appendDraw=function(b,c){c?this._instructions.push(new a(this._ctx.save,[],!1),new a(this._ctx.transform,c,!1),b,new a(this._ctx.restore,[],!1)):this._instructions.push(b)},c._newPath=function(){this._dirty&&this._updateInstructions(),this._oldInstructions=this._instructions,this._activeInstructions=[],this._active=this._dirty=!1},c._setProp=function(a,b){this[a]=b},createjs.Graphics=b}(),this.createjs=this.createjs||{},function(){var a=function(){this.initialize()},b=a.prototype=new createjs.EventDispatcher;a._MOUSE_EVENTS=["click","dblclick","mousedown","mouseout","mouseover","pressmove","pressup","rollout","rollover"],a.suppressCrossDomainErrors=!1;var c=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");c.getContext&&(a._hitTestCanvas=c,a._hitTestContext=c.getContext("2d"),c.width=c.height=1),a._nextCacheID=1,b.alpha=1,b.cacheCanvas=null,b.id=-1,b.mouseEnabled=!0,b.tickEnabled=!0,b.name=null,b.parent=null,b.regX=0,b.regY=0,b.rotation=0,b.scaleX=1,b.scaleY=1,b.skewX=0,b.skewY=0,b.shadow=null,b.visible=!0,b.x=0,b.y=0,b.compositeOperation=null,b.snapToPixel=!1,b.filters=null,b.cacheID=0,b.mask=null,b.hitArea=null,b.cursor=null,b._cacheOffsetX=0,b._cacheOffsetY=0,b._cacheScale=1,b._cacheDataURLID=0,b._cacheDataURL=null,b._matrix=null,b._rectangle=null,b._bounds=null,b.initialize=function(){this.id=createjs.UID.get(),this._matrix=new createjs.Matrix2D,this._rectangle=new createjs.Rectangle},b.isVisible=function(){return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY)},b.draw=function(a,b){var c=this.cacheCanvas;if(b||!c)return!1;var d,e=this._cacheScale,f=this._cacheOffsetX,g=this._cacheOffsetY;return(d=this._applyFilterBounds(f,g,0,0))&&(f=d.x,g=d.y),a.drawImage(c,f,g,c.width/e,c.height/e),!0},b.updateContext=function(a){var b,c=this.mask,d=this;c&&c.graphics&&!c.graphics.isEmpty()&&(b=c.getMatrix(c._matrix),a.transform(b.a,b.b,b.c,b.d,b.tx,b.ty),c.graphics.drawAsPath(a),a.clip(),b.invert(),a.transform(b.a,b.b,b.c,b.d,b.tx,b.ty)),b=d._matrix.identity().appendTransform(d.x,d.y,d.scaleX,d.scaleY,d.rotation,d.skewX,d.skewY,d.regX,d.regY),createjs.Stage._snapToPixelEnabled&&d.snapToPixel?a.transform(b.a,b.b,b.c,b.d,0|b.tx+.5,0|b.ty+.5):a.transform(b.a,b.b,b.c,b.d,b.tx,b.ty),a.globalAlpha*=d.alpha,d.compositeOperation&&(a.globalCompositeOperation=d.compositeOperation),d.shadow&&this._applyShadow(a,d.shadow)},b.cache=function(a,b,c,d,e){e=e||1,this.cacheCanvas||(this.cacheCanvas=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")),this._cacheWidth=c,this._cacheHeight=d,this._cacheOffsetX=a,this._cacheOffsetY=b,this._cacheScale=e,this.updateCache()},b.updateCache=function(b){var c,d=this.cacheCanvas,e=this._cacheScale,f=this._cacheOffsetX*e,g=this._cacheOffsetY*e,h=this._cacheWidth,i=this._cacheHeight;if(!d)throw"cache() must be called before updateCache()";var j=d.getContext("2d");(c=this._applyFilterBounds(f,g,h,i))&&(f=c.x,g=c.y,h=c.width,i=c.height),h=Math.ceil(h*e),i=Math.ceil(i*e),h!=d.width||i!=d.height?(d.width=h,d.height=i):b||j.clearRect(0,0,h+1,i+1),j.save(),j.globalCompositeOperation=b,j.setTransform(e,0,0,e,-f,-g),this.draw(j,!0),this._applyFilters(),j.restore(),this.cacheID=a._nextCacheID++},b.uncache=function(){this._cacheDataURL=this.cacheCanvas=null,this.cacheID=this._cacheOffsetX=this._cacheOffsetY=0,this._cacheScale=1},b.getCacheDataURL=function(){return this.cacheCanvas?(this.cacheID!=this._cacheDataURLID&&(this._cacheDataURL=this.cacheCanvas.toDataURL()),this._cacheDataURL):null},b.getStage=function(){for(var a=this;a.parent;)a=a.parent;return a instanceof createjs.Stage?a:null},b.localToGlobal=function(a,b){var c=this.getConcatenatedMatrix(this._matrix);return null==c?null:(c.append(1,0,0,1,a,b),new createjs.Point(c.tx,c.ty))},b.globalToLocal=function(a,b){var c=this.getConcatenatedMatrix(this._matrix);return null==c?null:(c.invert(),c.append(1,0,0,1,a,b),new createjs.Point(c.tx,c.ty))},b.localToLocal=function(a,b,c){var d=this.localToGlobal(a,b);return c.globalToLocal(d.x,d.y)},b.setTransform=function(a,b,c,d,e,f,g,h,i){return this.x=a||0,this.y=b||0,this.scaleX=null==c?1:c,this.scaleY=null==d?1:d,this.rotation=e||0,this.skewX=f||0,this.skewY=g||0,this.regX=h||0,this.regY=i||0,this},b.getMatrix=function(a){var b=this;return(a?a.identity():new createjs.Matrix2D).appendTransform(b.x,b.y,b.scaleX,b.scaleY,b.rotation,b.skewX,b.skewY,b.regX,b.regY).appendProperties(b.alpha,b.shadow,b.compositeOperation)},b.getConcatenatedMatrix=function(a){a?a.identity():a=new createjs.Matrix2D;for(var b=this;null!=b;)a.prependTransform(b.x,b.y,b.scaleX,b.scaleY,b.rotation,b.skewX,b.skewY,b.regX,b.regY).prependProperties(b.alpha,b.shadow,b.compositeOperation),b=b.parent;return a},b.hitTest=function(b,c){var d=a._hitTestContext;d.setTransform(1,0,0,1,-b,-c),this.draw(d); -var e=this._testHit(d);return d.setTransform(1,0,0,1,0,0),d.clearRect(0,0,2,2),e},b.set=function(a){for(var b in a)this[b]=a[b];return this},b.getBounds=function(){if(this._bounds)return this._rectangle.copy(this._bounds);var a=this.cacheCanvas;if(a){var b=this._cacheScale;return this._rectangle.initialize(this._cacheOffsetX,this._cacheOffsetY,a.width/b,a.height/b)}return null},b.getTransformedBounds=function(){return this._getBounds()},b.setBounds=function(a,b,c,d){null==a&&(this._bounds=a),this._bounds=(this._bounds||new createjs.Rectangle).initialize(a,b,c,d)},b.clone=function(){var b=new a;return this.cloneProps(b),b},b.toString=function(){return"[DisplayObject (name="+this.name+")]"},b.cloneProps=function(a){a.alpha=this.alpha,a.name=this.name,a.regX=this.regX,a.regY=this.regY,a.rotation=this.rotation,a.scaleX=this.scaleX,a.scaleY=this.scaleY,a.shadow=this.shadow,a.skewX=this.skewX,a.skewY=this.skewY,a.visible=this.visible,a.x=this.x,a.y=this.y,a._bounds=this._bounds,a.mouseEnabled=this.mouseEnabled,a.compositeOperation=this.compositeOperation},b._applyShadow=function(a,b){b=b||Shadow.identity,a.shadowColor=b.color,a.shadowOffsetX=b.offsetX,a.shadowOffsetY=b.offsetY,a.shadowBlur=b.blur},b._tick=function(a){var b=this._listeners;if(b&&b.tick){var c=new createjs.Event("tick");c.params=a,this._dispatchEvent(c,this,2)}},b._testHit=function(b){try{var c=b.getImageData(0,0,1,1).data[3]>1}catch(d){if(!a.suppressCrossDomainErrors)throw"An error has occurred. This is most likely due to security restrictions on reading canvas pixel data with local or cross-domain images."}return c},b._applyFilters=function(){if(this.filters&&0!=this.filters.length&&this.cacheCanvas)for(var a=this.filters.length,b=this.cacheCanvas.getContext("2d"),c=this.cacheCanvas.width,d=this.cacheCanvas.height,e=0;a>e;e++)this.filters[e].applyFilter(b,0,0,c,d)},b._applyFilterBounds=function(a,b,c,d){var e,f,g=this.filters;if(!g||!(f=g.length))return null;for(var h=0;f>h;h++){var i=this.filters[h],j=i.getBounds&&i.getBounds();j&&(e||(e=this._rectangle.initialize(a,b,c,d)),e.x+=j.x,e.y+=j.y,e.width+=j.width,e.height+=j.height)}return e},b._getBounds=function(a,b){return this._transformBounds(this.getBounds(),a,b)},b._transformBounds=function(a,b,c){if(!a)return a;var d=a.x,e=a.y,f=a.width,g=a.height,h=c?this._matrix.identity():this.getMatrix(this._matrix);(d||e)&&h.appendTransform(0,0,1,1,0,0,0,-d,-e),b&&h.prependMatrix(b);var i=f*h.a,j=f*h.b,k=g*h.c,l=g*h.d,m=h.tx,n=h.ty,o=m,p=m,q=n,r=n;return(d=i+m)p&&(p=d),(d=i+k+m)p&&(p=d),(d=k+m)p&&(p=d),(e=j+n)r&&(r=e),(e=j+l+n)r&&(r=e),(e=l+n)r&&(r=e),a.initialize(o,q,p-o,r-q)},b._hasMouseEventListener=function(){for(var b=a._MOUSE_EVENTS,c=0,d=b.length;d>c;c++)if(this.hasEventListener(b[c]))return!0;return!!this.cursor},createjs.DisplayObject=a}(),this.createjs=this.createjs||{},function(){var a=function(){this.initialize()},b=a.prototype=new createjs.DisplayObject;b.children=null,b.mouseChildren=!0,b.tickChildren=!0,b.DisplayObject_initialize=b.initialize,b.initialize=function(){this.DisplayObject_initialize(),this.children=[]},b.isVisible=function(){var a=this.cacheCanvas||this.children.length;return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&a)},b.DisplayObject_draw=b.draw,b.draw=function(a,b){if(this.DisplayObject_draw(a,b))return!0;for(var c=this.children.slice(0),d=0,e=c.length;e>d;d++){var f=c[d];f.isVisible()&&(a.save(),f.updateContext(a),f.draw(a),a.restore())}return!0},b.addChild=function(a){if(null==a)return a;var b=arguments.length;if(b>1){for(var c=0;b>c;c++)this.addChild(arguments[c]);return arguments[b-1]}return a.parent&&a.parent.removeChild(a),a.parent=this,this.children.push(a),a},b.addChildAt=function(a,b){var c=arguments.length,d=arguments[c-1];if(0>d||d>this.children.length)return arguments[c-2];if(c>2){for(var e=0;c-1>e;e++)this.addChildAt(arguments[e],d+e);return arguments[c-2]}return a.parent&&a.parent.removeChild(a),a.parent=this,this.children.splice(b,0,a),a},b.removeChild=function(a){var b=arguments.length;if(b>1){for(var c=!0,d=0;b>d;d++)c=c&&this.removeChild(arguments[d]);return c}return this.removeChildAt(createjs.indexOf(this.children,a))},b.removeChildAt=function(a){var b=arguments.length;if(b>1){for(var c=[],d=0;b>d;d++)c[d]=arguments[d];c.sort(function(a,b){return b-a});for(var e=!0,d=0;b>d;d++)e=e&&this.removeChildAt(c[d]);return e}if(0>a||a>this.children.length-1)return!1;var f=this.children[a];return f&&(f.parent=null),this.children.splice(a,1),!0},b.removeAllChildren=function(){for(var a=this.children;a.length;)a.pop().parent=null},b.getChildAt=function(a){return this.children[a]},b.getChildByName=function(a){for(var b=this.children,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},b.sortChildren=function(a){this.children.sort(a)},b.getChildIndex=function(a){return createjs.indexOf(this.children,a)},b.getNumChildren=function(){return this.children.length},b.swapChildrenAt=function(a,b){var c=this.children,d=c[a],e=c[b];d&&e&&(c[a]=e,c[b]=d)},b.swapChildren=function(a,b){for(var c,d,e=this.children,f=0,g=e.length;g>f&&(e[f]==a&&(c=f),e[f]==b&&(d=f),null==c||null==d);f++);f!=g&&(e[c]=b,e[d]=a)},b.setChildIndex=function(a,b){var c=this.children,d=c.length;if(!(a.parent!=this||0>b||b>=d)){for(var e=0;d>e&&c[e]!=a;e++);e!=d&&e!=b&&(c.splice(e,1),c.splice(b,0,a))}},b.contains=function(a){for(;a;){if(a==this)return!0;a=a.parent}return!1},b.hitTest=function(a,b){return null!=this.getObjectUnderPoint(a,b)},b.getObjectsUnderPoint=function(a,b){var c=[],d=this.localToGlobal(a,b);return this._getObjectsUnderPoint(d.x,d.y,c),c},b.getObjectUnderPoint=function(a,b){var c=this.localToGlobal(a,b);return this._getObjectsUnderPoint(c.x,c.y)},b.DisplayObject_getBounds=b.getBounds,b.getBounds=function(){return this._getBounds(null,!0)},b.getTransformedBounds=function(){return this._getBounds()},b.clone=function(b){var c=new a;if(this.cloneProps(c),b)for(var d=c.children=[],e=0,f=this.children.length;f>e;e++){var g=this.children[e].clone(b);g.parent=c,d.push(g)}return c},b.toString=function(){return"[Container (name="+this.name+")]"},b.DisplayObject__tick=b._tick,b._tick=function(a){if(this.tickChildren)for(var b=this.children.length-1;b>=0;b--){var c=this.children[b];c.tickEnabled&&c._tick&&c._tick(a)}this.DisplayObject__tick(a)},b._getObjectsUnderPoint=function(b,c,d,e,f){var g=createjs.DisplayObject._hitTestContext,h=this._matrix;f=f||e&&this._hasMouseEventListener();for(var i=this.children,j=i.length,k=j-1;k>=0;k--){var l=i[k],m=l.hitArea;if(l.visible&&(m||l.isVisible())&&(!e||l.mouseEnabled))if(!m&&l instanceof a){var n=l._getObjectsUnderPoint(b,c,d,e,f);if(!d&&n)return e&&!this.mouseChildren?this:n}else{if(!f&&!l._hasMouseEventListener())continue;if(l.getConcatenatedMatrix(h),m&&(h.appendTransform(m.x,m.y,m.scaleX,m.scaleY,m.rotation,m.skewX,m.skewY,m.regX,m.regY),h.alpha=m.alpha),g.globalAlpha=h.alpha,g.setTransform(h.a,h.b,h.c,h.d,h.tx-b,h.ty-c),(m||l).draw(g),!this._testHit(g))continue;if(g.setTransform(1,0,0,1,0,0),g.clearRect(0,0,2,2),!d)return e&&!this.mouseChildren?this:l;d.push(l)}}return null},b._getBounds=function(a,b){var c=this.DisplayObject_getBounds();if(c)return this._transformBounds(c,a,b);var d,e,f,g,h=b?this._matrix.identity():this.getMatrix(this._matrix);a&&h.prependMatrix(a);for(var i=this.children.length,j=0;i>j;j++){var k=this.children[j];if(k.visible&&(c=k._getBounds(h))){var l=c.x,m=c.y,n=l+c.width,o=m+c.height;(d>l||null==d)&&(d=l),(n>e||null==e)&&(e=n),(f>m||null==f)&&(f=m),(o>g||null==g)&&(g=o)}}return null==e?null:this._rectangle.initialize(d,f,e-d,g-f)},createjs.Container=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a){this.initialize(a)},b=a.prototype=new createjs.Container;a._snapToPixelEnabled=!1,b.autoClear=!0,b.canvas=null,b.mouseX=0,b.mouseY=0,b.snapToPixelEnabled=!1,b.mouseInBounds=!1,b.tickOnUpdate=!0,b.mouseMoveOutside=!1,b.nextStage=null,b._pointerData=null,b._pointerCount=0,b._primaryPointerID=null,b._mouseOverIntervalID=null,b.Container_initialize=b.initialize,b.initialize=function(a){this.Container_initialize(),this.canvas="string"==typeof a?document.getElementById(a):a,this._pointerData={},this.enableDOMEvents(!0)},b.update=function(){if(this.canvas){this.tickOnUpdate&&(this.dispatchEvent("tickstart"),this.tickEnabled&&this._tick(arguments.length?arguments:null),this.dispatchEvent("tickend")),this.dispatchEvent("drawstart"),a._snapToPixelEnabled=this.snapToPixelEnabled,this.autoClear&&this.clear();var b=this.canvas.getContext("2d");b.save(),this.updateContext(b),this.draw(b,!1),b.restore(),this.dispatchEvent("drawend")}},b.handleEvent=function(a){"tick"==a.type&&this.update(a)},b.clear=function(){if(this.canvas){var a=this.canvas.getContext("2d");a.setTransform(1,0,0,1,0,0),a.clearRect(0,0,this.canvas.width+1,this.canvas.height+1)}},b.toDataURL=function(a,b){b||(b="image/png");var c,d=this.canvas.getContext("2d"),e=this.canvas.width,f=this.canvas.height;if(a){c=d.getImageData(0,0,e,f);var g=d.globalCompositeOperation;d.globalCompositeOperation="destination-over",d.fillStyle=a,d.fillRect(0,0,e,f)}var h=this.canvas.toDataURL(b);return a&&(d.clearRect(0,0,e+1,f+1),d.putImageData(c,0,0),d.globalCompositeOperation=g),h},b.enableMouseOver=function(a){if(this._mouseOverIntervalID&&(clearInterval(this._mouseOverIntervalID),this._mouseOverIntervalID=null,0==a&&this._testMouseOver(!0)),null==a)a=20;else if(0>=a)return;var b=this;this._mouseOverIntervalID=setInterval(function(){b._testMouseOver()},1e3/Math.min(50,a))},b.enableDOMEvents=function(a){null==a&&(a=!0);var b,c,d=this._eventListeners;if(!a&&d){for(b in d)c=d[b],c.t.removeEventListener(b,c.f,!1);this._eventListeners=null}else if(a&&!d&&this.canvas){var e=window.addEventListener?window:document,f=this;d=this._eventListeners={},d.mouseup={t:e,f:function(a){f._handleMouseUp(a)}},d.mousemove={t:e,f:function(a){f._handleMouseMove(a)}},d.dblclick={t:this.canvas,f:function(a){f._handleDoubleClick(a)}},d.mousedown={t:this.canvas,f:function(a){f._handleMouseDown(a)}};for(b in d)c=d[b],c.t.addEventListener(b,c.f,!1)}},b.clone=function(){var b=new a(null);return this.cloneProps(b),b},b.toString=function(){return"[Stage (name="+this.name+")]"},b._getElementRect=function(a){var b;try{b=a.getBoundingClientRect()}catch(c){b={top:a.offsetTop,left:a.offsetLeft,width:a.offsetWidth,height:a.offsetHeight}}var d=(window.pageXOffset||document.scrollLeft||0)-(document.clientLeft||document.body.clientLeft||0),e=(window.pageYOffset||document.scrollTop||0)-(document.clientTop||document.body.clientTop||0),f=window.getComputedStyle?getComputedStyle(a):a.currentStyle,g=parseInt(f.paddingLeft)+parseInt(f.borderLeftWidth),h=parseInt(f.paddingTop)+parseInt(f.borderTopWidth),i=parseInt(f.paddingRight)+parseInt(f.borderRightWidth),j=parseInt(f.paddingBottom)+parseInt(f.borderBottomWidth);return{left:b.left+d+g,right:b.right+d-i,top:b.top+e+h,bottom:b.bottom+e-j}},b._getPointerData=function(a){var b=this._pointerData[a];return b||(b=this._pointerData[a]={x:0,y:0},null==this._primaryPointerID&&(this._primaryPointerID=a),(null==this._primaryPointerID||-1==this._primaryPointerID)&&(this._primaryPointerID=a)),b},b._handleMouseMove=function(a){a||(a=window.event),this._handlePointerMove(-1,a,a.pageX,a.pageY)},b._handlePointerMove=function(a,b,c,d){if(this.canvas){var e=this._getPointerData(a),f=e.inBounds;if(this._updatePointerPosition(a,b,c,d),f||e.inBounds||this.mouseMoveOutside){-1==a&&e.inBounds==!f&&this._dispatchMouseEvent(this,f?"mouseleave":"mouseenter",!1,a,e,b),this._dispatchMouseEvent(this,"stagemousemove",!1,a,e,b),this._dispatchMouseEvent(e.target,"pressmove",!0,a,e,b);var g=e.event;g&&g.hasEventListener("mousemove")&&g.dispatchEvent(new createjs.MouseEvent("mousemove",!1,!1,e.x,e.y,b,a,a==this._primaryPointerID,e.rawX,e.rawY),e.target),this.nextStage&&this.nextStage._handlePointerMove(a,b,c,d)}}},b._updatePointerPosition=function(a,b,c,d){var e=this._getElementRect(this.canvas);c-=e.left,d-=e.top;var f=this.canvas.width,g=this.canvas.height;c/=(e.right-e.left)/f,d/=(e.bottom-e.top)/g;var h=this._getPointerData(a);(h.inBounds=c>=0&&d>=0&&f-1>=c&&g-1>=d)?(h.x=c,h.y=d):this.mouseMoveOutside&&(h.x=0>c?0:c>f-1?f-1:c,h.y=0>d?0:d>g-1?g-1:d),h.posEvtObj=b,h.rawX=c,h.rawY=d,a==this._primaryPointerID&&(this.mouseX=h.x,this.mouseY=h.y,this.mouseInBounds=h.inBounds)},b._handleMouseUp=function(a){this._handlePointerUp(-1,a,!1)},b._handlePointerUp=function(a,b,c){var d=this._getPointerData(a);this._dispatchMouseEvent(this,"stagemouseup",!1,a,d,b);var e=d.target;e&&(this._getObjectsUnderPoint(d.x,d.y,null,!0)==e&&this._dispatchMouseEvent(e,"click",!0,a,d,b),this._dispatchMouseEvent(e,"pressup",!0,a,d,b));var f=d.event;f&&f.hasEventListener("mouseup")&&f.dispatchEvent(new createjs.MouseEvent("mouseup",!1,!1,d.x,d.y,b,a,a==this._primaryPointerID,d.rawX,d.rawY),e),c?(a==this._primaryPointerID&&(this._primaryPointerID=null),delete this._pointerData[a]):d.event=d.target=null,this.nextStage&&this.nextStage._handlePointerUp(a,b,c)},b._handleMouseDown=function(a){this._handlePointerDown(-1,a,a.pageX,a.pageY)},b._handlePointerDown=function(a,b,c,d){null!=d&&this._updatePointerPosition(a,b,c,d);var e=this._getPointerData(a);this._dispatchMouseEvent(this,"stagemousedown",!1,a,e,b),e.target=this._getObjectsUnderPoint(e.x,e.y,null,!0),e.event=this._dispatchMouseEvent(e.target,"mousedown",!0,a,e,b),this.nextStage&&this.nextStage._handlePointerDown(a,b,c,d)},b._testMouseOver=function(a){if(-1==this._primaryPointerID&&(a||this.mouseX!=this._mouseOverX||this.mouseY!=this._mouseOverY||!this.mouseInBounds)){var b,c,d,e,f=this._getPointerData(-1),g=f.posEvtObj,h=-1,i="";(a||this.mouseInBounds&&g&&g.target==this.canvas)&&(b=this._getObjectsUnderPoint(this.mouseX,this.mouseY,null,!0),this._mouseOverX=this.mouseX,this._mouseOverY=this.mouseY);var j=this._mouseOverTarget||[],k=j[j.length-1],l=this._mouseOverTarget=[];for(c=b;c;)l.unshift(c),null!=c.cursor&&(i=c.cursor),c=c.parent;for(this.canvas.style.cursor=i,d=0,e=l.length;e>d&&l[d]==j[d];d++)h=d;for(k!=b&&this._dispatchMouseEvent(k,"mouseout",!0,-1,f,g),d=j.length-1;d>h;d--)this._dispatchMouseEvent(j[d],"rollout",!1,-1,f,g);for(d=l.length-1;d>h;d--)this._dispatchMouseEvent(l[d],"rollover",!1,-1,f,g);k!=b&&this._dispatchMouseEvent(b,"mouseover",!0,-1,f,g)}},b._handleDoubleClick=function(a){var b=this._getPointerData(-1),c=this._getObjectsUnderPoint(b.x,b.y,null,!0);this._dispatchMouseEvent(c,"dblclick",!0,-1,b,a),this.nextStage&&this.nextStage._handleDoubleClick(a)},b._dispatchMouseEvent=function(a,b,c,d,e,f){if(a&&(c||a.hasEventListener(b))){var g=new createjs.MouseEvent(b,c,!1,e.x,e.y,f,d,d==this._primaryPointerID,e.rawX,e.rawY);return a.dispatchEvent(g),g}},createjs.Stage=a}(),this.createjs=this.createjs||{},function(){var a=function(a){this.initialize(a)},b=a.prototype=new createjs.DisplayObject;b.image=null,b.snapToPixel=!0,b.sourceRect=null,b.DisplayObject_initialize=b.initialize,b.initialize=function(a){this.DisplayObject_initialize(),"string"==typeof a?(this.image=document.createElement("img"),this.image.src=a):this.image=a},b.isVisible=function(){var a=this.cacheCanvas||this.image&&(this.image.complete||this.image.getContext||this.image.readyState>=2);return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&a)},b.DisplayObject_draw=b.draw,b.draw=function(a,b){if(this.DisplayObject_draw(a,b))return!0;var c=this.sourceRect;return c?a.drawImage(this.image,c.x,c.y,c.width,c.height,0,0,c.width,c.height):a.drawImage(this.image,0,0),!0},b.DisplayObject_getBounds=b.getBounds,b.getBounds=function(){var a=this.DisplayObject_getBounds();if(a)return a;var b=this.sourceRect||this.image,c=this.image&&(this.image.complete||this.image.getContext||this.image.readyState>=2);return c?this._rectangle.initialize(0,0,b.width,b.height):null},b.clone=function(){var b=new a(this.image);return this.sourceRect&&(b.sourceRect=this.sourceRect.clone()),this.cloneProps(b),b},b.toString=function(){return"[Bitmap (name="+this.name+")]"},createjs.Bitmap=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b){this.initialize(a,b)},b=a.prototype=new createjs.DisplayObject;b.currentFrame=0,b.currentAnimation=null,b.paused=!0,b.spriteSheet=null,b.snapToPixel=!0,b.offset=0,b.currentAnimationFrame=0,b.framerate=0,b._advanceCount=0,b._animation=null,b._currentFrame=null,b.DisplayObject_initialize=b.initialize,b.initialize=function(a,b){this.DisplayObject_initialize(),this.spriteSheet=a,b&&this.gotoAndPlay(b)},b.isVisible=function(){var a=this.cacheCanvas||this.spriteSheet.complete;return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&a)},b.DisplayObject_draw=b.draw,b.draw=function(a,b){if(this.DisplayObject_draw(a,b))return!0;this._normalizeFrame();var c=this.spriteSheet.getFrame(0|this._currentFrame);if(!c)return!1;var d=c.rect;return a.drawImage(c.image,d.x,d.y,d.width,d.height,-c.regX,-c.regY,d.width,d.height),!0},b.play=function(){this.paused=!1},b.stop=function(){this.paused=!0},b.gotoAndPlay=function(a){this.paused=!1,this._goto(a)},b.gotoAndStop=function(a){this.paused=!0,this._goto(a)},b.advance=function(a){var b=this._animation&&this._animation.speed||1,c=this.framerate||this.spriteSheet.framerate,d=c&&null!=a?a/(1e3/c):1;this._animation?this.currentAnimationFrame+=d*b:this._currentFrame+=d*b,this._normalizeFrame()},b.DisplayObject_getBounds=b.getBounds,b.getBounds=function(){return this.DisplayObject_getBounds()||this.spriteSheet.getFrameBounds(this.currentFrame,this._rectangle)},b.clone=function(){var b=new a(this.spriteSheet);return this.cloneProps(b),b},b.toString=function(){return"[Sprite (name="+this.name+")]"},b.DisplayObject__tick=b._tick,b._tick=function(a){this.paused||this.advance(a&&a[0]&&a[0].delta),this.DisplayObject__tick(a)},b._normalizeFrame=function(){var a,b=this._animation,c=this.paused,d=this._currentFrame,e=this.currentAnimationFrame;if(b)if(a=b.frames.length,(0|e)>=a){var f=b.next;if(this._dispatchAnimationEnd(b,d,c,f,a-1));else{if(f)return this._goto(f,e-a);this.paused=!0,e=this.currentAnimationFrame=b.frames.length-1,this._currentFrame=b.frames[e]}}else this._currentFrame=b.frames[0|e];else if(a=this.spriteSheet.getNumFrames(),d>=a&&!this._dispatchAnimationEnd(b,d,c,a-1)&&(this._currentFrame-=a)>=a)return this._normalizeFrame();this.currentFrame=0|this._currentFrame},b._dispatchAnimationEnd=function(a,b,c,d,e){var f=a?a.name:null;if(this.hasEventListener("animationend")){var g=new createjs.Event("animationend");g.name=f,g.next=d,this.dispatchEvent(g)}var h=this._animation!=a||this._currentFrame!=b;return h||c||!this.paused||(this.currentAnimationFrame=e,h=!0),h},b.DisplayObject_cloneProps=b.cloneProps,b.cloneProps=function(a){this.DisplayObject_cloneProps(a),a.currentFrame=this.currentFrame,a._currentFrame=this._currentFrame,a.currentAnimation=this.currentAnimation,a.paused=this.paused,a._animation=this._animation,a.currentAnimationFrame=this.currentAnimationFrame,a.framerate=this.framerate},b._goto=function(a,b){if(isNaN(a)){var c=this.spriteSheet.getAnimation(a);c&&(this.currentAnimationFrame=b||0,this._animation=c,this.currentAnimation=a,this._normalizeFrame())}else this.currentAnimationFrame=0,this.currentAnimation=this._animation=null,this._currentFrame=a,this._normalizeFrame()},createjs.Sprite=a}(),this.createjs=this.createjs||{},function(){"use strict";var a="BitmapAnimation is deprecated in favour of Sprite. See VERSIONS file for info on changes.";if(!createjs.Sprite)throw a;(createjs.BitmapAnimation=function(b){console.log(a),this.initialize(b)}).prototype=new createjs.Sprite}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a){this.initialize(a)},b=a.prototype=new createjs.DisplayObject;b.graphics=null,b.DisplayObject_initialize=b.initialize,b.initialize=function(a){this.DisplayObject_initialize(),this.graphics=a?a:new createjs.Graphics},b.isVisible=function(){var a=this.cacheCanvas||this.graphics&&!this.graphics.isEmpty();return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&a)},b.DisplayObject_draw=b.draw,b.draw=function(a,b){return this.DisplayObject_draw(a,b)?!0:(this.graphics.draw(a),!0)},b.clone=function(b){var c=new a(b&&this.graphics?this.graphics.clone():this.graphics);return this.cloneProps(c),c},b.toString=function(){return"[Shape (name="+this.name+")]"},createjs.Shape=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c){this.initialize(a,b,c)},b=a.prototype=new createjs.DisplayObject,c=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");c.getContext&&(a._workingContext=c.getContext("2d"),c.width=c.height=1),a.H_OFFSETS={start:0,left:0,center:-.5,end:-1,right:-1},a.V_OFFSETS={top:0,hanging:-.01,middle:-.4,alphabetic:-.8,ideographic:-.85,bottom:-1},b.text="",b.font=null,b.color=null,b.textAlign="left",b.textBaseline="top",b.maxWidth=null,b.outline=0,b.lineHeight=0,b.lineWidth=null,b.DisplayObject_initialize=b.initialize,b.initialize=function(a,b,c){this.DisplayObject_initialize(),this.text=a,this.font=b,this.color=c},b.isVisible=function(){var a=this.cacheCanvas||null!=this.text&&""!==this.text;return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&a)},b.DisplayObject_draw=b.draw,b.draw=function(a,b){if(this.DisplayObject_draw(a,b))return!0;var c=this.color||"#000";return this.outline?(a.strokeStyle=c,a.lineWidth=1*this.outline):a.fillStyle=c,this._drawText(this._prepContext(a)),!0},b.getMeasuredWidth=function(){return this._prepContext(a._workingContext).measureText(this.text).width},b.getMeasuredLineHeight=function(){return 1.2*this._prepContext(a._workingContext).measureText("M").width},b.getMeasuredHeight=function(){return this._drawText(null,{}).height},b.DisplayObject_getBounds=b.getBounds,b.getBounds=function(){var b=this.DisplayObject_getBounds();if(b)return b;if(null==this.text||""==this.text)return null;var c=this._drawText(null,{}),d=this.maxWidth&&this.maxWidthi;i++){var k=h[i],l=null;if(null!=this.lineWidth&&(l=b.measureText(k).width)>this.lineWidth){var m=k.split(/(\s)/);k=m[0],l=b.measureText(k).width;for(var n=1,o=m.length;o>n;n+=2){var p=b.measureText(m[n]+m[n+1]).width;l+p>this.lineWidth?(d&&this._drawTextLine(b,k,g*e),l>f&&(f=l),k=m[n+1],l=b.measureText(k).width,g++):(k+=m[n]+m[n+1],l+=p)}}d&&this._drawTextLine(b,k,g*e),c&&null==l&&(l=b.measureText(k).width),l>f&&(f=l),g++}return c&&(c.count=g,c.width=f,c.height=g*e),c},b._drawTextLine=function(a,b,c){this.outline?a.strokeText(b,0,c,this.maxWidth||65535):a.fillText(b,0,c,this.maxWidth||65535)},createjs.Text=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(a,b){this.initialize(a,b)}var b=a.prototype=new createjs.DisplayObject;b.text="",b.spriteSheet=null,b.lineHeight=0,b.letterSpacing=0,b.spaceWidth=0,b.DisplayObject_initialize=b.initialize,b.initialize=function(a,b){this.DisplayObject_initialize(),this.text=a,this.spriteSheet=b},b.DisplayObject_draw=b.draw,b.draw=function(a,b){return this.DisplayObject_draw(a,b)?!0:(this._drawText(a),void 0)},b.isVisible=function(){var a=this.cacheCanvas||this.spriteSheet&&this.spriteSheet.complete&&this.text;return!!(this.visible&&this.alpha>0&&0!=this.scaleX&&0!=this.scaleY&&a)},b.getBounds=function(){var a=this._rectangle;return this._drawText(null,a),a.width?a:null},b._getFrame=function(a,b){var c,d=b.getAnimation(a);return d||(a!=(c=a.toUpperCase())||a!=(c=a.toLowerCase())||(c=null),c&&(d=b.getAnimation(c))),d&&b.getFrame(d.frames[0])},b._getLineHeight=function(a){var b=this._getFrame("1",a)||this._getFrame("T",a)||this._getFrame("L",a)||a.getFrame(0);return b?b.rect.height:1},b._getSpaceWidth=function(a){var b=this._getFrame("1",a)||this._getFrame("l",a)||this._getFrame("e",a)||this._getFrame("a",a)||a.getFrame(0);return b?b.rect.width:1},b._drawText=function(a,b){var c,d,e,f=0,g=0,h=this.spaceWidth,i=this.lineHeight,j=this.spriteSheet,k=!!this._getFrame(" ",j);k||0!=h||(h=this._getSpaceWidth(j)),0==i&&(i=this._getLineHeight(j));for(var l=0,m=0,n=this.text.length;n>m;m++){var o=this.text.charAt(m);if(k||" "!=o)if("\n"!=o&&"\r"!=o){var p=this._getFrame(o,j);if(p){var q=p.rect;e=p.regX,c=q.width,a&&a.drawImage(p.image,q.x,q.y,c,d=q.height,f-e,g-p.regY,c,d),f+=c+this.letterSpacing}}else"\r"==o&&"\n"==this.text.charAt(m+1)&&m++,f-e>l&&(l=f-e),f=0,g+=i;else f+=h}f-e>l&&(l=f-e),b&&(b.width=l-this.letterSpacing,b.height=g+i)},createjs.BitmapText=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){throw"SpriteSheetUtils cannot be instantiated"},b=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");b.getContext&&(a._workingCanvas=b,a._workingContext=b.getContext("2d"),b.width=b.height=1),a.addFlippedFrames=function(b,c,d,e){if(c||d||e){var f=0;c&&a._flip(b,++f,!0,!1),d&&a._flip(b,++f,!1,!0),e&&a._flip(b,++f,!0,!0)}},a.extractFrame=function(b,c){isNaN(c)&&(c=b.getAnimation(c).frames[0]);var d=b.getFrame(c);if(!d)return null;var e=d.rect,f=a._workingCanvas;f.width=e.width,f.height=e.height,a._workingContext.drawImage(d.image,e.x,e.y,e.width,e.height,0,0,e.width,e.height);var g=document.createElement("img");return g.src=f.toDataURL("image/png"),g},a.mergeAlpha=function(a,b,c){c||(c=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")),c.width=Math.max(b.width,a.width),c.height=Math.max(b.height,a.height);var d=c.getContext("2d");return d.save(),d.drawImage(a,0,0),d.globalCompositeOperation="destination-in",d.drawImage(b,0,0),d.restore(),c},a._flip=function(b,c,d,e){for(var f=b._images,g=a._workingCanvas,h=a._workingContext,i=f.length/c,j=0;i>j;j++){var k=f[j];k.__tmp=j,h.setTransform(1,0,0,1,0,0),h.clearRect(0,0,g.width+1,g.height+1),g.width=k.width,g.height=k.height,h.setTransform(d?-1:1,0,0,e?-1:1,d?k.width:0,e?k.height:0),h.drawImage(k,0,0);var l=document.createElement("img");l.src=g.toDataURL("image/png"),l.width=k.width,l.height=k.height,f.push(l)}var m=b._frames,n=m.length/c;for(j=0;n>j;j++){k=m[j];var o=k.rect.clone();l=f[k.image.__tmp+i*c];var p={image:l,rect:o,regX:k.regX,regY:k.regY};d&&(o.x=l.width-o.x-o.width,p.regX=o.width-k.regX),e&&(o.y=l.height-o.y-o.height,p.regY=o.height-k.regY),m.push(p)}var q="_"+(d?"h":"")+(e?"v":""),r=b._animations,s=b._data,t=r.length/c;for(j=0;t>j;j++){var u=r[j];k=s[u];var v={name:u+q,speed:k.speed,next:k.next,frames:[]};k.next&&(v.next+=q),m=k.frames;for(var w=0,x=m.length;x>w;w++)v.frames.push(m[w]+n*c);s[v.name]=v,r.push(v.name)}},createjs.SpriteSheetUtils=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){this.initialize()},b=a.prototype=new createjs.EventDispatcher;a.ERR_DIMENSIONS="frame dimensions exceed max spritesheet dimensions",a.ERR_RUNNING="a build is already running",b.maxWidth=2048,b.maxHeight=2048,b.spriteSheet=null,b.scale=1,b.padding=1,b.timeSlice=.3,b.progress=-1,b._frames=null,b._animations=null,b._data=null,b._nextFrameIndex=0,b._index=0,b._timerID=null,b._scale=1,b.initialize=function(){this._frames=[],this._animations={}},b.addFrame=function(b,c,d,e,f,g){if(this._data)throw a.ERR_RUNNING;var h=c||b.bounds||b.nominalBounds;return!h&&b.getBounds&&(h=b.getBounds()),h?(d=d||1,this._frames.push({source:b,sourceRect:h,scale:d,funct:e,params:f,scope:g,index:this._frames.length,height:h.height*d})-1):null},b.addAnimation=function(b,c,d,e){if(this._data)throw a.ERR_RUNNING;this._animations[b]={frames:c,next:d,frequency:e}},b.addMovieClip=function(b,c,d){if(this._data)throw a.ERR_RUNNING;var e=b.frameBounds,f=c||b.bounds||b.nominalBounds;if(!f&&b.getBounds&&(f=b.getBounds()),!f&&!e)return null;for(var g=this._frames.length,h=b.timeline.duration,i=0;h>i;i++){var j=e&&e[i]?e[i]:f;this.addFrame(b,j,d,function(a){var b=this.actionsEnabled;this.actionsEnabled=!1,this.gotoAndStop(a),this.actionsEnabled=b},[i],b)}var k=b.timeline._labels,l=[];for(var m in k)l.push({index:k[m],label:m});if(l.length){l.sort(function(a,b){return a.index-b.index});for(var i=0,n=l.length;n>i;i++){for(var o=l[i].label,p=g+l[i].index,q=g+(i==n-1?h:l[i+1].index),r=[],s=p;q>s;s++)r.push(s);this.addAnimation(o,r,!0)}}},b.build=function(){if(this._data)throw a.ERR_RUNNING;for(this._startBuild();this._drawNext(););return this._endBuild(),this.spriteSheet},b.buildAsync=function(b){if(this._data)throw a.ERR_RUNNING;this.timeSlice=b,this._startBuild();var c=this;this._timerID=setTimeout(function(){c._run()},50-50*Math.max(.01,Math.min(.99,this.timeSlice||.3)))},b.stopAsync=function(){clearTimeout(this._timerID),this._data=null},b.clone=function(){throw"SpriteSheetBuilder cannot be cloned."},b.toString=function(){return"[SpriteSheetBuilder]"},b._startBuild=function(){var b=this.padding||0;this.progress=0,this.spriteSheet=null,this._index=0,this._scale=this.scale;var c=[];this._data={images:[],frames:c,animations:this._animations};var d=this._frames.slice();if(d.sort(function(a,b){return a.height<=b.height?-1:1}),d[d.length-1].height+2*b>this.maxHeight)throw a.ERR_DIMENSIONS;for(var e=0,f=0,g=0;d.length;){var h=this._fillRow(d,e,g,c,b);if(h.w>f&&(f=h.w),e+=h.h,!h.h||!d.length){var i=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");i.width=this._getSize(f,this.maxWidth),i.height=this._getSize(e,this.maxHeight),this._data.images[g]=i,h.h||(f=e=0,g++)}}},b._getSize=function(a,b){for(var c=4;Math.pow(2,++c)=0;l--){var m=b[l],n=this._scale*m.scale,o=m.sourceRect,p=m.source,q=Math.floor(n*o.x-f),r=Math.floor(n*o.y-f),s=Math.ceil(n*o.height+2*f),t=Math.ceil(n*o.width+2*f);if(t>g)throw a.ERR_DIMENSIONS;s>i||j+t>g||(m.img=d,m.rect=new createjs.Rectangle(j,c,t,s),k=k||s,b.splice(l,1),e[m.index]=[j,c,t,s,d,Math.round(-q+n*p.regX-f),Math.round(-r+n*p.regY-f)],j+=t)}return{w:j,h:k}},b._endBuild=function(){this.spriteSheet=new createjs.SpriteSheet(this._data),this._data=null,this.progress=1,this.dispatchEvent("complete")},b._run=function(){for(var a=50*Math.max(.01,Math.min(.99,this.timeSlice||.3)),b=(new Date).getTime()+a,c=!1;b>(new Date).getTime();)if(!this._drawNext()){c=!0;break}if(c)this._endBuild();else{var d=this;this._timerID=setTimeout(function(){d._run()},50-a)}var e=this.progress=this._index/this._frames.length;if(this.hasEventListener("progress")){var f=new createjs.Event("progress");f.progress=e,this.dispatchEvent(f)}},b._drawNext=function(){var a=this._frames[this._index],b=a.scale*this._scale,c=a.rect,d=a.sourceRect,e=this._data.images[a.img],f=e.getContext("2d");return a.funct&&a.funct.apply(a.scope,a.params),f.save(),f.beginPath(),f.rect(c.x,c.y,c.width,c.height),f.clip(),f.translate(Math.ceil(c.x-d.x*b),Math.ceil(c.y-d.y*b)),f.scale(b,b),a.source.draw(f),f.restore(),++this._indexa)&&(a=0),this.blurX=0|a,(isNaN(b)||0>b)&&(b=0),this.blurY=0|b,(isNaN(c)||1>c)&&(c=1),this.quality=0|c},b.blurX=0,b.blurY=0,b.quality=1,b.mul_table=[1,171,205,293,57,373,79,137,241,27,391,357,41,19,283,265,497,469,443,421,25,191,365,349,335,161,155,149,9,278,269,261,505,245,475,231,449,437,213,415,405,395,193,377,369,361,353,345,169,331,325,319,313,307,301,37,145,285,281,69,271,267,263,259,509,501,493,243,479,118,465,459,113,446,55,435,429,423,209,413,51,403,199,393,97,3,379,375,371,367,363,359,355,351,347,43,85,337,333,165,327,323,5,317,157,311,77,305,303,75,297,294,73,289,287,71,141,279,277,275,68,135,67,133,33,262,260,129,511,507,503,499,495,491,61,121,481,477,237,235,467,232,115,457,227,451,7,445,221,439,218,433,215,427,425,211,419,417,207,411,409,203,202,401,399,396,197,49,389,387,385,383,95,189,47,187,93,185,23,183,91,181,45,179,89,177,11,175,87,173,345,343,341,339,337,21,167,83,331,329,327,163,81,323,321,319,159,79,315,313,39,155,309,307,153,305,303,151,75,299,149,37,295,147,73,291,145,289,287,143,285,71,141,281,35,279,139,69,275,137,273,17,271,135,269,267,133,265,33,263,131,261,130,259,129,257,1],b.shg_table=[0,9,10,11,9,12,10,11,12,9,13,13,10,9,13,13,14,14,14,14,10,13,14,14,14,13,13,13,9,14,14,14,15,14,15,14,15,15,14,15,15,15,14,15,15,15,15,15,14,15,15,15,15,15,15,12,14,15,15,13,15,15,15,15,16,16,16,15,16,14,16,16,14,16,13,16,16,16,15,16,13,16,15,16,14,9,16,16,16,16,16,16,16,16,16,13,14,16,16,15,16,16,10,16,15,16,14,16,16,14,16,16,14,16,16,14,15,16,16,16,14,15,14,15,13,16,16,15,17,17,17,17,17,17,14,15,17,17,16,16,17,16,15,17,16,17,11,17,16,17,16,17,16,17,17,16,17,17,16,17,17,16,16,17,17,17,16,14,17,17,17,17,15,16,14,16,15,16,13,16,15,16,14,16,15,16,12,16,15,16,17,17,17,17,17,13,16,15,17,17,17,16,15,17,17,17,16,15,17,17,14,16,17,17,16,17,17,16,15,17,16,14,17,16,15,17,16,17,17,16,17,15,16,17,14,17,16,15,17,16,17,13,17,16,17,17,16,17,14,17,16,17,16,17,16,17,9],b.getBounds=function(){var a=.5*Math.pow(this.quality,.6);return new createjs.Rectangle(-this.blurX*a,-this.blurY*a,2*this.blurX*a,2*this.blurY*a)},b.applyFilter=function(a,b,c,d,e,f,g,h){f=f||a,null==g&&(g=b),null==h&&(h=c);try{var i=a.getImageData(b,c,d,e)}catch(j){return!1}var k=this.blurX/2;if(isNaN(k)||0>k)return!1;k|=0;var l=this.blurY/2;if(isNaN(l)||0>l)return!1;if(l|=0,0==k&&0==l)return!1;var m=this.quality;(isNaN(m)||1>m)&&(m=1),m|=0,m>3&&(m=3),1>m&&(m=1);var b,c,n,o,p,q,r,s,t,u,v,w,x,y,z,A=i.data,B=k+k+1,C=l+l+1,D=d-1,E=e-1,F=k+1,G=l+1,H={r:0,b:0,g:0,a:0,next:null},I=H;for(n=1;B>n;n++)I=I.next={r:0,b:0,g:0,a:0,next:null};I.next=H;var J={r:0,b:0,g:0,a:0,next:null},K=J;for(n=1;C>n;n++)K=K.next={r:0,b:0,g:0,a:0,next:null};K.next=J;for(var L=null;m-->0;){r=q=0;var M=this.mul_table[k],N=this.shg_table[k];for(c=e;--c>-1;){for(s=F*(w=A[q]),t=F*(x=A[q+1]),u=F*(y=A[q+2]),v=F*(z=A[q+3]),I=H,n=F;--n>-1;)I.r=w,I.g=x,I.b=y,I.a=z,I=I.next;for(n=1;F>n;n++)o=q+((n>D?D:n)<<2),s+=I.r=A[o],t+=I.g=A[o+1],u+=I.b=A[o+2],v+=I.a=A[o+3],I=I.next;for(L=H,b=0;d>b;b++)A[q++]=s*M>>>N,A[q++]=t*M>>>N,A[q++]=u*M>>>N,A[q++]=v*M>>>N,o=r+((o=b+k+1)b;b++){for(q=b<<2,s=G*(w=A[q]),t=G*(x=A[q+1]),u=G*(y=A[q+2]),v=G*(z=A[q+3]),K=J,n=0;G>n;n++)K.r=w,K.g=x,K.b=y,K.a=z,K=K.next;for(p=d,n=1;l>=n;n++)q=p+b<<2,s+=K.r=A[q],t+=K.g=A[q+1],u+=K.b=A[q+2],v+=K.a=A[q+3],K=K.next,E>n&&(p+=d);if(q=b,L=J,m>0)for(c=0;e>c;c++)o=q<<2,A[o+3]=z=v*M>>>N,z>0?(A[o]=s*M>>>N,A[o+1]=t*M>>>N,A[o+2]=u*M>>>N):A[o]=A[o+1]=A[o+2]=0,o=b+((o=c+G)c;c++)o=q<<2,A[o+3]=z=v*M>>>N,z>0?(z=255/z,A[o]=(s*M>>>N)*z,A[o+1]=(t*M>>>N)*z,A[o+2]=(u*M>>>N)*z):A[o]=A[o+1]=A[o+2]=0,o=b+((o=c+G)n;n+=4)k[n+3]=l[n]||0;return f.putImageData(i,g,h),!0},b.clone=function(){return new a(this.alphaMap)},b.toString=function(){return"[AlphaMapFilter]"},b._prepAlphaMap=function(){if(!this.alphaMap)return!1;if(this.alphaMap==this._alphaMap&&this._mapData)return!0;this._mapData=null;var a,b=this._alphaMap=this.alphaMap,c=b;b instanceof HTMLCanvasElement?a=c.getContext("2d"):(c=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"),c.width=b.width,c.height=b.height,a=c.getContext("2d"),a.drawImage(b,0,0));try{var d=a.getImageData(0,0,b.width,b.height)}catch(e){return!1}return this._mapData=d.data,!0},createjs.AlphaMapFilter=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a){this.initialize(a)},b=a.prototype=new createjs.Filter;b.initialize=function(a){this.mask=a},b.mask=null,b.applyFilter=function(a,b,c,d,e,f,g,h){return this.mask?(f=f||a,null==g&&(g=b),null==h&&(h=c),f.save(),f.globalCompositeOperation="destination-in",f.drawImage(this.mask,g,h),f.restore(),!0):!0},b.clone=function(){return new a(this.mask)},b.toString=function(){return"[AlphaMaskFilter]"},createjs.AlphaMaskFilter=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c,d,e,f,g,h){this.initialize(a,b,c,d,e,f,g,h)},b=a.prototype=new createjs.Filter;b.redMultiplier=1,b.greenMultiplier=1,b.blueMultiplier=1,b.alphaMultiplier=1,b.redOffset=0,b.greenOffset=0,b.blueOffset=0,b.alphaOffset=0,b.initialize=function(a,b,c,d,e,f,g,h){this.redMultiplier=null!=a?a:1,this.greenMultiplier=null!=b?b:1,this.blueMultiplier=null!=c?c:1,this.alphaMultiplier=null!=d?d:1,this.redOffset=e||0,this.greenOffset=f||0,this.blueOffset=g||0,this.alphaOffset=h||0},b.applyFilter=function(a,b,c,d,e,f,g,h){f=f||a,null==g&&(g=b),null==h&&(h=c);try{var i=a.getImageData(b,c,d,e)}catch(j){return!1}for(var k=i.data,l=k.length,m=0;l>m;m+=4)k[m]=k[m]*this.redMultiplier+this.redOffset,k[m+1]=k[m+1]*this.greenMultiplier+this.greenOffset,k[m+2]=k[m+2]*this.blueMultiplier+this.blueOffset,k[m+3]=k[m+3]*this.alphaMultiplier+this.alphaOffset;return f.putImageData(i,g,h),!0},b.toString=function(){return"[ColorFilter]"},b.clone=function(){return new a(this.redMultiplier,this.greenMultiplier,this.blueMultiplier,this.alphaMultiplier,this.redOffset,this.greenOffset,this.blueOffset,this.alphaOffset)},createjs.ColorFilter=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c,d){this.initialize(a,b,c,d)},b=a.prototype;a.DELTA_INDEX=[0,.01,.02,.04,.05,.06,.07,.08,.1,.11,.12,.14,.15,.16,.17,.18,.2,.21,.22,.24,.25,.27,.28,.3,.32,.34,.36,.38,.4,.42,.44,.46,.48,.5,.53,.56,.59,.62,.65,.68,.71,.74,.77,.8,.83,.86,.89,.92,.95,.98,1,1.06,1.12,1.18,1.24,1.3,1.36,1.42,1.48,1.54,1.6,1.66,1.72,1.78,1.84,1.9,1.96,2,2.12,2.25,2.37,2.5,2.62,2.75,2.87,3,3.2,3.4,3.6,3.8,4,4.3,4.7,4.9,5,5.5,6,6.5,6.8,7,7.3,7.5,7.8,8,8.4,8.7,9,9.4,9.6,9.8,10],a.IDENTITY_MATRIX=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1],a.LENGTH=a.IDENTITY_MATRIX.length,b.initialize=function(a,b,c,d){return this.reset(),this.adjustColor(a,b,c,d),this},b.reset=function(){return this.copyMatrix(a.IDENTITY_MATRIX)},b.adjustColor=function(a,b,c,d){return this.adjustHue(d),this.adjustContrast(b),this.adjustBrightness(a),this.adjustSaturation(c)},b.adjustBrightness=function(a){return 0==a||isNaN(a)?this:(a=this._cleanValue(a,255),this._multiplyMatrix([1,0,0,0,a,0,1,0,0,a,0,0,1,0,a,0,0,0,1,0,0,0,0,0,1]),this)},b.adjustContrast=function(b){if(0==b||isNaN(b))return this;b=this._cleanValue(b,100);var c;return 0>b?c=127+127*(b/100):(c=b%1,c=0==c?a.DELTA_INDEX[b]:a.DELTA_INDEX[b<<0]*(1-c)+a.DELTA_INDEX[(b<<0)+1]*c,c=127*c+127),this._multiplyMatrix([c/127,0,0,0,.5*(127-c),0,c/127,0,0,.5*(127-c),0,0,c/127,0,.5*(127-c),0,0,0,1,0,0,0,0,0,1]),this},b.adjustSaturation=function(a){if(0==a||isNaN(a))return this;a=this._cleanValue(a,100);var b=1+(a>0?3*a/100:a/100),c=.3086,d=.6094,e=.082;return this._multiplyMatrix([c*(1-b)+b,d*(1-b),e*(1-b),0,0,c*(1-b),d*(1-b)+b,e*(1-b),0,0,c*(1-b),d*(1-b),e*(1-b)+b,0,0,0,0,0,1,0,0,0,0,0,1]),this},b.adjustHue=function(a){if(0==a||isNaN(a))return this;a=this._cleanValue(a,180)/180*Math.PI;var b=Math.cos(a),c=Math.sin(a),d=.213,e=.715,f=.072;return this._multiplyMatrix([d+b*(1-d)+c*-d,e+b*-e+c*-e,f+b*-f+c*(1-f),0,0,d+b*-d+.143*c,e+b*(1-e)+.14*c,f+b*-f+c*-.283,0,0,d+b*-d+c*-(1-d),e+b*-e+c*e,f+b*(1-f)+c*f,0,0,0,0,0,1,0,0,0,0,0,1]),this},b.concat=function(b){return b=this._fixMatrix(b),b.length!=a.LENGTH?this:(this._multiplyMatrix(b),this)},b.clone=function(){return(new a).copyMatrix(this)},b.toArray=function(){for(var b=[],c=0,d=a.LENGTH;d>c;c++)b[c]=this[c];return b},b.copyMatrix=function(b){for(var c=a.LENGTH,d=0;c>d;d++)this[d]=b[d];return this},b.toString=function(){return"[ColorMatrix]"},b._multiplyMatrix=function(a){for(var b=[],c=0;5>c;c++){for(var d=0;5>d;d++)b[d]=this[d+5*c];for(var d=0;5>d;d++){for(var e=0,f=0;5>f;f++)e+=a[d+5*f]*b[f];this[d+5*c]=e}}},b._cleanValue=function(a,b){return Math.min(b,Math.max(-b,a))},b._fixMatrix=function(b){return b instanceof a&&(b=b.toArray()),b.lengtha.LENGTH&&(b=b.slice(0,a.LENGTH)),b},createjs.ColorMatrix=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a){this.initialize(a)},b=a.prototype=new createjs.Filter;b.matrix=null,b.initialize=function(a){this.matrix=a},b.applyFilter=function(a,b,c,d,e,f,g,h){f=f||a,null==g&&(g=b),null==h&&(h=c);try{var i=a.getImageData(b,c,d,e)}catch(j){return!1}for(var k,l,m,n,o=i.data,p=o.length,q=this.matrix,r=q[0],s=q[1],t=q[2],u=q[3],v=q[4],w=q[5],x=q[6],y=q[7],z=q[8],A=q[9],B=q[10],C=q[11],D=q[12],E=q[13],F=q[14],G=q[15],H=q[16],I=q[17],J=q[18],K=q[19],L=0;p>L;L+=4)k=o[L],l=o[L+1],m=o[L+2],n=o[L+3],o[L]=k*r+l*s+m*t+n*u+v,o[L+1]=k*w+l*x+m*y+n*z+A,o[L+2]=k*B+l*C+m*D+n*E+F,o[L+3]=k*G+l*H+m*I+n*J+K;return f.putImageData(i,g,h),!0},b.toString=function(){return"[ColorMatrixFilter]"},b.clone=function(){return new a(this.matrix)},createjs.ColorMatrixFilter=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){throw"Touch cannot be instantiated"};a.isSupported=function(){return"ontouchstart"in window||window.navigator.msPointerEnabled&&window.navigator.msMaxTouchPoints>0||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints>0},a.enable=function(b,c,d){return b&&b.canvas&&a.isSupported()?(b.__touch={pointers:{},multitouch:!c,preventDefault:!d,count:0},"ontouchstart"in window?a._IOS_enable(b):(window.navigator.msPointerEnabled||window.navigator.pointerEnabled)&&a._IE_enable(b),!0):!1},a.disable=function(b){b&&("ontouchstart"in window?a._IOS_disable(b):(window.navigator.msPointerEnabled||window.navigator.pointerEnabled)&&a._IE_disable(b))},a._IOS_enable=function(b){var c=b.canvas,d=b.__touch.f=function(c){a._IOS_handleEvent(b,c)};c.addEventListener("touchstart",d,!1),c.addEventListener("touchmove",d,!1),c.addEventListener("touchend",d,!1),c.addEventListener("touchcancel",d,!1)},a._IOS_disable=function(a){var b=a.canvas;if(b){var c=a.__touch.f;b.removeEventListener("touchstart",c,!1),b.removeEventListener("touchmove",c,!1),b.removeEventListener("touchend",c,!1),b.removeEventListener("touchcancel",c,!1)}},a._IOS_handleEvent=function(a,b){if(a){a.__touch.preventDefault&&b.preventDefault&&b.preventDefault();for(var c=b.changedTouches,d=b.type,e=0,f=c.length;f>e;e++){var g=c[e],h=g.identifier;g.target==a.canvas&&("touchstart"==d?this._handleStart(a,h,b,g.pageX,g.pageY):"touchmove"==d?this._handleMove(a,h,b,g.pageX,g.pageY):("touchend"==d||"touchcancel"==d)&&this._handleEnd(a,h,b))}}},a._IE_enable=function(b){var c=b.canvas,d=b.__touch.f=function(c){a._IE_handleEvent(b,c)};void 0===window.navigator.pointerEnabled?(c.addEventListener("MSPointerDown",d,!1),window.addEventListener("MSPointerMove",d,!1),window.addEventListener("MSPointerUp",d,!1),window.addEventListener("MSPointerCancel",d,!1),b.__touch.preventDefault&&(c.style.msTouchAction="none")):(c.addEventListener("pointerdown",d,!1),window.addEventListener("pointermove",d,!1),window.addEventListener("pointerup",d,!1),window.addEventListener("pointercancel",d,!1),b.__touch.preventDefault&&(c.style.touchAction="none")),b.__touch.activeIDs={}},a._IE_disable=function(a){var b=a.__touch.f;void 0===window.navigator.pointerEnabled?(window.removeEventListener("MSPointerMove",b,!1),window.removeEventListener("MSPointerUp",b,!1),window.removeEventListener("MSPointerCancel",b,!1),a.canvas&&a.canvas.removeEventListener("MSPointerDown",b,!1)):(window.removeEventListener("pointermove",b,!1),window.removeEventListener("pointerup",b,!1),window.removeEventListener("pointercancel",b,!1),a.canvas&&a.canvas.removeEventListener("pointerdown",b,!1))},a._IE_handleEvent=function(a,b){if(a){a.__touch.preventDefault&&b.preventDefault&&b.preventDefault();var c=b.type,d=b.pointerId,e=a.__touch.activeIDs;if("MSPointerDown"==c||"pointerdown"==c){if(b.srcElement!=a.canvas)return;e[d]=!0,this._handleStart(a,d,b,b.pageX,b.pageY)}else e[d]&&("MSPointerMove"==c||"pointermove"==c?this._handleMove(a,d,b,b.pageX,b.pageY):("MSPointerUp"==c||"MSPointerCancel"==c||"pointerup"==c||"pointercancel"==c)&&(delete e[d],this._handleEnd(a,d,b)))}},a._handleStart=function(a,b,c,d,e){var f=a.__touch;if(f.multitouch||!f.count){var g=f.pointers;g[b]||(g[b]=!0,f.count++,a._handlePointerDown(b,c,d,e))}},a._handleMove=function(a,b,c,d,e){a.__touch.pointers[b]&&a._handlePointerMove(b,c,d,e)},a._handleEnd=function(a,b,c){var d=a.__touch,e=d.pointers;e[b]&&(d.count--,a._handlePointerUp(b,c,!0),delete e[b])},createjs.Touch=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=createjs.EaselJS=createjs.EaselJS||{};a.version="NEXT",a.buildDate="Thu, 12 Dec 2013 23:37:07 GMT"}(); \ No newline at end of file diff --git a/examples/assets/manifest.json b/examples/assets/manifest.json deleted file mode 100644 index df6d399c..00000000 --- a/examples/assets/manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "basePath": "assets/", - "manifest": [ - "image0.jpg", - "image1.jpg", - "image2.jpg", - "image3.jpg", - { "src": "font.css" }, - { "src":"manifest.json", "type":"manifest" } - ] -} \ No newline at end of file diff --git a/examples/assets/soundjs-NEXT.min.js b/examples/assets/soundjs-NEXT.min.js deleted file mode 100644 index e7fdcf95..00000000 --- a/examples/assets/soundjs-NEXT.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! -* @license SoundJS -* Visit http://createjs.com/ for documentation, updates and examples. -* -* Copyright (c) 2011-2013 gskinner.com, inc. -* -* Distributed under the terms of the MIT license. -* http://www.opensource.org/licenses/mit-license.html -* -* This notice shall be included in all copies or substantial portions of the Software. -*/ - -/**! - * SoundJS FlashPlugin also includes swfobject (http://code.google.com/p/swfobject/) - */ - -this.createjs=this.createjs||{},function(){var a=createjs.SoundJS=createjs.SoundJS||{};a.version="NEXT",a.buildDate="Thu, 12 Dec 2013 23:37:06 GMT"}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){},b=a.prototype;a.initialize=function(a){a.addEventListener=b.addEventListener,a.on=b.on,a.removeEventListener=a.off=b.removeEventListener,a.removeAllEventListeners=b.removeAllEventListeners,a.hasEventListener=b.hasEventListener,a.dispatchEvent=b.dispatchEvent,a._dispatchEvent=b._dispatchEvent,a.willTrigger=b.willTrigger},b._listeners=null,b._captureListeners=null,b.initialize=function(){},b.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},b.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},b.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},b.off=b.removeEventListener,b.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},b.dispatchEvent=function(a,b){if("string"==typeof a){var c=this._listeners;if(!c||!c[a])return!1;a=new createjs.Event(a)}if(a.target=b||this,a.bubbles&&this.parent){for(var d=this,e=[d];d.parent;)e.push(d=d.parent);var f,g=e.length;for(f=g-1;f>=0&&!a.propagationStopped;f--)e[f]._dispatchEvent(a,1+(0==f));for(f=1;g>f&&!a.propagationStopped;f++)e[f]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return a.defaultPrevented},b.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},b.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},b.toString=function(){return"[EventDispatcher]"},b._dispatchEvent=function(a,b){var c,d=1==b?this._captureListeners:this._listeners;if(a&&d){var e=d[a.type];if(!e||!(c=e.length))return;a.currentTarget=this,a.eventPhase=b,a.removed=!1,e=e.slice();for(var f=0;c>f&&!a.immediatePropagationStopped;f++){var g=e[f];g.handleEvent?g.handleEvent(a):g(a),a.removed&&(this.off(a.type,g,1==b),a.removed=!1)}}},createjs.EventDispatcher=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c){this.initialize(a,b,c)},b=a.prototype;b.type=null,b.target=null,b.currentTarget=null,b.eventPhase=0,b.bubbles=!1,b.cancelable=!1,b.timeStamp=0,b.defaultPrevented=!1,b.propagationStopped=!1,b.immediatePropagationStopped=!1,b.removed=!1,b.initialize=function(a,b,c){this.type=a,this.bubbles=b,this.cancelable=c,this.timeStamp=(new Date).getTime()},b.preventDefault=function(){this.defaultPrevented=!0},b.stopPropagation=function(){this.propagationStopped=!0},b.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},b.remove=function(){this.removed=!0},b.clone=function(){return new a(this.type,this.bubbles,this.cancelable)},b.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=a}(),this.createjs=this.createjs||{},function(){"use strict";createjs.indexOf=function(a,b){for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1}}(),this.createjs=this.createjs||{},function(){"use strict";createjs.proxy=function(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){return a.apply(b,Array.prototype.slice.call(arguments,0).concat(c))}}}(),this.createjs=this.createjs||{},function(){"use strict";function a(){throw"Sound cannot be instantiated"}function b(a,b){this.init(a,b)}function c(){this.isDefault=!0,this.addEventListener=this.removeEventListener=this.removeAllEventListeners=this.dispatchEvent=this.hasEventListener=this._listeners=this._interrupt=this._playFailed=this.pause=this.resume=this.play=this._beginPlaying=this._cleanUp=this.stop=this.setMasterVolume=this.setVolume=this.mute=this.setMute=this.getMute=this.setPan=this.getPosition=this.setPosition=this.playFailed=function(){return!1},this.getVolume=this.getPan=this.getDuration=function(){return 0},this.playState=a.PLAY_FAILED,this.toString=function(){return"[Sound Default Sound Instance]"}}function d(){}var e=a;e.DELIMITER="|",e.INTERRUPT_ANY="any",e.INTERRUPT_EARLY="early",e.INTERRUPT_LATE="late",e.INTERRUPT_NONE="none",e.PLAY_INITED="playInited",e.PLAY_SUCCEEDED="playSucceeded",e.PLAY_INTERRUPTED="playInterrupted",e.PLAY_FINISHED="playFinished",e.PLAY_FAILED="playFailed",e.SUPPORTED_EXTENSIONS=["mp3","ogg","mpeg","wav","m4a","mp4","aiff","wma","mid"],e.EXTENSION_MAP={m4a:"mp4"},e.FILE_PATTERN=/^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/,e.defaultInterruptBehavior=e.INTERRUPT_NONE,e.alternateExtensions=[],e._lastID=0,e.activePlugin=null,e._pluginsRegistered=!1,e._masterVolume=1,e._masterMute=!1,e._instances=[],e._idHash={},e._preloadHash={},e._defaultSoundInstance=null,e.addEventListener=null,e.removeEventListener=null,e.removeAllEventListeners=null,e.dispatchEvent=null,e.hasEventListener=null,e._listeners=null,createjs.EventDispatcher.initialize(e),e._sendFileLoadEvent=function(a){if(e._preloadHash[a])for(var b=0,c=e._preloadHash[a].length;c>b;b++){var d=e._preloadHash[a][b];if(e._preloadHash[a][b]=!0,e.hasEventListener("fileload")){var f=new createjs.Event("fileload");f.src=d.src,f.id=d.id,f.data=d.data,e.dispatchEvent(f)}}},e.getPreloadHandlers=function(){return{callback:createjs.proxy(e.initLoad,e),types:["sound"],extensions:e.SUPPORTED_EXTENSIONS}},e.registerPlugin=function(a){try{console.log("createjs.Sound.registerPlugin has been deprecated. Please use registerPlugins.")}catch(b){}return e._registerPlugin(a)},e._registerPlugin=function(a){return e._pluginsRegistered=!0,null==a?!1:a.isSupported()?(e.activePlugin=new a,!0):!1},e.registerPlugins=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];if(e._registerPlugin(d))return!0}return!1},e.initializeDefaultPlugins=function(){return null!=e.activePlugin?!0:e._pluginsRegistered?!1:e.registerPlugins([createjs.WebAudioPlugin,createjs.HTMLAudioPlugin])?!0:!1},e.isReady=function(){return null!=e.activePlugin},e.getCapabilities=function(){return null==e.activePlugin?null:e.activePlugin._capabilities},e.getCapability=function(a){return null==e.activePlugin?null:e.activePlugin._capabilities[a]},e.initLoad=function(a,b,c,d,f){a=a.replace(f,"");var g=e.registerSound(a,c,d,!1,f);return null==g?!1:g},e.registerSound=function(a,c,d,f,g){if(!e.initializeDefaultPlugins())return!1;if(a instanceof Object&&(g=c,c=a.id,d=a.data,a=a.src),e.alternateExtensions.length)var h=e._parsePath2(a,"sound",c,d);else var h=e._parsePath(a,"sound",c,d);if(null==h)return!1;null!=g&&(a=g+a,h.src=g+h.src),null!=c&&(e._idHash[c]=h.src);var i=null;null!=d&&(isNaN(d.channels)?isNaN(d)||(i=parseInt(d)):i=parseInt(d.channels));var j=e.activePlugin.register(h.src,i);if(null!=j&&(null!=j.numChannels&&(i=j.numChannels),b.create(h.src,i),null!=d&&isNaN(d)?d.channels=h.data.channels=i||b.maxPerChannel():d=h.data=i||b.maxPerChannel(),null!=j.tag?h.tag=j.tag:j.src&&(h.src=j.src),null!=j.completeHandler&&(h.completeHandler=j.completeHandler),j.type&&(h.type=j.type)),0!=f)if(e._preloadHash[h.src]||(e._preloadHash[h.src]=[]),e._preloadHash[h.src].push({src:a,id:c,data:d}),1==e._preloadHash[h.src].length)e.activePlugin.preload(h.src,j);else if(1==e._preloadHash[h.src][0])return!0;return h},e.registerManifest=function(a,b){for(var c=[],d=0,e=a.length;e>d;d++)c[d]=createjs.Sound.registerSound(a[d].src,a[d].id,a[d].data,a[d].preload,b);return c},e.removeSound=function(a,c){if(null==e.activePlugin)return!1;if(a instanceof Object&&(a=a.src),a=e._getSrcById(a),e.alternateExtensions.length)var d=e._parsePath2(a);else var d=e._parsePath(a);if(null==d)return!1;null!=c&&(d.src=c+d.src),a=d.src;for(var f in e._idHash)e._idHash[f]==a&&delete e._idHash[f];return b.removeSrc(a),delete e._preloadHash[a],e.activePlugin.removeSound(a),!0},e.removeManifest=function(a,b){for(var c=[],d=0,e=a.length;e>d;d++)c[d]=createjs.Sound.removeSound(a[d].src,b);return c},e.removeAllSounds=function(){e._idHash={},e._preloadHash={},b.removeAll(),e.activePlugin.removeAllSounds()},e.loadComplete=function(a){if(e.alternateExtensions.length)var b=e._parsePath2(a,"sound");else var b=e._parsePath(a,"sound");return a=b?e._getSrcById(b.src):e._getSrcById(a),1==e._preloadHash[a][0]},e._parsePath=function(a,b,c,d){"string"!=typeof a&&(a=a.toString());var f=a.split(e.DELIMITER);if(f.length>1)try{console.log('createjs.Sound.DELIMITER "|" loading approach has been deprecated. Please use the new alternateExtensions property.')}catch(g){}for(var h={type:b||"sound",id:c,data:d},i=e.getCapabilities(),j=0,k=f.length;k>j;j++){var l=f[j],m=l.match(e.FILE_PATTERN);if(null==m)return!1;var n=m[4],o=m[5];if(i[o]&&createjs.indexOf(e.SUPPORTED_EXTENSIONS,o)>-1)return h.name=n,h.src=l,h.extension=o,h}return null},e._parsePath2=function(a,b,c,d){"string"!=typeof a&&(a=a.toString());var f=a.match(e.FILE_PATTERN);if(null==f)return!1;for(var g=f[4],h=f[5],i=e.getCapabilities(),j=0;!i[h];)if(h=e.alternateExtensions[j++],j>e.alternateExtensions.length)return null;a=a.replace("."+f[5],"."+h);var k={type:b||"sound",id:c,data:d};return k.name=g,k.src=a,k.extension=h,k},e.play=function(a,b,c,d,f,g,h){var i=e.createInstance(a),j=e._playInstance(i,b,c,d,f,g,h);return j||i.playFailed(),i},e.createInstance=function(c){if(!e.initializeDefaultPlugins())return e._defaultSoundInstance;if(c=e._getSrcById(c),e.alternateExtensions.length)var d=e._parsePath2(c,"sound");else var d=e._parsePath(c,"sound");var f=null;return null!=d&&null!=d.src?(b.create(d.src),f=e.activePlugin.create(d.src)):f=a._defaultSoundInstance,f.uniqueId=e._lastID++,f},e.setVolume=function(a){if(null==Number(a))return!1;if(a=Math.max(0,Math.min(1,a)),e._masterVolume=a,!this.activePlugin||!this.activePlugin.setVolume||!this.activePlugin.setVolume(a))for(var b=this._instances,c=0,d=b.length;d>c;c++)b[c].setMasterVolume(a)},e.getVolume=function(){return e._masterVolume},e.setMute=function(a){if(null==a||void 0==a)return!1;if(this._masterMute=a,!this.activePlugin||!this.activePlugin.setMute||!this.activePlugin.setMute(a))for(var b=this._instances,c=0,d=b.length;d>c;c++)b[c].setMasterMute(a);return!0},e.getMute=function(){return this._masterMute},e.stop=function(){for(var a=this._instances,b=a.length;b--;)a[b].stop()},e._playInstance=function(a,b,c,d,f,g,h){if(b instanceof Object&&(c=b.delay,d=b.offset,f=b.loop,g=b.volume,h=b.pan,b=b.interrupt),b=b||e.defaultInterruptBehavior,null==c&&(c=0),null==d&&(d=a.getPosition()),null==f&&(f=0),null==g&&(g=a.volume),null==h&&(h=a.pan),0==c){var i=e._beginPlaying(a,b,d,f,g,h);if(!i)return!1}else{var j=setTimeout(function(){e._beginPlaying(a,b,d,f,g,h)},c);a._delayTimeoutId=j}return this._instances.push(a),!0},e._beginPlaying=function(a,c,d,e,f,g){if(!b.add(a,c))return!1;var h=a._beginPlaying(d,e,f,g);if(!h){var i=createjs.indexOf(this._instances,a);return i>-1&&this._instances.splice(i,1),!1}return!0},e._getSrcById=function(a){return null==e._idHash||null==e._idHash[a]?a:e._idHash[a]},e._playFinished=function(a){b.remove(a);var c=createjs.indexOf(this._instances,a);c>-1&&this._instances.splice(c,1)},createjs.Sound=a,b.channels={},b.create=function(a,c){var d=b.get(a);return null==d?(b.channels[a]=new b(a,c),!0):!1},b.removeSrc=function(a){var c=b.get(a);return null==c?!1:(c.removeAll(),delete b.channels[a],!0)},b.removeAll=function(){for(var a in b.channels)b.channels[a].removeAll();b.channels={}},b.add=function(a,c){var d=b.get(a.src);return null==d?!1:d.add(a,c)},b.remove=function(a){var c=b.get(a.src);return null==c?!1:(c.remove(a),!0)},b.maxPerChannel=function(){return f.maxDefault},b.get=function(a){return b.channels[a]};var f=b.prototype;f.src=null,f.max=null,f.maxDefault=100,f.length=0,f.init=function(a,b){this.src=a,this.max=b||this.maxDefault,-1==this.max&&(this.max=this.maxDefault),this._instances=[]},f.get=function(a){return this._instances[a]},f.add=function(a,b){return this.getSlot(b,a)?(this._instances.push(a),this.length++,!0):!1},f.remove=function(a){var b=createjs.indexOf(this._instances,a);return-1==b?!1:(this._instances.splice(b,1),this.length--,!0)},f.removeAll=function(){for(var a=this.length-1;a>=0;a--)this._instances[a].stop()},f.getSlot=function(b){for(var c,d,e=0,f=this.max;f>e;e++){if(c=this.get(e),null==c)return!0;(b!=a.INTERRUPT_NONE||c.playState==a.PLAY_FINISHED)&&(0!=e?c.playState==a.PLAY_FINISHED||c.playState==a.PLAY_INTERRUPTED||c.playState==a.PLAY_FAILED?d=c:(b==a.INTERRUPT_EARLY&&c.getPosition()d.getPosition())&&(d=c):d=c)}return null!=d?(d._interrupt(),this.remove(d),!0):!1},f.toString=function(){return"[Sound SoundChannel]"},a._defaultSoundInstance=new c,d.init=function(){var a=window.navigator.userAgent;d.isFirefox=a.indexOf("Firefox")>-1,d.isOpera=null!=window.opera,d.isChrome=a.indexOf("Chrome")>-1,d.isIOS=a.indexOf("iPod")>-1||a.indexOf("iPhone")>-1||a.indexOf("iPad")>-1,d.isAndroid=a.indexOf("Android")>-1,d.isBlackberry=a.indexOf("Blackberry")>-1},d.init(),createjs.Sound.BrowserDetect=d}(),this.createjs=this.createjs||{},function(){"use strict";function a(){this._init()}var b=a;b._capabilities=null,b.isSupported=function(){var a=createjs.Sound.BrowserDetect.isIOS||createjs.Sound.BrowserDetect.isAndroid||createjs.Sound.BrowserDetect.isBlackberry;return"file:"!=location.protocol||a||this._isFileXHRSupported()?(b._generateCapabilities(),null==b.context?!1:!0):!1},b._isFileXHRSupported=function(){var a=!0,b=new XMLHttpRequest;try{b.open("GET","fail.fail",!1)}catch(c){return a=!1}b.onerror=function(){a=!1},b.onload=function(){a=404==this.status||200==this.status||0==this.status&&""!=this.response};try{b.send()}catch(c){a=!1}return a},b._generateCapabilities=function(){if(null==b._capabilities){var a=document.createElement("audio");if(null==a.canPlayType)return null;if(window.webkitAudioContext)b.context=new webkitAudioContext;else{if(!window.AudioContext)return null;b.context=new AudioContext}b._compatibilitySetUp(),b.playEmptySound(),b._capabilities={panning:!0,volume:!0,tracks:-1};for(var c=createjs.Sound.SUPPORTED_EXTENSIONS,d=createjs.Sound.EXTENSION_MAP,e=0,f=c.length;f>e;e++){var g=c[e],h=d[g]||g;b._capabilities[g]="no"!=a.canPlayType("audio/"+g)&&""!=a.canPlayType("audio/"+g)||"no"!=a.canPlayType("audio/"+h)&&""!=a.canPlayType("audio/"+h)}b.context.destination.numberOfChannels<2&&(b._capabilities.panning=!1),b.dynamicsCompressorNode=b.context.createDynamicsCompressor(),b.dynamicsCompressorNode.connect(b.context.destination),b.gainNode=b.context.createGain(),b.gainNode.connect(b.dynamicsCompressorNode)}},b._compatibilitySetUp=function(){if(!b.context.createGain){b.context.createGain=b.context.createGainNode;var a=b.context.createBufferSource();a.__proto__.start=a.__proto__.noteGrainOn,a.__proto__.stop=a.__proto__.noteOff,this._panningModel=0}},b.playEmptySound=function(){var a=this.context.createBuffer(1,1,22050),b=this.context.createBufferSource();b.buffer=a,b.connect(this.context.destination),b.start(0,0,0)};var c=a.prototype;c._capabilities=null,c._volume=1,c.context=null,c._panningModel="equalpower",c.dynamicsCompressorNode=null,c.gainNode=null,c._arrayBuffers=null,c._init=function(){this._capabilities=b._capabilities,this._arrayBuffers={},this.context=b.context,this.gainNode=b.gainNode,this.dynamicsCompressorNode=b.dynamicsCompressorNode},c.register=function(a){this._arrayBuffers[a]=!0;var b=new createjs.WebAudioPlugin.Loader(a,this);return{tag:b}},c.isPreloadStarted=function(a){return null!=this._arrayBuffers[a]},c.isPreloadComplete=function(a){return!(null==this._arrayBuffers[a]||1==this._arrayBuffers[a])},c.removeSound=function(a){delete this._arrayBuffers[a]},c.removeAllSounds=function(){this._arrayBuffers={}},c.addPreloadResults=function(a,b){this._arrayBuffers[a]=b},c._handlePreloadComplete=function(){createjs.Sound._sendFileLoadEvent(this.src)},c.preload=function(a){this._arrayBuffers[a]=!0;var b=new createjs.WebAudioPlugin.Loader(a,this);b.onload=this._handlePreloadComplete,b.load()},c.create=function(a){return this.isPreloadStarted(a)||this.preload(a),new createjs.WebAudioPlugin.SoundInstance(a,this)},c.setVolume=function(a){return this._volume=a,this._updateVolume(),!0},c._updateVolume=function(){var a=createjs.Sound._masterMute?0:this._volume;a!=this.gainNode.gain.value&&(this.gainNode.gain.value=a)},c.getVolume=function(){return this._volume},c.setMute=function(){return this._updateVolume(),!0},c.toString=function(){return"[WebAudioPlugin]"},createjs.WebAudioPlugin=a}(),function(){"use strict";function a(a,b){this._init(a,b)}var b=a.prototype=new createjs.EventDispatcher;b.src=null,b.uniqueId=-1,b.playState=null,b._owner=null,b._offset=0,b._delay=0,b._volume=1;try{Object.defineProperty(b,"volume",{get:function(){return this._volume},set:function(a){return null==Number(a)?!1:(a=Math.max(0,Math.min(1,a)),this._volume=a,this._updateVolume(),void 0)}})}catch(c){}b._pan=0;try{Object.defineProperty(b,"pan",{get:function(){return this._pan},set:function(a){return this._owner._capabilities.panning&&null!=Number(a)?(a=Math.max(-1,Math.min(1,a)),this._pan=a,this.panNode.setPosition(a,0,-.5),void 0):!1}})}catch(c){}b._duration=0,b._remainingLoops=0,b._delayTimeoutId=null,b._soundCompleteTimeout=null,b.gainNode=null,b.panNode=null,b.sourceNode=null,b._sourceNodeNext=null,b._muted=!1,b._paused=!1,b._startTime=0,b._endedHandler=null,b._sendEvent=function(a){var b=new createjs.Event(a);this.dispatchEvent(b)},b._init=function(a,b){this._owner=b,this.src=a,this.gainNode=this._owner.context.createGain(),this.panNode=this._owner.context.createPanner(),this.panNode.panningModel=this._owner._panningModel,this.panNode.connect(this.gainNode),this._owner.isPreloadComplete(this.src)&&(this._duration=1e3*this._owner._arrayBuffers[this.src].duration),this._endedHandler=createjs.proxy(this._handleSoundComplete,this)},b._cleanUp=function(){this.sourceNode&&this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this.sourceNode=this._cleanUpAudioNode(this.sourceNode),this._sourceNodeNext=this._cleanUpAudioNode(this._sourceNodeNext)),0!=this.gainNode.numberOfOutputs&&this.gainNode.disconnect(0),clearTimeout(this._delayTimeoutId),clearTimeout(this._soundCompleteTimeout),this._startTime=0,null!=window.createjs&&createjs.Sound._playFinished(this)},b._cleanUpAudioNode=function(a){return a&&(a.stop(0),a.disconnect(this.panNode),a=null),a},b._interrupt=function(){this._cleanUp(),this.playState=createjs.Sound.PLAY_INTERRUPTED,this._paused=!1,this._sendEvent("interrupted")},b._handleSoundReady=function(){if(null!=window.createjs){if(1e3*this._offset>this.getDuration())return this.playFailed(),void 0;this._offset<0&&(this._offset=0),this.playState=createjs.Sound.PLAY_SUCCEEDED,this._paused=!1,this.gainNode.connect(this._owner.gainNode);var a=this._owner._arrayBuffers[this.src].duration;this.sourceNode=this._createAndPlayAudioNode(this._owner.context.currentTime-a,this._offset),this._duration=1e3*a,this._startTime=this.sourceNode.startTime-this._offset,this._soundCompleteTimeout=setTimeout(this._endedHandler,1e3*(a-this._offset)),0!=this._remainingLoops&&(this._sourceNodeNext=this._createAndPlayAudioNode(this._startTime,0))}},b._createAndPlayAudioNode=function(a,b){var c=this._owner.context.createBufferSource();return c.buffer=this._owner._arrayBuffers[this.src],c.connect(this.panNode),this._owner.context.currentTime,c.startTime=a+c.buffer.duration,c.start(c.startTime,b,c.buffer.duration-b),c},b.play=function(a,b,c,d,e,f){this._cleanUp(),createjs.Sound._playInstance(this,a,b,c,d,e,f)},b._beginPlaying=function(a,b,c,d){return null!=window.createjs&&this.src?(this._offset=a/1e3,this._remainingLoops=b,this.volume=c,this.pan=d,this._owner.isPreloadComplete(this.src)?(this._handleSoundReady(null),this._sendEvent("succeeded"),1):(this.playFailed(),void 0)):void 0},b.pause=function(){return this._paused||this.playState!=createjs.Sound.PLAY_SUCCEEDED?!1:(this._paused=!0,this._offset=this._owner.context.currentTime-this._startTime,this._cleanUpAudioNode(this.sourceNode),this._cleanUpAudioNode(this._sourceNodeNext),0!=this.gainNode.numberOfOutputs&&this.gainNode.disconnect(),clearTimeout(this._delayTimeoutId),clearTimeout(this._soundCompleteTimeout),!0)},b.resume=function(){return this._paused?(this._handleSoundReady(null),!0):!1},b.stop=function(){return this._cleanUp(),this.playState=createjs.Sound.PLAY_FINISHED,this._offset=0,!0},b.setVolume=function(a){return this.volume=a,!0},b._updateVolume=function(){var a=this._muted?0:this._volume;return a!=this.gainNode.gain.value?(this.gainNode.gain.value=a,!0):!1},b.getVolume=function(){return this.volume},b.setMute=function(a){return null==a||void 0==a?!1:(this._muted=a,this._updateVolume(),!0)},b.getMute=function(){return this._muted},b.setPan=function(a){return this.pan=a,this.pan!=a?!1:void 0},b.getPan=function(){return this.pan},b.getPosition=function(){if(this._paused||null==this.sourceNode)var a=this._offset;else var a=this._owner.context.currentTime-this._startTime;return 1e3*a},b.setPosition=function(a){return this._offset=a/1e3,this.sourceNode&&this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this._cleanUpAudioNode(this.sourceNode),this._cleanUpAudioNode(this._sourceNodeNext),clearTimeout(this._soundCompleteTimeout)),this._paused||this.playState!=createjs.Sound.PLAY_SUCCEEDED||this._handleSoundReady(null),!0},b.getDuration=function(){return this._duration},b._handleSoundComplete=function(){return this._offset=0,0!=this._remainingLoops?(this._remainingLoops--,this._sourceNodeNext?(this._cleanUpAudioNode(this.sourceNode),this.sourceNode=this._sourceNodeNext,this._startTime=this.sourceNode.startTime,this._sourceNodeNext=this._createAndPlayAudioNode(this._startTime,0),this._soundCompleteTimeout=setTimeout(this._endedHandler,this._duration)):this._handleSoundReady(null),this._sendEvent("loop"),void 0):(null!=window.createjs&&(this._cleanUp(),this.playState=createjs.Sound.PLAY_FINISHED,this._sendEvent("complete")),void 0)},b.playFailed=function(){null!=window.createjs&&(this._cleanUp(),this.playState=createjs.Sound.PLAY_FAILED,this._sendEvent("failed"))},b.toString=function(){return"[WebAudioPlugin SoundInstance]"},createjs.WebAudioPlugin.SoundInstance=a}(),function(){"use strict";function a(a,b){this._init(a,b)}var b=a.prototype;b.request=null,b.owner=null,b.progress=-1,b.src=null,b.originalSrc=null,b.result=null,b.onload=null,b.onprogress=null,b.onError=null,b._init=function(a,b){this.src=a,this.originalSrc=a,this.owner=b},b.load=function(a){null!=a&&(this.src=a),this.request=new XMLHttpRequest,this.request.open("GET",this.src,!0),this.request.responseType="arraybuffer",this.request.onload=createjs.proxy(this.handleLoad,this),this.request.onError=createjs.proxy(this.handleError,this),this.request.onprogress=createjs.proxy(this.handleProgress,this),this.request.send()},b.handleProgress=function(a,b){this.progress=a/b,null!=this.onprogress&&this.onprogress({loaded:a,total:b,progress:this.progress})},b.handleLoad=function(){this.owner.context.decodeAudioData(this.request.response,createjs.proxy(this.handleAudioDecoded,this),createjs.proxy(this.handleError,this))},b.handleAudioDecoded=function(a){this.progress=1,this.result=a,this.src=this.originalSrc,this.owner.addPreloadResults(this.src,this.result),this.onload&&this.onload()},b.handleError=function(a){this.owner.removeSound(this.src),this.onerror&&this.onerror(a)},b.toString=function(){return"[WebAudioPlugin Loader]"},createjs.WebAudioPlugin.Loader=a}(),this.createjs=this.createjs||{},function(){"use strict";function a(){this._init()}var b=a;b.MAX_INSTANCES=30,b._AUDIO_READY="canplaythrough",b._AUDIO_ENDED="ended",b._AUDIO_SEEKED="seeked",b._AUDIO_STALLED="stalled",b._capabilities=null,b.enableIOS=!1,b.isSupported=function(){if(createjs.Sound.BrowserDetect.isIOS&&!b.enableIOS)return!1;b._generateCapabilities();var a=b.tag;return null==a||null==b._capabilities?!1:!0},b._generateCapabilities=function(){if(null==b._capabilities){var a=b.tag=document.createElement("audio");if(null==a.canPlayType)return null;b._capabilities={panning:!0,volume:!0,tracks:-1};for(var c=createjs.Sound.SUPPORTED_EXTENSIONS,d=createjs.Sound.EXTENSION_MAP,e=0,f=c.length;f>e;e++){var g=c[e],h=d[g]||g;b._capabilities[g]="no"!=a.canPlayType("audio/"+g)&&""!=a.canPlayType("audio/"+g)||"no"!=a.canPlayType("audio/"+h)&&""!=a.canPlayType("audio/"+h)}}};var c=a.prototype;c._capabilities=null,c._audioSources=null,c.defaultNumChannels=2,c.loadedHandler=null,c._init=function(){this._capabilities=b._capabilities,this._audioSources={}},c.register=function(a,b){this._audioSources[a]=!0;for(var c=createjs.HTMLAudioPlugin.TagPool.get(a),d=null,e=b||this.defaultNumChannels,f=0;e>f;f++)d=this._createTag(a),c.add(d);if(d.id=a,this.loadedHandler=createjs.proxy(this._handleTagLoad,this),d.addEventListener&&d.addEventListener("canplaythrough",this.loadedHandler),null==d.onreadystatechange)d.onreadystatechange=this.loadedHandler;else{var g=d.onreadystatechange;d.onreadystatechange=function(){g(),this.loadedHandler()}}return{tag:d,numChannels:e}},c._handleTagLoad=function(a){a.target.removeEventListener&&a.target.removeEventListener("canplaythrough",this.loadedHandler),a.target.onreadystatechange=null,a.target.src!=a.target.id&&createjs.HTMLAudioPlugin.TagPool.checkSrc(a.target.id)},c._createTag=function(a){var b=document.createElement("audio");return b.autoplay=!1,b.preload="none",b.src=a,b},c.removeSound=function(a){delete this._audioSources[a],createjs.HTMLAudioPlugin.TagPool.remove(a)},c.removeAllSounds=function(){this._audioSources={},createjs.HTMLAudioPlugin.TagPool.removeAll()},c.create=function(a){if(!this.isPreloadStarted(a)){var b=createjs.HTMLAudioPlugin.TagPool.get(a),c=this._createTag(a);c.id=a,b.add(c),this.preload(a,{tag:c})}return new createjs.HTMLAudioPlugin.SoundInstance(a,this)},c.isPreloadStarted=function(a){return null!=this._audioSources[a]},c.preload=function(a,b){this._audioSources[a]=!0,new createjs.HTMLAudioPlugin.Loader(a,b.tag)},c.toString=function(){return"[HTMLAudioPlugin]"},createjs.HTMLAudioPlugin=a}(),function(){"use strict";function a(a,b){this._init(a,b)}var b=a.prototype=new createjs.EventDispatcher;b.src=null,b.uniqueId=-1,b.playState=null,b._owner=null,b.loaded=!1,b._offset=0,b._delay=0,b._volume=1;try{Object.defineProperty(b,"volume",{get:function(){return this._volume},set:function(a){null!=Number(a)&&(a=Math.max(0,Math.min(1,a)),this._volume=a,this._updateVolume())}})}catch(c){}b.pan=0,b._duration=0,b._remainingLoops=0,b._delayTimeoutId=null,b.tag=null,b._muted=!1,b._paused=!1,b._endedHandler=null,b._readyHandler=null,b._stalledHandler=null,b.loopHandler=null,b._init=function(a,b){this.src=a,this._owner=b,this._endedHandler=createjs.proxy(this._handleSoundComplete,this),this._readyHandler=createjs.proxy(this._handleSoundReady,this),this._stalledHandler=createjs.proxy(this._handleSoundStalled,this),this.loopHandler=createjs.proxy(this.handleSoundLoop,this)},b._sendEvent=function(a){var b=new createjs.Event(a);this.dispatchEvent(b)},b._cleanUp=function(){var a=this.tag;if(null!=a){a.pause(),a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED,this._endedHandler,!1),a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_READY,this._readyHandler,!1),a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this.loopHandler,!1);try{a.currentTime=0}catch(b){}createjs.HTMLAudioPlugin.TagPool.setInstance(this.src,a),this.tag=null}clearTimeout(this._delayTimeoutId),null!=window.createjs&&createjs.Sound._playFinished(this)},b._interrupt=function(){null!=this.tag&&(this.playState=createjs.Sound.PLAY_INTERRUPTED,this._cleanUp(),this._paused=!1,this._sendEvent("interrupted"))},b.play=function(a,b,c,d,e,f){this._cleanUp(),createjs.Sound._playInstance(this,a,b,c,d,e,f)},b._beginPlaying=function(a,b,c,d){if(null==window.createjs)return-1;var e=this.tag=createjs.HTMLAudioPlugin.TagPool.getInstance(this.src);return null==e?(this.playFailed(),-1):(e.addEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED,this._endedHandler,!1),this._offset=a,this.volume=c,this.pan=d,this._updateVolume(),this._remainingLoops=b,4!==e.readyState?(e.addEventListener(createjs.HTMLAudioPlugin._AUDIO_READY,this._readyHandler,!1),e.addEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED,this._stalledHandler,!1),e.preload="auto",e.load()):this._handleSoundReady(null),this._sendEvent("succeeded"),1)},b._handleSoundStalled=function(){this._cleanUp(),this._sendEvent("failed")},b._handleSoundReady=function(){if(null!=window.createjs){if(this._duration=1e3*this.tag.duration,this.playState=createjs.Sound.PLAY_SUCCEEDED,this._paused=!1,this.tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_READY,this._readyHandler,!1),this._offset>=this.getDuration())return this.playFailed(),void 0;this._offset>0&&(this.tag.currentTime=.001*this._offset),-1==this._remainingLoops&&(this.tag.loop=!0),0!=this._remainingLoops&&(this.tag.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this.loopHandler,!1),this.tag.loop=!0),this.tag.play()}},b.pause=function(){return this._paused||this.playState!=createjs.Sound.PLAY_SUCCEEDED||null==this.tag?!1:(this._paused=!0,this.tag.pause(),clearTimeout(this._delayTimeoutId),!0)},b.resume=function(){return this._paused&&null!=this.tag?(this._paused=!1,this.tag.play(),!0):!1},b.stop=function(){return this._offset=0,this.pause(),this.playState=createjs.Sound.PLAY_FINISHED,this._cleanUp(),!0},b.setMasterVolume=function(){return this._updateVolume(),!0},b.setVolume=function(a){return this.volume=a,!0},b._updateVolume=function(){if(null!=this.tag){var a=this._muted||createjs.Sound._masterMute?0:this._volume*createjs.Sound._masterVolume;return a!=this.tag.volume&&(this.tag.volume=a),!0}return!1},b.getVolume=function(){return this.volume},b.setMasterMute=function(){return this._updateVolume(),!0},b.setMute=function(a){return null==a||void 0==a?!1:(this._muted=a,this._updateVolume(),!0)},b.getMute=function(){return this._muted},b.setPan=function(){return!1},b.getPan=function(){return 0},b.getPosition=function(){return null==this.tag?this._offset:1e3*this.tag.currentTime},b.setPosition=function(a){if(null==this.tag)this._offset=a;else{this.tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this.loopHandler,!1);try{this.tag.currentTime=.001*a}catch(b){return!1}this.tag.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this.loopHandler,!1)}return!0},b.getDuration=function(){return this._duration},b._handleSoundComplete=function(){this._offset=0,null!=window.createjs&&(this.playState=createjs.Sound.PLAY_FINISHED,this._cleanUp(),this._sendEvent("complete"))},b.handleSoundLoop=function(){this._offset=0,this._remainingLoops--,0==this._remainingLoops&&(this.tag.loop=!1,this.tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this.loopHandler,!1)),this._sendEvent("loop")},b.playFailed=function(){null!=window.createjs&&(this.playState=createjs.Sound.PLAY_FAILED,this._cleanUp(),this._sendEvent("failed"))},b.toString=function(){return"[HTMLAudioPlugin SoundInstance]"},createjs.HTMLAudioPlugin.SoundInstance=a}(),function(){"use strict";function a(a,b){this._init(a,b)}var b=a.prototype;b.src=null,b.tag=null,b.preloadTimer=null,b.loadedHandler=null,b._init=function(a,b){if(this.src=a,this.tag=b,this.preloadTimer=setInterval(createjs.proxy(this.preloadTick,this),200),this.loadedHandler=createjs.proxy(this.sendLoadedEvent,this),this.tag.addEventListener&&this.tag.addEventListener("canplaythrough",this.loadedHandler),null==this.tag.onreadystatechange)this.tag.onreadystatechange=createjs.proxy(this.sendLoadedEvent,this);else{var c=this.tag.onreadystatechange;this.tag.onreadystatechange=function(){c(),this.tag.onreadystatechange=createjs.proxy(this.sendLoadedEvent,this)}}this.tag.preload="auto",this.tag.load() -},b.preloadTick=function(){var a=this.tag.buffered,b=this.tag.duration;a.length>0&&a.end(0)>=b-1&&this.handleTagLoaded()},b.handleTagLoaded=function(){clearInterval(this.preloadTimer)},b.sendLoadedEvent=function(){this.tag.removeEventListener&&this.tag.removeEventListener("canplaythrough",this.loadedHandler),this.tag.onreadystatechange=null,createjs.Sound._sendFileLoadEvent(this.src)},b.toString=function(){return"[HTMLAudioPlugin Loader]"},createjs.HTMLAudioPlugin.Loader=a}(),function(){"use strict";function a(a){this._init(a)}var b=a;b.tags={},b.get=function(c){var d=b.tags[c];return null==d&&(d=b.tags[c]=new a(c)),d},b.remove=function(a){var c=b.tags[a];return null==c?!1:(c.removeAll(),delete b.tags[a],!0)},b.removeAll=function(){for(var a in b.tags)b.tags[a].removeAll();b.tags={}},b.getInstance=function(a){var c=b.tags[a];return null==c?null:c.get()},b.setInstance=function(a,c){var d=b.tags[a];return null==d?null:d.set(c)},b.checkSrc=function(a){var c=b.tags[a];return null==c?null:(c.checkSrcChange(),void 0)};var c=a.prototype;c.src=null,c.length=0,c.available=0,c.tags=null,c._init=function(a){this.src=a,this.tags=[]},c.add=function(a){this.tags.push(a),this.length++,this.available++},c.removeAll=function(){for(;this.length--;)delete this.tags[this.length];this.src=null,this.tags.length=0},c.get=function(){if(0==this.tags.length)return null;this.available=this.tags.length;var a=this.tags.pop();return null==a.parentNode&&document.body.appendChild(a),a},c.set=function(a){var b=createjs.indexOf(this.tags,a);-1==b&&this.tags.push(a),this.available=this.tags.length},c.checkSrcChange=function(){for(var a=this.tags.length-1,b=this.tags[a].src;a--;)this.tags[a].src=b},c.toString=function(){return"[HTMLAudioPlugin TagPool]"},createjs.HTMLAudioPlugin.TagPool=a}(); \ No newline at end of file diff --git a/examples/assets/tweenjs-NEXT.min.js b/examples/assets/tweenjs-NEXT.min.js deleted file mode 100644 index 6c18b246..00000000 --- a/examples/assets/tweenjs-NEXT.min.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! -* @license TweenJS -* Visit http://createjs.com/ for documentation, updates and examples. -* -* Copyright (c) 2011-2013 gskinner.com, inc. -* -* Distributed under the terms of the MIT license. -* http://www.opensource.org/licenses/mit-license.html -* -* This notice shall be included in all copies or substantial portions of the Software. -*/ - -/**! - * SoundJS FlashPlugin also includes swfobject (http://code.google.com/p/swfobject/) - */ - -this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c){this.initialize(a,b,c)},b=a.prototype;b.type=null,b.target=null,b.currentTarget=null,b.eventPhase=0,b.bubbles=!1,b.cancelable=!1,b.timeStamp=0,b.defaultPrevented=!1,b.propagationStopped=!1,b.immediatePropagationStopped=!1,b.removed=!1,b.initialize=function(a,b,c){this.type=a,this.bubbles=b,this.cancelable=c,this.timeStamp=(new Date).getTime()},b.preventDefault=function(){this.defaultPrevented=!0},b.stopPropagation=function(){this.propagationStopped=!0},b.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},b.remove=function(){this.removed=!0},b.clone=function(){return new a(this.type,this.bubbles,this.cancelable)},b.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){},b=a.prototype;a.initialize=function(a){a.addEventListener=b.addEventListener,a.on=b.on,a.removeEventListener=a.off=b.removeEventListener,a.removeAllEventListeners=b.removeAllEventListeners,a.hasEventListener=b.hasEventListener,a.dispatchEvent=b.dispatchEvent,a._dispatchEvent=b._dispatchEvent,a.willTrigger=b.willTrigger},b._listeners=null,b._captureListeners=null,b.initialize=function(){},b.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},b.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},b.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},b.off=b.removeEventListener,b.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},b.dispatchEvent=function(a,b){if("string"==typeof a){var c=this._listeners;if(!c||!c[a])return!1;a=new createjs.Event(a)}if(a.target=b||this,a.bubbles&&this.parent){for(var d=this,e=[d];d.parent;)e.push(d=d.parent);var f,g=e.length;for(f=g-1;f>=0&&!a.propagationStopped;f--)e[f]._dispatchEvent(a,1+(0==f));for(f=1;g>f&&!a.propagationStopped;f++)e[f]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return a.defaultPrevented},b.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},b.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},b.toString=function(){return"[EventDispatcher]"},b._dispatchEvent=function(a,b){var c,d=1==b?this._captureListeners:this._listeners;if(a&&d){var e=d[a.type];if(!e||!(c=e.length))return;a.currentTarget=this,a.eventPhase=b,a.removed=!1,e=e.slice();for(var f=0;c>f&&!a.immediatePropagationStopped;f++){var g=e[f];g.handleEvent?g.handleEvent(a):g(a),a.removed&&(this.off(a.type,g,1==b),a.removed=!1)}}},createjs.EventDispatcher=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c){this.initialize(a,b,c)},b=a.prototype=new createjs.EventDispatcher;a.NONE=0,a.LOOP=1,a.REVERSE=2,a.IGNORE={},a._tweens=[],a._plugins={},a.get=function(b,c,d,e){return e&&a.removeTweens(b),new a(b,c,d)},a.tick=function(b,c){for(var d=a._tweens.slice(),e=d.length-1;e>=0;e--){var f=d[e];c&&!f.ignoreGlobalPause||f._paused||f.tick(f._useTicks?1:b)}},a.handleEvent=function(a){"tick"==a.type&&this.tick(a.delta,a.paused)},a.removeTweens=function(b){if(b.tweenjs_count){for(var c=a._tweens,d=c.length-1;d>=0;d--)c[d]._target==b&&(c[d]._paused=!0,c.splice(d,1));b.tweenjs_count=0}},a.removeAllTweens=function(){for(var b=a._tweens,c=0,d=b.length;d>c;c++){var e=b[c];e.paused=!0,e.target.tweenjs_count=0}b.length=0},a.hasActiveTweens=function(b){return b?b.tweenjs_count:a._tweens&&!!a._tweens.length},a.installPlugin=function(b,c){var d=b.priority;null==d&&(b.priority=d=0);for(var e=0,f=c.length,g=a._plugins;f>e;e++){var h=c[e];if(g[h]){for(var i=g[h],j=0,k=i.length;k>j&&!(d=a)return this;var c=this._cloneProps(this._curQueueProps);return this._addStep({d:a,p0:c,e:this._linearEase,p1:c,v:b})},b.to=function(a,b,c){return(isNaN(b)||0>b)&&(b=0),this._addStep({d:b||0,p0:this._cloneProps(this._curQueueProps),e:c,p1:this._cloneProps(this._appendQueueProps(a))})},b.call=function(a,b,c){return this._addAction({f:a,p:b?b:[this],o:c?c:this._target})},b.set=function(a,b){return this._addAction({f:this._set,o:this,p:[a,b?b:this._target]})},b.play=function(a){return a||(a=this),this.call(a.setPaused,[!1],a)},b.pause=function(a){return a||(a=this),this.call(a.setPaused,[!0],a)},b.setPosition=function(a,b){0>a&&(a=0),null==b&&(b=1);var c=a,d=!1;if(c>=this.duration&&(this.loop?c%=this.duration:(c=this.duration,d=!0)),c==this._prevPos)return d;var e=this._prevPos;if(this.position=this._prevPos=c,this._prevPosition=a,this._target)if(d)this._updateTargetProps(null,1);else if(this._steps.length>0){for(var f=0,g=this._steps.length;g>f&&!(this._steps[f].t>c);f++);var h=this._steps[f-1];this._updateTargetProps(h,(this._stepPosition=c-h.t)/h.d)}return 0!=b&&this._actions.length>0&&(this._useTicks?this._runActions(c,c):1==b&&e>c?(e!=this.duration&&this._runActions(e,this.duration),this._runActions(0,c,!0)):this._runActions(e,c)),d&&this.setPaused(!0),this.dispatchEvent("change"),d},b.tick=function(a){this._paused||this.setPosition(this._prevPosition+a)},b.setPaused=function(b){return this._paused=!!b,a._register(this,!b),this},b.w=b.wait,b.t=b.to,b.c=b.call,b.s=b.set,b.toString=function(){return"[Tween]"},b.clone=function(){throw"Tween can not be cloned."},b._updateTargetProps=function(b,c){var d,e,f,g,h,i;if(b||1!=c){if(this.passive=!!b.v,this.passive)return;b.e&&(c=b.e(c,0,1,1)),d=b.p0,e=b.p1}else this.passive=!1,d=e=this._curQueueProps;for(var j in this._initQueueProps){null==(g=d[j])&&(d[j]=g=this._initQueueProps[j]),null==(h=e[j])&&(e[j]=h=g),f=g==h||0==c||1==c||"number"!=typeof g?1==c?h:g:g+(h-g)*c;var k=!1;if(i=a._plugins[j])for(var l=0,m=i.length;m>l;l++){var n=i[l].tween(this,j,f,d,e,c,!!b&&d==e,!b);n==a.IGNORE?k=!0:f=n}k||(this._target[j]=f)}},b._runActions=function(a,b,c){var d=a,e=b,f=-1,g=this._actions.length,h=1;for(a>b&&(d=b,e=a,f=g,g=h=-1);(f+=h)!=g;){var i=this._actions[f],j=i.t;(j==e||j>d&&e>j||c&&j==a)&&i.f.apply(i.o,i.p)}},b._appendQueueProps=function(b){var c,d,e,f,g;for(var h in b)if(void 0===this._initQueueProps[h]){if(d=this._target[h],c=a._plugins[h])for(e=0,f=c.length;f>e;e++)d=c[e].init(this,h,d);this._initQueueProps[h]=this._curQueueProps[h]=void 0===d?null:d}else d=this._curQueueProps[h];for(var h in b){if(d=this._curQueueProps[h],c=a._plugins[h])for(g=g||{},e=0,f=c.length;f>e;e++)c[e].step&&c[e].step(this,h,d,b[h],g);this._curQueueProps[h]=b[h]}return g&&this._appendQueueProps(g),this._curQueueProps},b._cloneProps=function(a){var b={};for(var c in a)b[c]=a[c];return b},b._addStep=function(a){return a.d>0&&(this._steps.push(a),a.t=this.duration,this.duration+=a.d),this},b._addAction=function(a){return a.t=this.duration,this._actions.push(a),this},b._set=function(a,b){for(var c in a)b[c]=a[c]},createjs.Tween=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c){this.initialize(a,b,c)},b=a.prototype=new createjs.EventDispatcher;b.ignoreGlobalPause=!1,b.duration=0,b.loop=!1,b.position=null,b._paused=!1,b._tweens=null,b._labels=null,b._labelList=null,b._prevPosition=0,b._prevPos=-1,b._useTicks=!1,b.initialize=function(a,b,c){this._tweens=[],c&&(this._useTicks=c.useTicks,this.loop=c.loop,this.ignoreGlobalPause=c.ignoreGlobalPause,c.onChange&&this.addEventListener("change",c.onChange)),a&&this.addTween.apply(this,a),this.setLabels(b),c&&c.paused?this._paused=!0:createjs.Tween._register(this,!0),c&&null!=c.position&&this.setPosition(c.position,createjs.Tween.NONE)},b.addTween=function(a){var b=arguments.length;if(b>1){for(var c=0;b>c;c++)this.addTween(arguments[c]);return arguments[0]}return 0==b?null:(this.removeTween(a),this._tweens.push(a),a.setPaused(!0),a._paused=!1,a._useTicks=this._useTicks,a.duration>this.duration&&(this.duration=a.duration),this._prevPos>=0&&a.setPosition(this._prevPos,createjs.Tween.NONE),a)},b.removeTween=function(a){var b=arguments.length;if(b>1){for(var c=!0,d=0;b>d;d++)c=c&&this.removeTween(arguments[d]);return c}if(0==b)return!1;for(var e=this._tweens,d=e.length;d--;)if(e[d]==a)return e.splice(d,1),a.duration>=this.duration&&this.updateDuration(),!0;return!1},b.addLabel=function(a,b){this._labels[a]=b;var c=this._labelList;if(c){for(var d=0,e=c.length;e>d&&!(bd&&!(ba&&(a=0);var c=this.loop?a%this.duration:a,d=!this.loop&&a>=this.duration;if(c==this._prevPos)return d;this._prevPosition=a,this.position=this._prevPos=c;for(var e=0,f=this._tweens.length;f>e;e++)if(this._tweens[e].setPosition(c,b),c!=this._prevPos)return!1;return d&&this.setPaused(!0),this.dispatchEvent("change"),d},b.setPaused=function(a){this._paused=!!a,createjs.Tween._register(this,!a)},b.updateDuration=function(){this.duration=0;for(var a=0,b=this._tweens.length;b>a;a++){var c=this._tweens[a];c.duration>this.duration&&(this.duration=c.duration)}},b.tick=function(a){this.setPosition(this._prevPosition+a)},b.resolve=function(a){var b=parseFloat(a);return isNaN(b)&&(b=this._labels[a]),b},b.toString=function(){return"[Timeline]"},b.clone=function(){throw"Timeline can not be cloned."},b._goto=function(a){var b=this.resolve(a);null!=b&&this.setPosition(b)},createjs.Timeline=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){throw"Ease cannot be instantiated."};a.linear=function(a){return a},a.none=a.linear,a.get=function(a){return-1>a&&(a=-1),a>1&&(a=1),function(b){return 0==a?b:0>a?b*(b*-a+1+a):b*((2-b)*a+(1-a))}},a.getPowIn=function(a){return function(b){return Math.pow(b,a)}},a.getPowOut=function(a){return function(b){return 1-Math.pow(1-b,a)}},a.getPowInOut=function(a){return function(b){return(b*=2)<1?.5*Math.pow(b,a):1-.5*Math.abs(Math.pow(2-b,a))}},a.quadIn=a.getPowIn(2),a.quadOut=a.getPowOut(2),a.quadInOut=a.getPowInOut(2),a.cubicIn=a.getPowIn(3),a.cubicOut=a.getPowOut(3),a.cubicInOut=a.getPowInOut(3),a.quartIn=a.getPowIn(4),a.quartOut=a.getPowOut(4),a.quartInOut=a.getPowInOut(4),a.quintIn=a.getPowIn(5),a.quintOut=a.getPowOut(5),a.quintInOut=a.getPowInOut(5),a.sineIn=function(a){return 1-Math.cos(a*Math.PI/2)},a.sineOut=function(a){return Math.sin(a*Math.PI/2)},a.sineInOut=function(a){return-.5*(Math.cos(Math.PI*a)-1)},a.getBackIn=function(a){return function(b){return b*b*((a+1)*b-a)}},a.backIn=a.getBackIn(1.7),a.getBackOut=function(a){return function(b){return--b*b*((a+1)*b+a)+1}},a.backOut=a.getBackOut(1.7),a.getBackInOut=function(a){return a*=1.525,function(b){return(b*=2)<1?.5*b*b*((a+1)*b-a):.5*((b-=2)*b*((a+1)*b+a)+2)}},a.backInOut=a.getBackInOut(1.7),a.circIn=function(a){return-(Math.sqrt(1-a*a)-1)},a.circOut=function(a){return Math.sqrt(1- --a*a)},a.circInOut=function(a){return(a*=2)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)},a.bounceIn=function(b){return 1-a.bounceOut(1-b)},a.bounceOut=function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375},a.bounceInOut=function(b){return.5>b?.5*a.bounceIn(2*b):.5*a.bounceOut(2*b-1)+.5},a.getElasticIn=function(a,b){var c=2*Math.PI;return function(d){if(0==d||1==d)return d;var e=b/c*Math.asin(1/a);return-(a*Math.pow(2,10*(d-=1))*Math.sin((d-e)*c/b))}},a.elasticIn=a.getElasticIn(1,.3),a.getElasticOut=function(a,b){var c=2*Math.PI;return function(d){if(0==d||1==d)return d;var e=b/c*Math.asin(1/a);return a*Math.pow(2,-10*d)*Math.sin((d-e)*c/b)+1}},a.elasticOut=a.getElasticOut(1,.3),a.getElasticInOut=function(a,b){var c=2*Math.PI;return function(d){var e=b/c*Math.asin(1/a);return(d*=2)<1?-.5*a*Math.pow(2,10*(d-=1))*Math.sin((d-e)*c/b):.5*a*Math.pow(2,-10*(d-=1))*Math.sin((d-e)*c/b)+1}},a.elasticInOut=a.getElasticInOut(1,.3*1.5),createjs.Ease=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){throw"MotionGuidePlugin cannot be instantiated."};a.priority=0,a._rotOffS,a._rotOffE,a._rotNormS,a._rotNormE,a.install=function(){return createjs.Tween.installPlugin(a,["guide","x","y","rotation"]),createjs.Tween.IGNORE},a.init=function(a,b,c){var d=a.target;return d.hasOwnProperty("x")||(d.x=0),d.hasOwnProperty("y")||(d.y=0),d.hasOwnProperty("rotation")||(d.rotation=0),"rotation"==b&&(a.__needsRot=!0),"guide"==b?null:c},a.step=function(b,c,d,e,f){if("rotation"==c&&(b.__rotGlobalS=d,b.__rotGlobalE=e,a.testRotData(b,f)),"guide"!=c)return e;var g,h=e;h.hasOwnProperty("path")||(h.path=[]);var i=h.path;if(h.hasOwnProperty("end")||(h.end=1),h.hasOwnProperty("start")||(h.start=d&&d.hasOwnProperty("end")&&d.path===i?d.end:0),h.hasOwnProperty("_segments")&&h._length)return e;var j=i.length,k=10;if(!(j>=6&&0==(j-2)%4))throw"invalid 'path' data, please see documentation for valid paths";h._segments=[],h._length=0;for(var l=2;j>l;l+=4){for(var m,n,o=i[l-2],p=i[l-1],q=i[l+0],r=i[l+1],s=i[l+2],t=i[l+3],u=o,v=p,w=0,x=[],y=1;k>=y;y++){var z=y/k,A=1-z;m=A*A*o+2*A*z*q+z*z*s,n=A*A*p+2*A*z*r+z*z*t,w+=x[x.push(Math.sqrt((g=m-u)*g+(g=n-v)*g))-1],u=m,v=n}h._segments.push(w),h._segments.push(x),h._length+=w}g=h.orient,h.orient=!0;var B={};return a.calc(h,h.start,B),b.__rotPathS=Number(B.rotation.toFixed(5)),a.calc(h,h.end,B),b.__rotPathE=Number(B.rotation.toFixed(5)),h.orient=!1,a.calc(h,h.end,f),h.orient=g,h.orient?(b.__guideData=h,a.testRotData(b,f),e):e},a.testRotData=function(a,b){if(void 0===a.__rotGlobalS||void 0===a.__rotGlobalE){if(a.__needsRot)return;a.__rotGlobalS=a.__rotGlobalE=void 0!==a._curQueueProps.rotation?a._curQueueProps.rotation:b.rotation=a.target.rotation||0}if(void 0!==a.__guideData){var c=a.__guideData,d=a.__rotGlobalE-a.__rotGlobalS,e=a.__rotPathE-a.__rotPathS,f=d-e;if("auto"==c.orient)f>180?f-=360:-180>f&&(f+=360);else if("cw"==c.orient){for(;0>f;)f+=360;0==f&&d>0&&180!=d&&(f+=360)}else if("ccw"==c.orient){for(f=d-(e>180?360-e:e);f>0;)f-=360;0==f&&0>d&&-180!=d&&(f-=360)}c.rotDelta=f,c.rotOffS=a.__rotGlobalS-a.__rotPathS,a.__rotGlobalS=a.__rotGlobalE=a.__guideData=a.__needsRot=void 0}},a.tween=function(b,c,d,e,f,g,h){var i=f.guide;if(void 0==i||i===e.guide)return d;if(i.lastRatio!=g){var j=(i.end-i.start)*(h?i.end:g)+i.start;switch(a.calc(i,j,b.target),i.orient){case"cw":case"ccw":case"auto":b.target.rotation+=i.rotOffS+i.rotDelta*g;break;case"fixed":default:b.target.rotation+=i.rotOffS}i.lastRatio=g}return"rotation"!=c||i.orient&&"false"!=i.orient?b.target[c]:d},a.calc=function(b,c,d){void 0==b._segments&&a.validate(b),void 0==d&&(d={x:0,y:0,rotation:0});for(var e=b._segments,f=b.path,g=b._length*c,h=e.length-2,i=0;g>e[i]&&h>i;)g-=e[i],i+=2;var j=e[i+1],k=0;for(h=j.length-1;g>j[k]&&h>k;)g-=j[k],k++;var l=k/++h+g/(h*j[k]);i=2*i+2;var m=1-l;return d.x=m*m*f[i-2]+2*m*l*f[i+0]+l*l*f[i+2],d.y=m*m*f[i-1]+2*m*l*f[i+1]+l*l*f[i+3],b.orient&&(d.rotation=57.2957795*Math.atan2((f[i+1]-f[i-1])*m+(f[i+3]-f[i+1])*l,(f[i+0]-f[i-2])*m+(f[i+2]-f[i+0])*l)),d},createjs.MotionGuidePlugin=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=createjs.TweenJS=createjs.TweenJS||{};a.version="NEXT",a.buildDate="Thu, 12 Dec 2013 23:37:07 GMT"}(); \ No newline at end of file diff --git a/icon.png b/icon.png new file mode 100644 index 00000000..05641602 Binary files /dev/null and b/icon.png differ diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 00000000..1c0c45d2 --- /dev/null +++ b/lib/README.md @@ -0,0 +1,21 @@ +# lib directory +This directory contains compressed versions of the PreloadJS library, including the most recent tagged release and the +in-progress NEXT release. + +Both combined and minified versions of the library are included. The former being useful for debugging, and the latter +for deployment. + +You can also link to the libraries on the [CreateJS CDN](http://code.createjs.com/), to benefit from faster load times +and shared caching across sites. + + +# libraries +* **preloadjs.js** the most recent _tagged_ version of all the PreloadJS classes. +* **preloadjs.min.js** the most recent tagged version, minified and stripped of comments and whitespace. +* **preloadjs-NEXT.js** contains the _latest_ PreloadJS classes. +* **preloadjs-NEXT.min.js** is a minified version of the _latest updates_ to the library. + + +# license +The libraries are ©2017 gskinner.com, inc., and made available under the highly permissive MIT open source software +license. See the source file header for the full license text. diff --git a/lib/README.txt b/lib/README.txt deleted file mode 100644 index adaf7769..00000000 --- a/lib/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This directory contains a compressed version of the PreloadJS library. - -You can also gzip the file to further reduce its size (by about 75%). Many servers do this automatically. diff --git a/lib/preloadjs-0.4.1.combined.js b/lib/preloadjs-0.4.1.combined.js deleted file mode 100644 index 2056f8f6..00000000 --- a/lib/preloadjs-0.4.1.combined.js +++ /dev/null @@ -1,4428 +0,0 @@ -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - /** - * Static class holding library specific information such as the version and buildDate of - * the library. - * - * The old PreloadJS class has been renamed to LoadQueue. Please see the {{#crossLink "LoadQueue"}}{{/crossLink}} - * class for information on loading files. - * @class PreloadJS - **/ - var s = createjs.PreloadJS = createjs.PreloadJS || {}; - - /** - * The version string for this release. - * @property version - * @type String - * @static - **/ - s.version = /*version*/"0.4.1"; // injected by build process - - /** - * The build date for this release in UTC format. - * @property buildDate - * @type String - * @static - **/ - s.buildDate = /*date*/"Tue, 04 Mar 2014 23:44:08 GMT"; // injected by build process - -})(); -/* -* Event -* Visit http://createjs.com/ for documentation, updates and examples. -* -* Copyright (c) 2010 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * A collection of Classes that are shared across all the CreateJS libraries. The classes are included in the minified - * files of each library and are available on the createsjs namespace directly. - * - *

Example

- * myObject.addEventListener("change", createjs.proxy(myMethod, scope)); - * - * @module CreateJS - * @main CreateJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - -/** - * Contains properties and methods shared by all events for use with - * {{#crossLink "EventDispatcher"}}{{/crossLink}}. - * - * Note that Event objects are often reused, so you should never - * rely on an event object's state outside of the call stack it was received in. - * @class Event - * @param {String} type The event type. - * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. - * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. - * @constructor - **/ -var Event = function(type, bubbles, cancelable) { - this.initialize(type, bubbles, cancelable); -}; -var p = Event.prototype; - -// events: - -// public properties: - - /** - * The type of event. - * @property type - * @type String - **/ - p.type = null; - - /** - * The object that generated an event. - * @property target - * @type Object - * @default null - * @readonly - */ - p.target = null; - - /** - * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will - * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event - * is generated from childObj, then a listener on parentObj would receive the event with - * target=childObj (the original target) and currentTarget=parentObj (where the listener was added). - * @property currentTarget - * @type Object - * @default null - * @readonly - */ - p.currentTarget = null; - - /** - * For bubbling events, this indicates the current event phase:
    - *
  1. capture phase: starting from the top parent to the target
  2. - *
  3. at target phase: currently being dispatched from the target
  4. - *
  5. bubbling phase: from the target to the top parent
  6. - *
- * @property eventPhase - * @type Number - * @default 0 - * @readonly - */ - p.eventPhase = 0; - - /** - * Indicates whether the event will bubble through the display list. - * @property bubbles - * @type Boolean - * @default false - * @readonly - */ - p.bubbles = false; - - /** - * 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 - */ - p.cancelable = false; - - /** - * The epoch time at which this event was created. - * @property timeStamp - * @type Number - * @default 0 - * @readonly - */ - p.timeStamp = 0; - - /** - * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called - * on this event. - * @property defaultPrevented - * @type Boolean - * @default false - * @readonly - */ - p.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 - */ - p.propagationStopped = false; - - /** - * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called - * on this event. - * @property immediatePropagationStopped - * @type Boolean - * @default false - * @readonly - */ - p.immediatePropagationStopped = false; - - /** - * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event. - * @property removed - * @type Boolean - * @default false - * @readonly - */ - p.removed = false; - -// constructor: - /** - * Initialization method. - * @method initialize - * @param {String} type The event type. - * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. - * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. - * @protected - **/ - p.initialize = function(type, bubbles, cancelable) { - this.type = type; - this.bubbles = bubbles; - this.cancelable = cancelable; - this.timeStamp = (new Date()).getTime(); - }; - -// public methods: - - /** - * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true. - * Mirrors the DOM event standard. - * @method preventDefault - **/ - p.preventDefault = function() { - this.defaultPrevented = 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); - }; - - /** - * 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; -}()); -/* -* EventDispatcher -* Visit http://createjs.com/ for documentation, updates and examples. -* -* Copyright (c) 2010 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * @module CreateJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - -/** - * EventDispatcher provides methods for managing queues of event listeners and dispatching events. - * - * You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the - * EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method. - * - * Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the - * DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports - * bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent. - * - * EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier - * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The - * {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to - * {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}. - * - * Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}} - * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also - * includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener. - * - *

Example

- * Add EventDispatcher capabilities to the "MyClass" class. - * - * EventDispatcher.initialize(MyClass.prototype); - * - * Add an event (see {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}}). - * - * instance.addEventListener("eventName", handlerMethod); - * function handlerMethod(event) { - * console.log(event.target + " Was Clicked"); - * } - * - * Maintaining proper scope
- * Scope (ie. "this") can be be a challenge with events. Using the {{#crossLink "EventDispatcher/on"}}{{/crossLink}} - * method to subscribe to events simplifies this. - * - * instance.addEventListener("click", function(event) { - * console.log(instance == this); // false, scope is ambiguous. - * }); - * - * instance.on("click", function(event) { - * console.log(instance == this); // true, "on" uses dispatcher scope by default. - * }); - * - * If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage scope. - * - * - * @class EventDispatcher - * @constructor - **/ -var EventDispatcher = function() { -/* this.initialize(); */ // not needed. -}; -var p = EventDispatcher.prototype; - - - /** - * 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; - }; - -// constructor: - -// private properties: - /** - * @protected - * @property _listeners - * @type Object - **/ - p._listeners = null; - - /** - * @protected - * @property _captureListeners - * @type Object - **/ - p._captureListeners = null; - -// constructor: - /** - * Initialization method. - * @method initialize - * @protected - **/ - p.initialize = function() {}; - -// public methods: - /** - * Adds the specified event listener. Note that adding multiple listeners to the same function will result in - * multiple callbacks getting fired. - * - *

Example

- * - * displayObject.addEventListener("click", handleClick); - * function handleClick(event) { - * // Click happened. - * } - * - * @method addEventListener - * @param {String} type The string type of the event. - * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when - * the event is dispatched. - * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. - * @return {Function | Object} Returns the listener for chaining or assignment. - **/ - p.addEventListener = function(type, listener, useCapture) { - var listeners; - if (useCapture) { - listeners = this._captureListeners = this._captureListeners||{}; - } else { - listeners = this._listeners = this._listeners||{}; - } - var arr = listeners[type]; - if (arr) { this.removeEventListener(type, listener, useCapture); } - arr = listeners[type]; // remove may have deleted the array - if (!arr) { listeners[type] = [listener]; } - else { arr.push(listener); } - return listener; - }; - - /** - * A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener - * only run once, associate arbitrary data with the listener, and remove the listener. - * - * This method works by creating an anonymous wrapper function and subscribing it with addEventListener. - * The created anonymous function is returned for use with .removeEventListener (or .off). - * - *

Example

- * - * var listener = myBtn.on("click", handleClick, null, false, {count:3}); - * function handleClick(evt, data) { - * data.count -= 1; - * console.log(this == myBtn); // true - scope defaults to the dispatcher - * if (data.count == 0) { - * alert("clicked 3 times!"); - * myBtn.off("click", listener); - * // alternately: evt.remove(); - * } - * } - * - * @method on - * @param {String} type The string type of the event. - * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when - * the event is dispatched. - * @param {Object} [scope] The scope to execute the listener in. Defaults to the dispatcher/currentTarget for function listeners, and to the listener itself for object listeners (ie. using handleEvent). - * @param {Boolean} [once=false] If true, the listener will remove itself after the first time it is triggered. - * @param {*} [data] Arbitrary data that will be included as the second parameter when the listener is called. - * @param {Boolean} [useCapture=false] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. - * @return {Function} Returns the anonymous function that was created and assigned as the listener. This is needed to remove the listener later using .removeEventListener. - **/ - p.on = function(type, listener, scope, once, data, useCapture) { - if (listener.handleEvent) { - scope = scope||listener; - listener = listener.handleEvent; - } - scope = scope||this; - return this.addEventListener(type, function(evt) { - listener.call(scope, evt, data); - once&&evt.remove(); - }, useCapture); - }; - - /** - * Removes the specified event listener. - * - * Important Note: that you must pass the exact function reference used when the event was added. If a proxy - * function, or function closure is used as the callback, the proxy/closure reference must be used - a new proxy or - * closure will not work. - * - *

Example

- * - * displayObject.removeEventListener("click", handleClick); - * - * @method removeEventListener - * @param {String} type The string type of the event. - * @param {Function | Object} listener The listener function or object. - * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. - **/ - p.removeEventListener = function(type, listener, useCapture) { - var listeners = useCapture ? this._captureListeners : this._listeners; - if (!listeners) { return; } - var arr = listeners[type]; - if (!arr) { return; } - for (var i=0,l=arr.length; iExample - * - * // Remove all listeners - * displayObject.removeAllEventListeners(); - * - * // Remove all click listeners - * displayObject.removeAllEventListeners("click"); - * - * @method removeAllEventListeners - * @param {String} [type] The string type of the event. If omitted, all listeners for all types will be removed. - **/ - p.removeAllEventListeners = function(type) { - if (!type) { this._listeners = this._captureListeners = null; } - else { - if (this._listeners) { delete(this._listeners[type]); } - if (this._captureListeners) { delete(this._captureListeners[type]); } - } - }; - - /** - * Dispatches the specified event to all listeners. - * - *

Example

- * - * // Use a string event - * this.dispatchEvent("complete"); - * - * // Use an Event instance - * var event = new createjs.Event("progress"); - * this.dispatchEvent(event); - * - * @method dispatchEvent - * @param {Object | String | Event} eventObj An object with a "type" property, or a string type. - * While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used, - * dispatchEvent will construct an Event instance with the specified type. - * @param {Object} [target] The object to use as the target property of the event object. This will default to the - * dispatching object. This parameter is deprecated and will be removed. - * @return {Boolean} Returns the value of eventObj.defaultPrevented. - **/ - p.dispatchEvent = function(eventObj, target) { - if (typeof eventObj == "string") { - // won't bubble, so skip everything if there's no listeners: - var listeners = this._listeners; - if (!listeners || !listeners[eventObj]) { return false; } - eventObj = new createjs.Event(eventObj); - } - // TODO: deprecated. Target param is deprecated, only use case is MouseEvent/mousemove, remove. - eventObj.target = target||this; - - 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; iExample - * 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)); - }; - } - -}());/* -* AbstractLoader -* Visit http://createjs.com/ for documentation, updates and examples. -* -* -* Copyright (c) 2012 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * @module PreloadJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - /** - * The base loader, which defines all the generic callbacks and events. All loaders extend this class, including the - * {{#crossLink "LoadQueue"}}{{/crossLink}}. - * @class AbstractLoader - * @extends EventDispatcher - */ - var AbstractLoader = function () { - this.init(); - }; - - AbstractLoader.prototype = new createjs.EventDispatcher(); //TODO: TEST! - var p = AbstractLoader.prototype; - var s = AbstractLoader; - - /** - * The RegExp pattern to use to parse file URIs. This supports simple file names, as well as full domain URIs with - * query strings. The resulting match is: protocol:$1 domain:$2 relativePath:$3 path:$4 file:$5 extension:$6 query:$7. - * @property FILE_PATTERN - * @type {RegExp} - * @static - * @protected - */ - s.FILE_PATTERN = /^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?)|(.{0,2}\/{1}))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/; - - /** - * The RegExp pattern to use to parse path URIs. This supports protocols, relative files, and paths. The resulting - * match is: protocol:$1 relativePath:$2 path$3. - * @property PATH_PATTERN - * @type {RegExp} - * @static - * @protected - */ - s.PATH_PATTERN = /^(?:(\w+:)\/{2})|(.{0,2}\/{1})?([/.]*?(?:[^?]+)?\/?)?$/; - - /** - * 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 event. - * @property loaded - * @type {Boolean} - * @default false - */ - p.loaded = false; - - /** - * Determine if the loader was canceled. Canceled loads will not fire complete events. Note that - * {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "AbstractLoader/close"}}{{/crossLink}} - * instead of setting this property. - * @property canceled - * @type {Boolean} - * @default false - */ - p.canceled = false; - - /** - * The current load progress (percentage) for this item. This will be a number between 0 and 1. - * - *

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 - */ - p.progress = 0; - - /** - * The item this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}}, but will - * be available on loaders such as {{#crossLink "XHRLoader"}}{{/crossLink}} and {{#crossLink "TagLoader"}}{{/crossLink}}. - * @property _item - * @type {Object} - * @private - */ - p._item = null; - -// Events - /** - * The event that is fired when the overall progress changes. - * @event progress - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Number} loaded The amount that has been loaded so far. Note that this is may just be a percentage of 1, - * since file sizes can not be determined before a load is kicked off, if at all. - * @param {Number} total The total number of bytes. Note that this may just be 1. - * @param {Number} progress The ratio that has been loaded between 0 and 1. - * @since 0.3.0 - */ - - /** - * The event that is fired when a load starts. - * @event loadstart - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.3.1 - */ - - /** - * The event that is fired when the entire queue has been loaded. - * @event complete - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.3.0 - */ - - /** - * The event that is fired when the loader encounters an error. If the error was encountered by a file, the event will - * contain the item that caused the error. There may be additional properties such as the error reason on event - * objects. - * @event error - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Object} [item] The item that was being loaded that caused the error. The item was specified in - * the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * call. If only a string path or tag was specified, the object will contain that value as a `src` property. - * @param {String} [error] The error object or text. - * @since 0.3.0 - */ - - //TODO: Deprecated - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}} - * event. - * @property onProgress - * @type {Function} - * @deprecated Use addEventListener and the "progress" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}} - * event. - * @property onLoadStart - * @type {Function} - * @deprecated Use addEventListener and the "loadstart" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} - * event. - * @property onComplete - * @type {Function} - * @deprecated Use addEventListener and the "complete" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} - * event. - * @property onError - * @type {Function} - * @deprecated Use addEventListener and the "error" event. - */ - - /** - * Get a reference to the manifest item that is loaded by this loader. In most cases this will be the value that was - * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or - * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will - * be an Object created by the LoadQueue. - * @return {Object} The manifest item that this loader is responsible for loading. - */ - p.getItem = function() { - return this._item; - }; - - /** - * Initialize the loader. This is called by the constructor. - * @method init - * @private - */ - p.init = function () {}; - - /** - * Begin loading the queued items. This method can be called when a {{#crossLink "LoadQueue"}}{{/crossLink}} is set - * up but not started immediately. - * @example - * var queue = new createjs.LoadQueue(); - * queue.addEventListener("complete", handleComplete); - * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet - * queue.load(); - * @method load - */ - p.load = function() {}; - - /** - * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from - * starting to download. Note that currently any active loads will remain open, and events may be processed. - * - * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead. - * @method close - */ - p.close = function() {}; - - -//Callback proxies - /** - * Dispatch a loadstart event. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}} event - * for details on the event payload. - * @method _sendLoadStart - * @protected - */ - p._sendLoadStart = function() { - if (this._isCanceled()) { return; } - this.dispatchEvent("loadstart"); - }; - - /** - * Dispatch a progress event. Please see the {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}} event for - * details on the event payload. - * @method _sendProgress - * @param {Number | Object} value The progress of the loaded item, or an object containing loaded - * and total properties. - * @protected - */ - p._sendProgress = function(value) { - if (this._isCanceled()) { return; } - var event = null; - if (typeof(value) == "number") { - this.progress = value; - event = new createjs.Event("progress"); - event.loaded = this.progress; - event.total = 1; - } else { - event = value; - this.progress = value.loaded / value.total; - if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } - } - event.progress = this.progress; - this.hasEventListener("progress") && this.dispatchEvent(event); - }; - - /** - * Dispatch a complete event. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event - * for details on the event payload. - * @method _sendComplete - * @protected - */ - p._sendComplete = function() { - if (this._isCanceled()) { return; } - this.dispatchEvent("complete"); - }; - - /** - * Dispatch an error event. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} event for - * details on the event payload. - * @method _sendError - * @param {Object} event The event object containing specific error properties. - * @protected - */ - p._sendError = function(event) { - if (this._isCanceled() || !this.hasEventListener("error")) { return; } - if (event == null) { - event = new createjs.Event("error"); - } - this.dispatchEvent(event); - }; - - /** - * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events - * do not cause issues after the queue has been cleaned up. - * @method _isCanceled - * @return {Boolean} If the loader has been canceled. - * @protected - */ - p._isCanceled = function() { - if (window.createjs == null || this.canceled) { - return true; - } - return false; - }; - - /** - * Parse a file URI using the {{#crossLink "AbstractLoader/FILE_PATTERN:property"}}{{/crossLink}} RegExp pattern. - * @method _parseURI - * @param {String} path The file path to parse. - * @return {Array} The matched file contents. Please see the FILE_PATTERN property for details on the return value. - * This will return null if it does not match. - * @protected - */ - p._parseURI = function(path) { - if (!path) { return null; } - return path.match(s.FILE_PATTERN); - }; - - /** - * Parse a file URI using the {{#crossLink "AbstractLoader/PATH_PATTERN"}}{{/crossLink}} RegExp pattern. - * @method _parsePath - * @param {String} path The file path to parse. - * @return {Array} The matched path contents. Please see the PATH_PATTERN property for details on the return value. - * This will return null if it does not match. - * @protected - */ - p._parsePath = function(path) { - if (!path) { return null; } - return path.match(s.PATH_PATTERN); - }; - - /** - * Formats an object into a query string for either a POST or GET request. - * @method _formatQueryString - * @param {Object} data The data to convert to a query string. - * @param {Array} [query] Existing name/value pairs to append on to this query. - * @private - */ - p._formatQueryString = function(data, query) { - if (data == null) { - throw new Error('You must specify data.'); - } - var params = []; - for (var n in data) { - params.push(n+'='+escape(data[n])); - } - if (query) { - params = params.concat(query); - } - return params.join('&'); - }; - - /** - * A utility method that builds a file path using a source and a data object, and formats it into a new path. All - * of the loaders in PreloadJS use this method to compile paths when loading. - * @method buildPath - * @param {String} src The source path to add values to. - * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the - * path will be preserved. - * @returns {string} A formatted string that contains the path and the supplied parameters. - * @since 0.3.1 - */ - p.buildPath = function(src, 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 {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. - * @private - */ - p._isCrossDomain = function(item) { - var target = document.createElement("a"); - target.href = item.src; - - var host = document.createElement("a"); - host.href = location.href; - - var crossdomain = (target.hostname != "") && - (target.port != host.port || - target.protocol != host.protocol || - target.hostname != host.hostname); - return crossdomain; - } - - /** - * @method _isLocal - * @param {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. - * @private - */ - p._isLocal = function(item) { - var target = document.createElement("a"); - target.href = item.src; - return target.hostname == "" && target.protocol == "file:"; - }; - - /** - * @method toString - * @return {String} a string representation of the instance. - */ - p.toString = function() { - return "[PreloadJS AbstractLoader]"; - }; - - createjs.AbstractLoader = AbstractLoader; - -}()); -/* -* LoadQueue -* Visit http://createjs.com/ for documentation, updates and examples. -* -* -* Copyright (c) 2012 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ -/** - * PreloadJS provides a consistent way to preload content for use in HTML applications. Preloading can be done using - * HTML tags, as well as XHR. - * - * By default, PreloadJS will try and load content using XHR, since it provides better support for progress and - * completion events, however due to cross-domain issues, it may still be preferable to use tag-based loading - * instead. Note that some content requires XHR to work (plain text, web audio), and some requires tags (HTML audio). - * Note this is handled automatically where possible. - * - * PreloadJS currently supports all modern browsers, and we have done our best to include support for most older - * browsers. If you find an issue with any specific OS/browser combination, please visit http://community.createjs.com/ - * and report it. - * - *

Getting Started

- * To get started, check out the {{#crossLink "LoadQueue"}}{{/crossLink}} class, which includes a quick overview of how - * to load files and process results. - * - *

Example

- * - * var queue = new createjs.LoadQueue(); - * queue.installPlugin(createjs.Sound); - * queue.on("complete", handleComplete, this); - * queue.loadFile({id:"sound", src:"http://path/to/sound.mp3"}); - * queue.loadManifest([ - * {id: "myImage", src:"path/to/myImage.jpg"} - * ]); - * function handleComplete() { - * createjs.Sound.play("sound"); - * var image = queue.getResult("myImage"); - * document.body.appendChild(image); - * } - * - * Important note on plugins: Plugins must be installed before items are added to the queue, otherwise - * they will not be processed, even if the load has not actually kicked off yet. Plugin functionality is handled when - * the items are added to the LoadQueue. - * - *

Browser Support

- * PreloadJS is partially supported in all browsers, and fully supported in all modern browsers. Known exceptions: - *
  • XHR loading of any content will not work in many older browsers (See a matrix here: http://caniuse.com/xhr2). - * In many cases, you can fall back on tag loading (images, audio, CSS, scripts, SVG, and JSONP). Text and - * WebAudio will only work with XHR.
  • - *
  • Some formats have poor support for complete events in IE 6, 7, and 8 (SVG, tag loading of scripts, XML/JSON)
  • - *
  • Opera has poor support for SVG loading with XHR
  • - *
  • CSS loading in Android and Safari will not work with tags (currently, a workaround is in progress)
  • - *
  • Local loading is not permitted with XHR, which is required by some file formats. When testing local content - * use either a local server, or enable tag loading, which is supported for most formats. See {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} - * for more information.
  • - *
- * - *

Cross-domain Loading

- * Most content types can be loaded cross-domain, as long as the server supports CORS. PreloadJS also has internal - * support for images served from a CORS-enabled server, via the `crossOrigin` argument on the {{#crossLink "LoadQueue"}}{{/crossLink}} - * constructor. If set to a string value (such as "Anonymous"), the "crossOrigin" property of images generated by - * PreloadJS is set to that value. Please note that setting a `crossOrigin` value on an image that is served from a - * server without CORS will cause other errors. For more info on CORS, visit https://en.wikipedia.org/wiki/Cross-origin_resource_sharing. - * - * @module PreloadJS - * @main PreloadJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -/* -TODO: WINDOWS ISSUES - * No error for HTML audio in IE 678 - * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR - * No script complete handler in IE 67 TAGS (XHR is fine) - * No XML/JSON in IE6 TAGS - * Need to hide loading SVG in Opera TAGS - * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking) - * SVG no load or failure in Opera XHR - * Reported issues with IE7/8 - */ - -(function() { - "use strict"; - - /** - * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either - * a single file, or queue of files. - * - * Creating a Queue
- * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the useXHR - * argument to false. - * - * var queue = new createjs.LoadQueue(true); - * - * Listening for Events
- * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}} - * lets you add as many listeners as you want for events. You can subscribe to the following events:
    - *
  • {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all - * files
  • - *
  • {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with - * any file.
  • - *
  • {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has - * changed.
  • - *
  • {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.
  • - *
  • {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note - * that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.
  • - *
- * - * queue.on("fileload", handleFileLoad, this); - * queue.on("complete", handleComplete, this); - * - * Adding files and manifests
- * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a - * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are - * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you - * like. - * - * queue.loadFile("filePath/file.jpg"); - * queue.loadFile({id:"image", src:"filePath/file.jpg"}); - * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]; - * - * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not - * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin - * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a - * `loadNow` argument of `true`. - * - * queue.load(); - * - * File Types
- * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS - * should handle the majority of standard file and url formats, and works with common file extensions. If you have - * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a - * type property with any manifest item. - * - * queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.LoadQueue.SOUND}); - * - * // Note that PreloadJS will not read a file extension from the query string - * queue.loadFile({src:"http://server.com/proxy?file=image.jpg"}, type:createjs.LoadQueue.IMAGE}); - * - * Supported types are defined on the LoadQueue class, and include: - *
    - *
  • {{#crossLink "LoadQueue/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
  • - *
  • {{#crossLink "LoadQueue/CSS:property"}}{{/crossLink}}: CSS files
  • - *
  • {{#crossLink "LoadQueue/IMAGE:property"}}{{/crossLink}}: Common image formats
  • - *
  • {{#crossLink "LoadQueue/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
  • - *
  • {{#crossLink "LoadQueue/JSON:property"}}{{/crossLink}}: JSON data
  • - *
  • {{#crossLink "LoadQueue/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
  • - *
  • {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see - * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
  • - *
  • {{#crossLink "LoadQueue/SOUND:property"}}{{/crossLink}}: Audio file formats
  • - *
  • {{#crossLink "LoadQueue/SVG:property"}}{{/crossLink}}: SVG files
  • - *
  • {{#crossLink "LoadQueue/TEXT:property"}}{{/crossLink}}: Text files - XHR only
  • - *
  • {{#crossLink "LoadQueue/XML:property"}}{{/crossLink}}: XML data
  • - *
- * - * Handling Results
- * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is - * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a - * resolved object that can be used immediately, including: - *
    - *
  • Image: An <img /> tag
  • - *
  • Audio: An <audio /> tag - *
  • JavaScript: A <script /> tag
  • - *
  • CSS: A <link /> tag
  • - *
  • XML: An XML DOM node
  • - *
  • SVG: An <object /> tag
  • - *
  • JSON: A formatted JavaScript Object
  • - *
  • Text: Raw text
  • - *
  • Binary: The binary loaded result
  • - *
- * - * function handleFileLoad(event) { - * var item = event.item; // A reference to the item that was passed in to the LoadQueue - * var type = item.type; - * - * // Add any images to the page body. - * if (type == createjs.LoadQueue.IMAGE) { - * document.body.appendChild(event.result); - * } - * } - * - * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up - * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the "src" or - * file path can be used instead, including the `path` defined by a manifest, but not including a - * base path defined on the LoadQueue. It is recommended to always pass an id. - * - * var image = queue.getResult("image"); - * document.body.appendChild(image); - * - * Raw loaded content can be accessed using the rawResult property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} - * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd - * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript, - * CSS, XML, SVG, and JSON objects, or anything loaded with XHR. - * - * var image = queue.getResult("image", true); // load the binary image data loaded with XHR. - * - * Plugins
- * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio, - * make sure to install the SoundJS Sound class, which will help load HTML audio, - * Flash audio, and WebAudio files. This should be installed before loading any audio files. - * - * queue.installPlugin(createjs.Sound); - * - *

Known Browser Issues

- *
    - *
  • Browsers without audio support can not load audio files.
  • - *
  • Safari on Mac OS X can only play HTML audio if QuickTime is installed
  • - *
  • HTML Audio tags will only download until their canPlayThrough event is fired. Browsers other - * than Chrome will continue to download in the background.
  • - *
  • When loading scripts using tags, they are automatically added to the document.
  • - *
  • Scripts loaded via XHR may not be properly inspectable with browser tools.
  • - *
  • IE6 and IE7 (and some other browsers) may not be able to load XML, Text, or JSON, since they require - * XHR to work.
  • - *
  • Content loaded via tags will not show progress, and will continue to download in the background when - * canceled, although no events will be dispatched.
  • - *
- * - * @class LoadQueue - * @param {Boolean} [useXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP - * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR - * when necessary. - * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue - * before they are loaded. Sources beginning with a protocol such as `http://` or a relative path such as `../` - * will not receive a base path. - * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To - * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any - * string value will be passed through, but only "" and "Anonymous" are recommended. - * @constructor - * @extends AbstractLoader - */ - var LoadQueue = function(useXHR, basePath, crossOrigin) { - this.init(useXHR, basePath, crossOrigin); - }; - - var p = LoadQueue.prototype = new createjs.AbstractLoader(); - var s = LoadQueue; - - /** - * Time in milliseconds to assume a load has failed. An {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} - * event is dispatched if the timeout is reached before any data is received. - * @property loadTimeout - * @type {Number} - * @default 8000 - * @static - * @since 0.4.1 - */ - s.loadTimeout = 8000; - - /** - * Time in milliseconds to assume a load has failed. - * @type {Number} - * @deprecated in favor of the {{#crossLink "LoadQueue/loadTimeout:property"}}{{/crossLink}} property. - */ - s.LOAD_TIMEOUT = 0; - -// Preload Types - /** - * 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 - */ - 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 - */ - s.CSS = "css"; - - /** - * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag. - * @property IMAGE - * @type {String} - * @default image - * @static - */ - s.IMAGE = "image"; - - /** - * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a - * <script> tag. - * - * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into - * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier, - * only tag-loaded scripts are injected. - * @property JAVASCRIPT - * @type {String} - * @default javascript - * @static - */ - s.JAVASCRIPT = "javascript"; - - /** - * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a - * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP, - * no matter what the {{#crossLink "LoadQueue/useXHR:property"}}{{/crossLink}} property is set to, and the JSON - * must contain a matching wrapper function. - * @property JSON - * @type {String} - * @default json - * @static - */ - s.JSON = "json"; - - /** - * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a - * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON. - * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/useXHR:property"}}{{/crossLink}} - * property is set to. - * @property JSONP - * @type {String} - * @default jsonp - * @static - */ - s.JSONP = "jsonp"; - - /** - * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded - * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an - * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead, - * regardless of what the {{#crossLink "LoadQueue/useXHR:property"}}{{/crossLink}} property is set to. - * @property MANIFEST - * @type {String} - * @default manifest - * @static - * @since 0.4.1 - */ - s.MANIFEST = "manifest"; - - /** - * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an - * <audio> tag. - * @property SOUND - * @type {String} - * @default sound - * @static - */ - s.SOUND = "sound"; - - /** - * The preload type for SVG files. - * @property SVG - * @type {String} - * @default svg - * @static - */ - s.SVG = "svg"; - - /** - * The preload type for text files, which is also the default file type if the type can not be determined. Text is - * loaded as raw text. - * @property TEXT - * @type {String} - * @default text - * @static - */ - s.TEXT = "text"; - - /** - * The preload type for xml files. XML is loaded into an XML document. - * @property XML - * @type {String} - * @default xml - * @static - */ - s.XML = "xml"; - - /** - * Defines a POST request, use for a method value when loading data. - * - * @type {string} - */ - s.POST = 'POST'; - - /** - * Defines a GET request, use for a method value when loading data. - * - * @type {string} - */ - s.GET = 'GET'; - - -// Prototype - /** - * A path that will be prepended on to the item's `src`. The `_basePath` property will only be used if an item's - * source is relative, and does not include a protocol such as `http://`, or a relative path such as `../`. - * @property _basePath - * @type {String} - * @private - * @since 0.3.1 - */ - p._basePath = null; - - /** - * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded - * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by - * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues, - * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are "" - * and "Anonymous". - * @property _crossOrigin - * @type {String} - * @defaultValue "" - * @private - * @since 0.4.1 - */ - p._crossOrigin = ""; - - /** - * Use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR loading depending - * on the requirements for a media type. For example, HTML audio can not be loaded with XHR, and WebAudio can not be - * loaded with tags, so it will default the the correct type instead of using the user-defined type. - * - * Note: This property is read-only. To change it, please use the {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} - * method, or specify the `useXHR` argument in the LoadQueue constructor. - * - * @property useXHR - * @type {Boolean} - * @readOnly - * @default true - */ - p.useXHR = true; - - /** - * Determines if the LoadQueue will stop processing the current queue when an error is encountered. - * @property stopOnError - * @type {Boolean} - * @default false - */ - p.stopOnError = false; - - /** - * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head - * once they are loaded. Note that scripts loaded via tags will load one-at-a-time when this property is `true`. - * load one at a time - * @property maintainScriptOrder - * @type {Boolean} - * @default true - */ - p.maintainScriptOrder = true; - - /** - * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and - * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed. - * @property next - * @type {LoadQueue} - * @default null - */ - p.next = null; - -// Events - /** - * This event is fired when an individual file has loaded, and been processed. - * @event fileload - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the - * object will contain that value as a `src` property. - * @param {Object} result The HTML tag or parsed result of the loaded item. - * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted - * to a usable object. - * @since 0.3.0 - */ - - /** - * This event is fired when an an individual file progress changes. - * @event fileprogress - * @param {Object} The object that dispatched the event. - * @param {String} type The event type. - * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the - * object will contain that value as a `src` property. - * @param {Number} loaded The number of bytes that have been loaded. Note that this may just be a percentage of 1. - * @param {Number} total The total number of bytes. If it is unknown, the value is 1. - * @param {Number} progress The amount that has been loaded between 0 and 1. - * @since 0.3.0 - */ - - /** - * This event is fired when an individual file starts to load. - * @event filestart - * @param {Object} The object that dispatched the event. - * @param {String} type The event type. - * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the - * object will contain that value as a property. - */ - - //TODO: Deprecated - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} - * event. - * @property onFileLoad - * @type {Function} - * @deprecated Use addEventListener and the "fileload" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}} - * event. - * @property onFileProgress - * @type {Function} - * @deprecated Use addEventListener and the "fileprogress" event. - */ - - -// Protected - /** - * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the - * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} - * method for more information. - * @property _typeCallbacks - * @type {Object} - * @private - */ - p._typeCallbacks = null; - - /** - * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the - * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} - * method for more information. - * @property _extensionCallbacks - * @type {null} - * @private - */ - p._extensionCallbacks = null; - - /** - * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first - * file is requested. - * @property _loadStartWasDispatched - * @type {Boolean} - * @default false - * @private - */ - p._loadStartWasDispatched = false; - - /** - * The number of maximum open connections that a loadQueue tries to maintain. Please see - * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information. - * @property _maxConnections - * @type {Number} - * @default 1 - * @private - */ - p._maxConnections = 1; - - /** - * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when - * using a script tag to do preloading. - * @property _currentlyLoadingScript - * @type {Boolean} - * @private - */ - p._currentlyLoadingScript = null; - - /** - * An array containing the currently downloading files. - * @property _currentLoads - * @type {Array} - * @private - */ - p._currentLoads = null; - - /** - * An array containing the queued items that have not yet started downloading. - * @property _loadQueue - * @type {Array} - * @private - */ - p._loadQueue = null; - - /** - * An array containing downloads that have not completed, so that the LoadQueue can be properly reset. - * @property _loadQueueBackup - * @type {Array} - * @private - */ - p._loadQueueBackup = null; - - /** - * An object hash of items that have finished downloading, indexed by item IDs. - * @property _loadItemsById - * @type {Object} - * @private - */ - p._loadItemsById = null; - - /** - * An object hash of items that have finished downloading, indexed by item source. - * @property _loadItemsBySrc - * @type {Object} - * @private - */ - p._loadItemsBySrc = null; - - /** - * An object hash of loaded items, indexed by the ID of the load item. - * @property _loadedResults - * @type {Object} - * @private - */ - p._loadedResults = null; - - /** - * An object hash of un-parsed loaded items, indexed by the ID of the load item. - * @property _loadedRawResults - * @type {Object} - * @private - */ - p._loadedRawResults = null; - - /** - * The number of items that have been requested. This helps manage an overall progress without knowing how large - * the files are before they are downloaded. - * @property _numItems - * @type {Number} - * @default 0 - * @private - */ - p._numItems = 0; - - /** - * The number of items that have completed loaded. This helps manage an overall progress without knowing how large - * the files are before they are downloaded. - * @property _numItemsLoaded - * @type {Number} - * @default 0 - * @private - */ - p._numItemsLoaded = 0; - - /** - * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right - * order. - * @property _scriptOrder - * @type {Array} - * @private - */ - p._scriptOrder = null; - - /** - * A list of scripts that have been loaded. Items are added to this list as null when they are - * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true - * once they are complete and have been dispatched. - * @property _loadedScripts - * @type {Array} - * @private - */ - p._loadedScripts = null; - - // Overrides abstract method in AbstractLoader - p.init = function(useXHR, basePath, crossOrigin) { - this._numItems = this._numItemsLoaded = 0; - this._paused = false; - this._loadStartWasDispatched = false; - - this._currentLoads = []; - this._loadQueue = []; - this._loadQueueBackup = []; - this._scriptOrder = []; - this._loadedScripts = []; - this._loadItemsById = {}; - this._loadItemsBySrc = {}; - this._loadedResults = {}; - this._loadedRawResults = {}; - - // Callbacks for plugins - this._typeCallbacks = {}; - this._extensionCallbacks = {}; - - this._basePath = basePath; - this.setUseXHR(useXHR); - this._crossOrigin = (crossOrigin === true) - ? "Anonymous" : (crossOrigin === false || crossOrigin == null) - ? "" : crossOrigin; - }; - - /** - * Change the usXHR value. Note that if this is set to true, it may fail depending on the browser's capabilities. - * Additionally, some files require XHR in order to load, such as JSON (without JSONP), Text, and XML, so XHR will - * be used regardless of what is passed to this method. - * @method setUseXHR - * @param {Boolean} value The new useXHR value to set. - * @return {Boolean} The new useXHR value. If XHR is not supported by the browser, this will return false, even if - * the provided value argument was true. - * @since 0.3.0 - */ - p.setUseXHR = function(value) { - // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it. - //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR. - this.useXHR = (value != false && window.XMLHttpRequest != null); - return this.useXHR; - }; - - /** - * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded - * content, and allows the queue to be used again. - * @method removeAll - * @since 0.3.0 - */ - p.removeAll = function() { - this.remove(); - }; - - /** - * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed. - * This also removes internal references to loaded item(s). - * - *

Example

- * - * queue.loadManifest([ - * {src:"test.png", id:"png"}, - * {src:"test.jpg", id:"jpg"}, - * {src:"test.mp3", id:"mp3"} - * ]); - * queue.remove("png"); // Single item by ID - * queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src. - * queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src. - * - * @method remove - * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of - * items, or multiple items as arguments. - * @since 0.3.0 - */ - p.remove = function(idsOrUrls) { - var args = null; - - if (idsOrUrls && !(idsOrUrls instanceof Array)) { - args = [idsOrUrls]; - } else if (idsOrUrls) { - args = idsOrUrls; - } else if (arguments.length > 0) { - return; - } - - var itemsWereRemoved = false; - - // Destroy everything - if (!args) { - this.close(); - for (var n in this._loadItemsById) { - this._disposeItem(this._loadItemsById[n]); - } - this.init(this.useXHR); - - // Remove specific items - } else { - while (args.length) { - var item = args.pop(); - var r = this.getResult(item); - - //Remove from the main load Queue - for (i = this._loadQueue.length-1;i>=0;i--) { - loadItem = this._loadQueue[i].getItem(); - if (loadItem.id == item || loadItem.src == item) { - this._loadQueue.splice(i,1)[0].cancel(); - break; - } - } - - //Remove from the backup queue - for (i = this._loadQueueBackup.length-1;i>=0;i--) { - loadItem = this._loadQueueBackup[i].getItem(); - if (loadItem.id == item || loadItem.src == item) { - this._loadQueueBackup.splice(i,1)[0].cancel(); - break; - } - } - - if (r) { - delete this._loadItemsById[r.id]; - delete this._loadItemsBySrc[r.src]; - this._disposeItem(r); - } else { - for (var i=this._currentLoads.length-1;i>=0;i--) { - var loadItem = this._currentLoads[i].getItem(); - if (loadItem.id == item || loadItem.src == item) { - this._currentLoads.splice(i,1)[0].cancel(); - itemsWereRemoved = true; - break; - } - } - } - } - - // If this was called during a load, try to load the next item. - if (itemsWereRemoved) { - this._loadNext(); - } - } - }; - - /** - * Stops all open loads, destroys any loaded items, and resets the queue, so all items can - * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the - * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or - * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method. - * @method reset - * @since 0.3.0 - */ - p.reset = function() { - this.close(); - for (var n in this._loadItemsById) { - this._disposeItem(this._loadItemsById[n]); - } - - //Reset the queue to its start state - var a = []; - for (var i=0, l=this._loadQueueBackup.length; inot a binary type, as we can not play - * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get - * a binary result to work with. Binary files are loaded using XHR2. - * @method isBinary - * @param {String} type The item type. - * @return {Boolean} If the specified type is binary. - * @private - */ - s.isBinary = function(type) { - switch (type) { - case createjs.LoadQueue.IMAGE: - case createjs.LoadQueue.BINARY: - return true; - default: - return false; - } - }; - - - /** - * 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. - * @private - */ - s.isText = function(type) { - switch (type) { - case createjs.LoadQueue.TEXT: - case createjs.LoadQueue.JSON: - case createjs.LoadQueue.MANIFEST: - case createjs.LoadQueue.XML: - case createjs.LoadQueue.HTML: - case createjs.LoadQueue.CSS: - case createjs.LoadQueue.SVG: - case createjs.LoadQueue.JAVASCRIPT: - return true; - default: - return false; - } - }; - - /** - * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc). - * Currently, only one plugin can exist per type/extension. - * - * When a plugin is installed, a getPreloadHandlers() method will be called on it. For more information - * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the - * {{#crossLink "SamplePlugin"}}{{/crossLink}} class. - * - * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned - * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its - * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when - * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these - * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}} - * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}. - * - * @method installPlugin - * @param {Function} plugin The plugin class to install. - */ - p.installPlugin = function(plugin) { - if (plugin == null || plugin.getPreloadHandlers == null) { return; } - var map = plugin.getPreloadHandlers(); - map.scope = plugin; - - if (map.types != null) { - for (var i=0, l=map.types.length; iExample - * - * var queue = new createjs.LoadQueue(); - * queue.setMaxConnections(10); // Allow 10 concurrent loads - * - * @method setMaxConnections - * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue - * is open at any time. - */ - p.setMaxConnections = function (value) { - this._maxConnections = value; - if (!this._paused && this._loadQueue.length > 0) { - this._loadNext(); - } - }; - - /** - * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * method. - * - * Files are always appended to the current queue, so this method can be used multiple times to add files. - * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method. - * @method loadFile - * @param {Object | String} file The file object or path to load. A file can be either - *
    - *
  • A string path to a resource. Note that this kind of load item will be converted to an object (see below) - * in the background.
  • - *
  • OR an object that contains:
      - *
    • src: The source of the file that is being loaded. This property is required. The source can - * either be a string (recommended), or an HTML tag.
    • - *
    • type: The type of file that will be loaded (image, sound, json, etc). PreloadJS does auto-detection - * of types using the extension. Supported types are defined on LoadQueue, such as LoadQueue.IMAGE. - * It is recommended that a type is specified when a non-standard file URI (such as a php script) us used.
    • - *
    • id: A string identifier which can be used to reference the loaded object.
    • - *
    • callback: Optional, used for JSONP requests, to define what method to call when the JSONP is loaded.
    • - *
    • data: An arbitrary data object, which is included with the loaded object
    • - *
    • method: used to define if this request uses GET or POST when sending data to the server. The default - * value is "GET"
    • - *
    • values: Optional object of name/value pairs to send to the server.
    • - *
    - *
- * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default - * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is - * `true`, the queue will resume automatically. - * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the - * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}}, - * its files will NOT use the basePath parameter. The basePath parameter is deprecated. - * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue - * constructor, or a `path` property in a manifest definition. - */ - p.loadFile = function(file, loadNow, basePath) { - if (file == null) { - var event = new createjs.Event("error"); - event.text = "PRELOAD_NO_FILE"; - this._sendError(event); - return; - } - this._addItem(file, null, basePath); - - if (loadNow !== false) { - this.setPaused(false); - } else { - this.setPaused(true); - } - }; - - /** - * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method. - * The files in the manifest are requested in the same order, but may complete in a different order if the max - * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load - * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is - * default). - * - * Files are always appended to the current queue, so this method can be used multiple times to add files. - * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method. - * @method loadManifest - * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of - * manifests: - *
    - *
  1. A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property, - * which defines the list of files to load, and can optionally contain a "path" property, which will be - * prepended to each file in the list.
  2. - *
  3. An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP - * file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load, - * and can optionally contain a "path" property, which will be prepended to each file in the list.
  4. - *
  5. An object which contains a "manifest" property, which defines the list of files to load, and can - * optionally contain a "path" property, which will be prepended to each file in the list.
  6. - *
  7. An Array of files to load.
  8. - *
- * - * Each "file" in a manifest can be either: - *
    - *
  • A string path to a resource (string). Note that this kind of load item will be converted to an object - * (see below) in the background.
  • - *
  • OR an object that contains:
      - *
    • src: The source of the file that is being loaded. This property is required. The source can - * either be a string (recommended), or an HTML tag.
    • - *
    • type: The type of file that will be loaded (image, sound, json, etc). PreloadJS does auto-detection - * of types using the extension. Supported types are defined on LoadQueue, such as LoadQueue.IMAGE. - * It is recommended that a type is specified when a non-standard file URI (such as a php script) us used.
    • - *
    • id: A string identifier which can be used to reference the loaded object.
    • - *
    • callback: Optional, used for JSONP requests, to define what method to call when the JSONP is loaded.
    • - *
    • data: An arbitrary data object, which is included with the loaded object
    • - *
    • method: used to define if this request uses GET or POST when sending data to the server. The default - * value is "GET"
    • - *
    • values: Optional object of name/value pairs to send to the server.
    • - *
    - *
- * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default - * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is - * `true`, the queue will resume automatically. - * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the - * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}}, - * its files will NOT use the basePath parameter. The basePath parameter is deprecated. - * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue - * constructor, or a `path` property in a manifest definition. - */ - p.loadManifest = function(manifest, loadNow, basePath) { - var fileList = null; - var path = null; - - // Array-based list of items - if (manifest instanceof Array) { - if (manifest.length == 0) { - var event = new createjs.Event("error"); - event.text = "PRELOAD_MANIFEST_EMPTY"; - this._sendError(event); - return; - } - fileList = manifest; - - // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded. - } else if (typeof(manifest) === "string") { - fileList = [{ - src: manifest, - type: s.MANIFEST - }]; - - } else if (typeof(manifest) == "object") { - - // An object that defines a manifest path - if (manifest.src !== undefined) { - if (manifest.type == null) { - manifest.type = s.MANIFEST; - } else if (manifest.type != s.MANIFEST) { - var event = new createjs.Event("error"); - event.text = "PRELOAD_MANIFEST_ERROR"; - this._sendError(event); - } - fileList = [manifest]; - - // An object that defines a manifest - } else if (manifest.manifest !== undefined) { - fileList = manifest.manifest; - path = manifest.path; - } - - // Unsupported. This will throw an error. - } else { - var event = new createjs.Event("error"); - event.text = "PRELOAD_MANIFEST_NULL"; - this._sendError(event); - return; - } - - for (var i=0, l=fileList.length; iid
or src of the load item. - * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} - * event as the `item` parameter. - */ - p.getItem = function(value) { - return this._loadItemsById[value] || this._loadItemsBySrc[value]; - }; - - /** - * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id" - * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The - * `basePath` will not be part of the ID. - * @method getResult - * @param {String} value The id or src of the load item. - * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content - * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be - * returned instead. - * @return {Object} A result object containing the content that was loaded, such as: - *
    - *
  • An image tag (<image />) for images
  • - *
  • A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML - * DOM.
  • - *
  • A style tag for CSS (<style /> or <link >)
  • - *
  • Raw text for TEXT
  • - *
  • A formatted JavaScript object defined by JSON
  • - *
  • An XML document
  • - *
  • A binary arraybuffer loaded by XHR
  • - *
  • An audio tag (<audio >) for HTML audio. Note that it is recommended to use SoundJS APIs to play - * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method - * which can not be used to play audio back.
  • - *
- * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item` - * parameter. Note that if a raw result is requested, but not found, the result will be returned instead. - */ - p.getResult = function(value, rawResult) { - var item = this._loadItemsById[value] || this._loadItemsBySrc[value]; - if (item == null) { return null; } - var id = item.id; - if (rawResult && this._loadedRawResults[id]) { - return this._loadedRawResults[id]; - } - return this._loadedResults[id]; - }; - - /** - * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not - * be processed when active loads complete. LoadQueues are not paused by default. - * - * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, - * a paused queue will be resumed, unless the `loadNow` argument is `false`. - * @method setPaused - * @param {Boolean} value Whether the queue should be paused or not. - */ - p.setPaused = function(value) { - this._paused = value; - if (!this._paused) { - this._loadNext(); - } - }; - - // Overrides abstract method in AbstractLoader - p.close = function() { - while (this._currentLoads.length) { - this._currentLoads.pop().cancel(); - } - this._scriptOrder.length = 0; - this._loadedScripts.length = 0; - this.loadStartWasDispatched = false; - }; - - -//Protected Methods - /** - * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to - * load the content. The load queue is populated with the loader instance that handles preloading, and not the load - * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}} - * method. - * @method _addItem - * @param {String|Object} value The item to add to the queue. - * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is - * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was - * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after. - * @param {String} [basePath] DeprecatedAn optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged - * version. - * @private - */ - p._addItem = function(value, path, basePath) { - var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src. - if (item == null) { return; } // Sometimes plugins or types should be skipped. - var loader = this._createLoader(item); - if (loader != null) { - this._loadQueue.push(loader); - this._loadQueueBackup.push(loader); - - this._numItems++; - this._updateProgress(); - - // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time. - if (this.maintainScriptOrder - && item.type == createjs.LoadQueue.JAVASCRIPT - && loader instanceof createjs.XHRLoader) { - this._scriptOrder.push(item); - this._loadedScripts.push(null); - } - } - }; - - /** - * Create a refined load item, which contains all the required properties (src, type, extension, tag). The type of - * item is determined by browser support, requirements based on the file type, and developer settings. For example, - * XHR is only used for file types that support it in new browsers. - * - * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may - * alter the load item. - * @method _createLoadItem - * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded. - * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will - * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}} - * when it is added. - * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to - * the path argument. - * @return {Object} The loader instance that will be used. - * @private - */ - p._createLoadItem = function(value, path, basePath) { - var item = null; - - // Create/modify a load item - switch(typeof(value)) { - case "string": - item = { - src: value - }; break; - case "object": - if (window.HTMLAudioElement && value instanceof window.HTMLAudioElement) { - item = { - tag: value, - src: item.tag.src, - type: createjs.LoadQueue.SOUND - }; - } else { - item = value; - } - break; - default: - return null; - } - - // Determine Extension, etc. - var match = this._parseURI(item.src); - if (match != null) { item.ext = match[6]; } - if (item.type == null) { - item.type = this._getTypeByExtension(item.ext); - } - - // Inject path & basePath - var bp = ""; // Store the generated basePath - var useBasePath = basePath || this._basePath; - var autoId = item.src; - if (match && match[1] == null && match[3] == null) { - if (path) { - bp = path; - var pathMatch = this._parsePath(path); - autoId = path + autoId; - // Also append basePath - if (useBasePath != null && pathMatch && pathMatch[1] == null && pathMatch[2] == null) { - bp = useBasePath + bp; - } - } else if (useBasePath != null) { - bp = useBasePath; - } - } - item.src = bp + item.src; - item.path = bp; - - if (item.type == createjs.LoadQueue.JSON || item.type == createjs.LoadQueue.MANIFEST) { - item._loadAsJSONP = (item.callback != null); - } - - if (item.type == createjs.LoadQueue.JSONP && item.callback == null) { - throw new Error('callback is required for loading JSONP requests.'); - } - - // Create a tag for the item. This ensures there is something to either load with or populate when finished. - if (item.tag === undefined || item.tag === null) { - item.tag = this._createTag(item); - } - - // If there's no id, set one now. - if (item.id === undefined || item.id === null || item.id === "") { - item.id = autoId; - } - - // Give plugins a chance to modify the loadItem: - var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext]; - if (customHandler) { - // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately) - var result = customHandler.callback.call(customHandler.scope, item.src, item.type, item.id, item.data, - bp, this); - // NOTE: BasePath argument is deprecated. We pass it to plugins.allow SoundJS to modify the file. to sanymore. The full path is sent to the plugin - - // The plugin will handle the load, or has canceled it. Ignore it. - if (result === false) { - return null; - - // Load as normal: - } else if (result === true) { - // Do Nothing - - // Result is a loader class: - } else { - if (result.src != null) { item.src = result.src; } - if (result.id != null) { item.id = result.id; } // TODO: Evaluate this. An overridden ID could be problematic - if (result.tag != null) { // Assumes that the returned tag either has a load method or a src setter. - item.tag = result.tag; - } - if (result.completeHandler != null) { item.completeHandler = result.completeHandler; } - - // Allow type overriding: - if (result.type) { item.type = result.type; } - - // Update the extension in case the type changed: - match = this._parseURI(item.src); - if (match != null && match[6] != null) { - item.ext = match[6].toLowerCase(); - } - } - } - - // Store the item for lookup. This also helps clean-up later. - this._loadItemsById[item.id] = item; - this._loadItemsBySrc[item.src] = item; - - return item; - }; - - /** - * Create a loader for a load item. - * @method _createLoader - * @param {Object} item A formatted load item that can be used to generate a loader. - * @return {AbstractLoader} A loader that can be used to load content. - * @private - */ - p._createLoader = function(item) { - // Initially, try and use the provided/supported XHR mode: - var useXHR = this.useXHR; - - // Determine the XHR usage overrides: - switch (item.type) { - case createjs.LoadQueue.JSON: - case createjs.LoadQueue.MANIFEST: - useXHR = !item._loadAsJSONP; - break; - case createjs.LoadQueue.XML: - case createjs.LoadQueue.TEXT: - useXHR = true; // Always use XHR2 with text/XML - break; - case createjs.LoadQueue.SOUND: - case createjs.LoadQueue.JSONP: - useXHR = false; // Never load audio using XHR. WebAudio will provide its own loader. - break; - case null: - return null; - // Note: IMAGE, CSS, SCRIPT, SVG can all use TAGS or XHR. - } - - if (useXHR) { - return new createjs.XHRLoader(item, this._crossOrigin); - } else { - return new createjs.TagLoader(item); - } - }; - - - /** - * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event - * is processed. The queue will "fill up" any empty slots, up to the max connection specified using - * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded - * using tags, which have to be loaded one at a time to maintain load order. - * @method _loadNext - * @private - */ - p._loadNext = function() { - if (this._paused) { return; } - - // Only dispatch loadstart event when the first file is loaded. - if (!this._loadStartWasDispatched) { - this._sendLoadStart(); - this._loadStartWasDispatched = true; - } - - // The queue has completed. - if (this._numItems == this._numItemsLoaded) { - this.loaded = true; - this._sendComplete(); - - // Load the next queue, if it has been defined. - if (this.next && this.next.load) { - this.next.load(); - } - } else { - this.loaded = false; - } - - // Must iterate forwards to load in the right order. - for (var i=0; i= this._maxConnections) { break; } - var loader = this._loadQueue[i]; - - // Determine if we should be only loading one at a time: - if (this.maintainScriptOrder - && loader instanceof createjs.TagLoader - && loader.getItem().type == createjs.LoadQueue.JAVASCRIPT) { - if (this._currentlyLoadingScript) { continue; } // Later items in the queue might not be scripts. - this._currentlyLoadingScript = true; - } - this._loadQueue.splice(i, 1); - i--; - this._loadItem(loader); - } - }; - - /** - * Begin loading an item. Events are not added to the loaders until the load starts. - * @method _loadItem - * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader. - * @private - */ - p._loadItem = function(loader) { - loader.on("progress", this._handleProgress, this); - loader.on("complete", this._handleFileComplete, this); - loader.on("error", this._handleFileError, this); - this._currentLoads.push(loader); - this._sendFileStart(loader.getItem()); - loader.load(); - }; - - /** - * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} - * is set to `true`. - * @method _handleFileError - * @param {Object} event The error event, containing relevant error information. - * @private - */ - p._handleFileError = function(event) { - var loader = event.target; - this._numItemsLoaded++; - this._updateProgress(); - - var newEvent = new createjs.Event("error"); - newEvent.text = "FILE_LOAD_ERROR"; - newEvent.item = loader.getItem(); - // TODO: Propagate actual error message. - - this._sendError(newEvent); - - if (!this.stopOnError) { - this._removeLoadItem(loader); - this._loadNext(); - } - }; - - /** - * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and - * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML, - * CSS, JavaScript, etc) is available as the "rawResult" event, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. - * @method _handleFileComplete - * @param {Object} event The event object from the loader. - * @private - */ - p._handleFileComplete = function(event) { - var loader = event.target; - var item = loader.getItem(); - - this._loadedResults[item.id] = loader.getResult(); - if (loader instanceof createjs.XHRLoader) { - this._loadedRawResults[item.id] = loader.getResult(true); - } - - this._removeLoadItem(loader); - - // Ensure that script loading happens in the right order. - if (this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT) { - if (loader instanceof createjs.TagLoader) { - this._currentlyLoadingScript = false; - } else { - this._loadedScripts[createjs.indexOf(this._scriptOrder, item)] = item; - this._checkScriptLoadOrder(loader); - return; - } - } - - // Clean up the load item - delete item._loadAsJSONP; - - // If the item was a manifest, then - if (item.type == createjs.LoadQueue.MANIFEST) { - var result = loader.getResult(); - if (result != null && result.manifest !== undefined) { - this.loadManifest(result, true); - } - } - - this._processFinishedLoad(item, loader); - }; - - /** - * @method _processFinishedLoad - * @param {Object} item - * @param {AbstractLoader} loader - * @protected - */ - p._processFinishedLoad = function(item, loader) { - // Old handleFileTagComplete follows here. - this._numItemsLoaded++; - - this._updateProgress(); - this._sendFileComplete(item, loader); - - this._loadNext(); - }; - - /** - * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the - * order they were added, but with a "null" value. When they are completed, the value is set to the load item, - * and then when they are processed and dispatched, the value is set to true. This method simply - * iterates the array, and ensures that any loaded items that are not preceded by a null value are - * dispatched. - * @method _checkScriptLoadOrder - * @private - */ - p._checkScriptLoadOrder = function () { - var l = this._loadedScripts.length; - - for (var i=0;i - *
  • 5/10 of the items in the queue (50%)
  • - *
  • plus 20% of item 6's slot (2%)
  • - *
  • equals 52%
  • - * @method _updateProgress - * @private - */ - p._updateProgress = function () { - var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress - var remaining = this._numItems-this._numItemsLoaded; - if (remaining > 0) { - var chunk = 0; - for (var i=0, l=this._currentLoads.length; iLoadQueue.IMAGE
    or null if it can not be - * determined by the extension. - * @private - */ - p._getTypeByExtension = function(extension) { - if (extension == null) { - return createjs.LoadQueue.TEXT; - } - switch (extension.toLowerCase()) { - case "jpeg": - case "jpg": - case "gif": - case "png": - case "webp": - case "bmp": - return createjs.LoadQueue.IMAGE; - case "ogg": - case "mp3": - case "wav": - return createjs.LoadQueue.SOUND; - case "json": - return createjs.LoadQueue.JSON; - case "xml": - return createjs.LoadQueue.XML; - case "css": - return createjs.LoadQueue.CSS; - case "js": - return createjs.LoadQueue.JAVASCRIPT; - case 'svg': - return createjs.LoadQueue.SVG; - default: - return createjs.LoadQueue.TEXT; - } - }; - - /** - * Dispatch a fileprogress event (and onFileProgress callback). Please see the LoadQueue.fileprogress - * event for details on the event payload. - * @method _sendFileProgress - * @param {Object} item The item that is being loaded. - * @param {Number} progress The amount the item has been loaded (between 0 and 1). - * @protected - */ - p._sendFileProgress = function(item, progress) { - if (this._isCanceled()) { - this._cleanUp(); - return; - } - if (!this.hasEventListener("fileprogress")) { return; } - - var event = new createjs.Event("fileprogress"); - event.progress = progress; - event.loaded = progress; - event.total = 1; - event.item = item; - - this.dispatchEvent(event); - }; - - /** - * Dispatch a fileload event. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for - * details on the event payload. - * @method _sendFileComplete - * @param {Object} item The item that is being loaded. - * @param {TagLoader | XHRLoader} loader - * @protected - */ - p._sendFileComplete = function(item, loader) { - if (this._isCanceled()) { return; } - - var event = new createjs.Event("fileload"); - event.loader = loader; - event.item = item; - event.result = this._loadedResults[item.id]; - event.rawResult = this._loadedRawResults[item.id]; - - // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this. - if (item.completeHandler) { - item.completeHandler(event); - } - - this.hasEventListener("fileload") && this.dispatchEvent(event) - }; - - /** - * Dispatch a filestart event immediately before a file starts to load. Please see the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} - * event for details on the event payload. - * @method _sendFileStart - * @param {Object} item The item that is being loaded. - * @protected - */ - p._sendFileStart = function(item) { - var event = new createjs.Event("filestart"); - event.item = item; - this.hasEventListener("filestart") && this.dispatchEvent(event); - }; - - /** - * REMOVED. Use createjs.proxy instead - * @method proxy - * @param {Function} method The function to call - * @param {Object} scope The scope to call the method name on - * @static - * @private - * @deprecated In favour of the createjs.proxy method (see LoadQueue source). - */ - - p.toString = function() { - return "[PreloadJS LoadQueue]"; - }; - - createjs.LoadQueue = LoadQueue; - - -// Helper methods - - // An additional module to determine the current browser, version, operating system, and other environmental variables. - var BrowserDetect = function() {} - - BrowserDetect.init = function() { - var agent = navigator.userAgent; - BrowserDetect.isFirefox = (agent.indexOf("Firefox") > -1); - BrowserDetect.isOpera = (window.opera != null); - BrowserDetect.isChrome = (agent.indexOf("Chrome") > -1); - BrowserDetect.isIOS = agent.indexOf("iPod") > -1 || agent.indexOf("iPhone") > -1 || agent.indexOf("iPad") > -1; - }; - - BrowserDetect.init(); - - createjs.LoadQueue.BrowserDetect = BrowserDetect; - -}()); -/* -* TagLoader -* Visit http://createjs.com/ for documentation, updates and examples. -* -* -* Copyright (c) 2012 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * @module PreloadJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - /** - * A preloader that loads items using a tag-based approach. HTML audio and images can use this loader to load - * content cross-domain without security errors, whereas anything loaded with XHR has potential issues with cross- - * domain requests. - * - * Note for audio tags, TagLoader relies on the canPlayThrough event, which fires when the buffer - * is full enough to play the audio all the way through at the current download speed. This completely preloads most - * sound effects, however longer tracks like background audio will only load a portion before the event is fired. - * Most browsers (all excluding Chrome) will continue to preload once this is fired, so this is considered good - * enough for most cases. - * @class TagLoader - * @constructor - * @extends AbstractLoader - * @param {Object} item The item to load. Please see {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} for - * information on load items. - */ - var TagLoader = function (item) { - this.init(item); - }; - - var p = TagLoader.prototype = new createjs.AbstractLoader(); - -// Protected - - /** - * The timeout that is fired if nothing is loaded after a certain delay. See the LoadQueue.LOAD_TIMEOUT - * for the timeout duration. - * @property _loadTimeout - * @type {Number} - * @private - */ - p._loadTimeout = null; - - /** - * A reference to a bound function, which we need in order to properly remove the event handler when the load - * completes. - * @property _tagCompleteProxy - * @type {Function} - * @private - */ - p._tagCompleteProxy = null; - - /** - * Determines if the load item is an audio tag, since we take some specific approaches to properly load audio. - * @property _isAudio - * @type {Boolean} - * @default false - * @protected - */ - p._isAudio = false; - - /** - * The HTML tag or JavaScript object this loader uses to preload content. Note that a tag may be a custom object - * that matches the API of an HTML tag (load method, onload callback). For example, flash audio from SoundJS passes - * in a custom object to handle preloading for Flash audio and WebAudio. - * @property _tag - * @type {HTMLAudioElement | Object} - * @private - */ - p._tag = null; - - /** - * When loading a JSONP request this will be the parsed JSON result. - * - * @type {Object} - * @private - */ - p._jsonResult = null; - - // Overrides abstract method in AbstractLoader - p.init = function (item) { - this._item = item; - this._tag = item.tag; - this._isAudio = (window.HTMLAudioElement && item.tag instanceof window.HTMLAudioElement); - this._tagCompleteProxy = createjs.proxy(this._handleLoad, this); - }; - - /** - * Get the loaded content. This is usually an HTML tag or other tag-style object that has been fully loaded. If the - * loader is not complete, this will be null. - * @method getResult - * @return {HTMLImageElement | HTMLAudioElement | Object} The loaded and parsed content. - */ - p.getResult = function() { - if (this._item.type == createjs.LoadQueue.JSONP || this._item.type == createjs.LoadQueue.MANIFEST) { - return this._jsonResult; - } else { - return this._tag; - } - }; - - // Overrides abstract method in AbstractLoader - p.cancel = function() { - this.canceled = true; - this._clean(); - }; - - // Overrides abstract method in AbstractLoader - p.load = function() { - var item = this._item; - var tag = this._tag; - - clearTimeout(this._loadTimeout); // Clear out any existing timeout - var duration = createjs.LoadQueue.LOAD_TIMEOUT; - if (duration == 0) { duration = createjs.LoadQueue.loadTimeout; } - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), duration); - - if (this._isAudio) { - tag.src = null; // Unset the source so we can set the preload type to "auto" without kicking off a load. This is only necessary for audio tags passed in by the developer. - tag.preload = "auto"; - } - - // Handlers for all tags - tag.onerror = createjs.proxy(this._handleError, this); - // Note: We only get progress events in Chrome, but do not fully load tags in Chrome due to its behaviour, so we ignore progress. - - if (this._isAudio) { - tag.onstalled = createjs.proxy(this._handleStalled, this); - // This will tell us when audio is buffered enough to play through, but not when its loaded. - // The tag doesn't keep loading in Chrome once enough has buffered, and we have decided that behaviour is sufficient. - tag.addEventListener("canplaythrough", this._tagCompleteProxy, false); // canplaythrough callback doesn't work in Chrome, so we use an event. - } else { - tag.onload = createjs.proxy(this._handleLoad, this); - tag.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this); - } - - var src = this.buildPath(item.src, item.values); - - // Set the src after the events are all added. - switch(item.type) { - case createjs.LoadQueue.CSS: - tag.href = src; - break; - case createjs.LoadQueue.SVG: - tag.data = src; - break; - default: - tag.src = src; - } - - // If we're loading JSONP, we need to add our callback now. - if (item.type == createjs.LoadQueue.JSONP - || item.type == createjs.LoadQueue.JSON - || item.type == createjs.LoadQueue.MANIFEST) { - if (item.callback == null) { - throw new Error('callback is required for loading JSONP requests.'); - } - - if (window[item.callback] != null) { - throw new Error('JSONP callback "' + item.callback + '" already exists on window. You need to specify a different callback. Or re-name the current one.'); - } - - window[item.callback] = createjs.proxy(this._handleJSONPLoad, this); - } - - // If its SVG, it needs to be on the DOM to load (we remove it before sending complete). - // It is important that this happens AFTER setting the src/data. - if (item.type == createjs.LoadQueue.SVG || - item.type == createjs.LoadQueue.JSONP || - item.type == createjs.LoadQueue.JSON || - item.type == createjs.LoadQueue.MANIFEST || - item.type == createjs.LoadQueue.JAVASCRIPT || - item.type == createjs.LoadQueue.CSS) { - this._startTagVisibility = tag.style.visibility; - tag.style.visibility = "hidden"; - (document.body || document.getElementsByTagName("body")[0]).appendChild(tag); - } - - // Note: Previous versions didn't seem to work when we called load() for OGG tags in Firefox. Seems fixed in 15.0.1 - if (tag.load != null) { - tag.load(); - } - }; - - p._handleJSONPLoad = function(data) { - this._jsonResult = data; - }; - - /** - * Handle an audio timeout. Newer browsers get a callback from the tags, but older ones may require a setTimeout - * to handle it. The setTimeout is always running until a response is handled by the browser. - * @method _handleTimeout - * @private - */ - p._handleTimeout = function() { - this._clean(); - var event = new createjs.Event("error"); - event.text = "PRELOAD_TIMEOUT"; - this._sendError(event); - }; - - /** - * Handle a stalled audio event. The main place we seem to get these is with HTMLAudio in Chrome when we try and - * playback audio that is already in a load, but not complete. - * @method _handleStalled - * @private - */ - p._handleStalled = function() { - //Ignore, let the timeout take care of it. Sometimes its not really stopped. - }; - - /** - * Handle an error event generated by the tag. - * @method _handleError - * @private - */ - p._handleError = function(event) { - this._clean(); - - var newEvent = new createjs.Event("error"); - //TODO: Propagate actual event error? - this._sendError(newEvent); - }; - - /** - * Handle the readyStateChange event from a tag. We sometimes need this in place of the onload event (mainly SCRIPT - * and LINK tags), but other cases may exist. - * @method _handleReadyStateChange - * @private - */ - p._handleReadyStateChange = function() { - clearTimeout(this._loadTimeout); - // This is strictly for tags in browsers that do not support onload. - var tag = this.getItem().tag; - - // Complete is for old IE support. - if (tag.readyState == "loaded" || tag.readyState == "complete") { - this._handleLoad(); - } - }; - - /** - * Handle a load (complete) event. This is called by tag callbacks, but also by readyStateChange and canPlayThrough - * events. Once loaded, the item is dispatched to the {{#crossLink "LoadQueue"}}{{/crossLink}}. - * @method _handleLoad - * @param {Object} [event] A load event from a tag. This is sometimes called from other handlers without an event. - * @private - */ - p._handleLoad = function(event) { - if (this._isCanceled()) { return; } - - var item = this.getItem(); - var tag = item.tag; - - if (this.loaded || this._isAudio && tag.readyState !== 4) { return; } //LM: Not sure if we still need the audio check. - this.loaded = true; - - // Remove from the DOM - switch (item.type) { - case createjs.LoadQueue.SVG: - case createjs.LoadQueue.JSON: - case createjs.LoadQueue.JSONP: // Note: Removing script tags is a fool's errand. - case createjs.LoadQueue.MANIFEST: - case createjs.LoadQueue.CSS: - // case createjs.LoadQueue.CSS: - //LM: We may need to remove CSS tags loaded using a LINK - tag.style.visibility = this._startTagVisibility; - (document.body || document.getElementsByTagName("body")[0]).removeChild(tag); - break; - default: - } - - this._clean(); - this._sendComplete(); - }; - - /** - * Clean up the loader. - * This stops any timers and removes references to prevent errant callbacks and clean up memory. - * @method _clean - * @private - */ - p._clean = function() { - clearTimeout(this._loadTimeout); - - // Delete handlers. - var item = this.getItem(); - var tag = item.tag; - if (tag != null) { - tag.onload = null; - tag.removeEventListener && tag.removeEventListener("canplaythrough", this._tagCompleteProxy, false); - tag.onstalled = null; - tag.onprogress = null; - tag.onerror = null; - - //TODO: Test this - if (tag.parentNode != null - && item.type == createjs.LoadQueue.SVG - && item.type == createjs.LoadQueue.JSON - && item.type == createjs.LoadQueue.MANIFEST - && item.type == createjs.LoadQueue.CSS - && item.type == createjs.LoadQueue.JSONP) { - // Note: Removing script tags is a fool's errand. - tag.parentNode.removeChild(tag); - } - } - - var item = this.getItem(); - if (item.type == createjs.LoadQueue.JSONP - || item.type == createjs.LoadQueue.MANIFEST) { - window[item.callback] = null; - } - }; - - p.toString = function() { - return "[PreloadJS TagLoader]"; - }; - - createjs.TagLoader = TagLoader; - -}()); -/* - * XHRLoader - * Visit http://createjs.com/ for documentation, updates and examples. - * - * - * Copyright (c) 2012 gskinner.com, inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * @module PreloadJS - */ - -// namespace: -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - /** - * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used - * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary. - * XHR requests load the content as text or binary data, provide progress and consistent completion events, and - * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for - * cross-domain loading. - * @class XHRLoader - * @constructor - * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * for an overview of supported file properties. - * @param {String} [crossOrigin] An optional flag to support images loaded from a CORS-enabled server. Please see - * {{#crossLink "LoadQueue/_crossOrigin:property"}}{{/crossLink}} for more info. - * @extends AbstractLoader - */ - var XHRLoader = function (item, crossOrigin) { - this.init(item, crossOrigin); - }; - - var p = XHRLoader.prototype = new createjs.AbstractLoader(); - - //Protected - /** - * A reference to the XHR request used to load the content. - * @property _request - * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP} - * @private - */ - p._request = null; - - /** - * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1, - * typically IE9). - * @property _loadTimeout - * @type {Number} - * @private - */ - p._loadTimeout = null; - - /** - * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect - * the version, so we use capabilities to make a best guess. - * @property _xhrLevel - * @type {Number} - * @default 1 - * @private - */ - p._xhrLevel = 1; - - /** - * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be - * null until the file is loaded. - * @property _response - * @type {mixed} - * @private - */ - p._response = null; - - /** - * The response of the loaded file before it is modified. In most cases, content is converted from raw text to - * an HTML tag or a formatted object which is set to the result property, but the developer may still - * want to access the raw content as it was loaded. - * @property _rawResponse - * @type {String|Object} - * @private - */ - p._rawResponse = null; - - /** - * See {{#crossLink "LoadQueue/_crossOrigin:property"}}{{/crossLink}} - * @property _crossOrigin - * @type {String} - * @defaultValue "" - * @private - */ - p._crossOrigin = ""; - - // Overrides abstract method in AbstractLoader - p.init = function (item, crossOrigin) { - this._item = item; - this._crossOrigin = crossOrigin; - if (!this._createXHR(item)) { - //TODO: Throw error? - } - }; - - /** - * Look up the loaded result. - * @method getResult - * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content - * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be - * returned instead. - * @return {Object} A result object containing the content that was loaded, such as: - *
      - *
    • An image tag (<image />) for images
    • - *
    • A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the - * HTML head.
    • - *
    • A style tag for CSS (<style />)
    • - *
    • Raw text for TEXT
    • - *
    • A formatted JavaScript object defined by JSON
    • - *
    • An XML document
    • - *
    • An binary arraybuffer loaded by XHR
    • - *
    - * Note that if a raw result is requested, but not found, the result will be returned instead. - */ - p.getResult = function (rawResult) { - if (rawResult && this._rawResponse) { - return this._rawResponse; - } - return this._response; - }; - - // Overrides abstract method in AbstractLoader - 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 - this._request.onloadstart = createjs.proxy(this._handleLoadStart, this); - this._request.onprogress = createjs.proxy(this._handleProgress, this); - this._request.onabort = createjs.proxy(this._handleAbort, this); - this._request.onerror = createjs.proxy(this._handleError, this); - this._request.ontimeout = createjs.proxy(this._handleTimeout, this); - // Set up a timeout if we don't have XHR2 - if (this._xhrLevel == 1) { - var duration = createjs.LoadQueue.LOAD_TIMEOUT; - if (duration == 0) { - duration = createjs.LoadQueue.loadTimeout; - } else { - try { console.warn("LoadQueue.LOAD_TIMEOUT has been deprecated in favor of LoadQueue.loadTimeout");} catch(e) {} - } - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), duration); - } - - // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. - this._request.onload = createjs.proxy(this._handleLoad, this); - - this._request.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this); - - // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome - try { - if (!this._item.values || this._item.method == createjs.LoadQueue.GET) { - this._request.send(); - } else if (this._item.method == createjs.LoadQueue.POST) { - this._request.send(this._formatQueryString(this._item.values)); - } - } catch (error) { - var event = new createjs.Event("error"); - event.error = error; - this._sendError(event); - } - }; - - /** - * 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; - } - }; - - /** - * 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.Event("progress"); - newEvent.loaded = event.loaded; - newEvent.total = event.total; - this._sendProgress(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._sendLoadStart(); - }; - - /** - * The XHR request has reported an abort event. - * @method handleAbort - * @param {Object} event The XHR abort event. - * @private - */ - p._handleAbort = function (event) { - this._clean(); - var newEvent = new createjs.Event("error"); - newEvent.text = "XHR_ABORTED"; - this._sendError(newEvent); - }; - - /** - * The XHR request has reported an error event. - * @method _handleError - * @param {Object} event The XHR error event. - * @private - */ - p._handleError = function (event) { - this._clean(); - var newEvent = new createjs.Event("error"); - //TODO: Propagate event error - this._sendError(newEvent); - }; - - /** - * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload - * event, so we must monitor the readyStateChange to determine if the file is loaded. - * @method _handleReadyStateChange - * @param {Object} event The XHR readyStateChange event. - * @private - */ - p._handleReadyStateChange = function (event) { - if (this._request.readyState == 4) { - this._handleLoad(); - } - }; - - /** - * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has - * request.readyState == 4. Only the first call to this method will be processed. - * @method _handleLoad - * @param {Object} event The XHR load event. - * @private - */ - p._handleLoad = function (event) { - if (this.loaded) { - return; - } - this.loaded = true; - - if (!this._checkError()) { - this._handleError(); - return; - } - - this._response = this._getResponse(); - this._clean(); - var isComplete = this._generateTag(); - if (isComplete) { - this._sendComplete(); - } - }; - - /** - * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout - * callback. - * @method _handleTimeout - * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout. - * @private - */ - p._handleTimeout = function (event) { - this._clean(); - var newEvent = new createjs.Event("error"); - newEvent.text = "PRELOAD_TIMEOUT"; - //TODO: Propagate actual event error - this._sendError(event); - }; - - -// Protected - /** - * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note - * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code. - * @method _checkError - * @return {Boolean} If the request status returns an error code. - * @private - */ - p._checkError = function () { - //LM: Probably need additional handlers here, maybe 501 - var status = parseInt(this._request.status); - - switch (status) { - case 404: // Not Found - case 0: // Not Loaded - return false; - } - return true; - }; - - /** - * Validate the response. Different browsers have different approaches, some of which throw errors when accessed - * in other browsers. If there is no response, the _response property will remain null. - * @method _getResponse - * @private - */ - p._getResponse = function () { - if (this._response != null) { - return this._response; - } - - if (this._request.response != null) { - return this._request.response; - } - - // Android 2.2 uses .responseText - try { - if (this._request.responseText != null) { - return this._request.responseText; - } - } catch (e) { - } - - // When loading XML, IE9 does not return .response, instead it returns responseXML.xml - //TODO: TEST - try { - if (this._request.responseXML != null) { - return this._request.responseXML; - } - } catch (e) { - } - return null; - }; - - /** - * Create an XHR request. Depending on a number of factors, we get totally different results. - *
    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 = this._isCrossDomain(item); - - // Create the request. Fall back to whatever support we have. - var req = null; - if (crossdomain && window.XDomainRequest) { - req = new XDomainRequest(); // Note: IE9 will fail if this is not actually cross-domain. - } else if (window.XMLHttpRequest) { // Old IE versions use a different approach - req = new XMLHttpRequest(); - } else { - try { - req = new ActiveXObject("Msxml2.XMLHTTP.6.0"); - } catch (e) { - try { - req = new ActiveXObject("Msxml2.XMLHTTP.3.0"); - } catch (e) { - try { - req = new ActiveXObject("Msxml2.XMLHTTP"); - } catch (e) { - return false; - } - } - } - } - - // IE9 doesn't support overrideMimeType(), so we need to check for it. - if (createjs.LoadQueue.isText(item.type) && req.overrideMimeType) { - req.overrideMimeType("text/plain; charset=utf-8"); - } - - // Determine the XHR level - this._xhrLevel = (typeof req.responseType === "string") ? 2 : 1; - - var src = null; - if (item.method == createjs.LoadQueue.GET) { - src = this.buildPath(item.src, item.values); - } else { - src = item.src; - } - - // Open the request. Set cross-domain flags if it is supported (XHR level 1 only) - req.open(item.method || createjs.LoadQueue.GET, src, true); - - if (crossdomain && req instanceof XMLHttpRequest && this._xhrLevel == 1) { - req.setRequestHeader("Origin", location.origin); - } - - /*TODO: Test and implement. - if (crossDomain && !headers["X-Requested-With"] ) { - headers["X-Requested-With"] = "XMLHttpRequest"; - }*/ - - // To send data we need to set the Content-type header) - if (item.values && item.method == createjs.LoadQueue.POST) { - req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); - } - - // Binary files are loaded differently. - if (createjs.LoadQueue.isBinary(item.type)) { - req.responseType = "arraybuffer"; - } - - 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); - - var req = this._request; - req.onloadstart = null; - req.onprogress = null; - req.onabort = null; - req.onerror = null; - req.onload = null; - req.ontimeout = null; - req.onloadend = null; - req.onreadystatechange = null; - }; - - /** - * Generate a tag for items that can be represented as tags. For example, IMAGE, SCRIPT, and LINK. This also handles - * XML and SVG objects. - * @method _generateTag - * @return {Boolean} If a tag was generated and is ready for instantiation. If it still needs processing, this - * method returns false. - * @private - */ - p._generateTag = function () { - var type = this._item.type; - var tag = this._item.tag; - - switch (type) { - // Note: Images need to wait for onload, but do use the cache. - case createjs.LoadQueue.IMAGE: - tag.onload = createjs.proxy(this._handleTagReady, this); - if (this._crossOrigin != "") { tag.crossOrigin = "Anonymous"; }// We can assume this, since XHR images are always loaded on a server. - tag.src = this.buildPath(this._item.src, this._item.values); - - this._rawResponse = this._response; - this._response = tag; - return false; // Images need to get an onload event first - - case createjs.LoadQueue.JAVASCRIPT: - tag = document.createElement("script"); - tag.text = this._response; - - this._rawResponse = this._response; - this._response = tag; - return true; - - case createjs.LoadQueue.CSS: - // Maybe do this conditionally? - var head = document.getElementsByTagName("head")[0]; //Note: This is unavoidable in IE678 - head.appendChild(tag); - - if (tag.styleSheet) { // IE - tag.styleSheet.cssText = this._response; - } else { - var textNode = document.createTextNode(this._response); - tag.appendChild(textNode); - } - - this._rawResponse = this._response; - this._response = tag; - return true; - - case createjs.LoadQueue.XML: - var xml = this._parseXML(this._response, "text/xml"); - this._rawResponse = this._response; - this._response = xml; - return true; - - case createjs.LoadQueue.SVG: - var xml = this._parseXML(this._response, "image/svg+xml"); - this._rawResponse = this._response; - if (xml.documentElement != null) { - tag.appendChild(xml.documentElement); - this._response = tag; - } else { // For browsers that don't support SVG, just give them the XML. (IE 9-8) - this._response = xml; - } - return true; - - case createjs.LoadQueue.JSON: - case createjs.LoadQueue.MANIFEST: - var json = {}; - try { - json = JSON.parse(this._response); - } catch (error) { - json = error; - } - - this._rawResponse = this._response; - this._response = json; - return true; - - } - return true; - }; - - /** - * Parse XML using the DOM. This is required when preloading XML or SVG. - * @method _parseXML - * @param {String} text The raw text or XML that is loaded by XHR. - * @param {String} type The mime type of the XML. - * @return {XML} An XML document. - * @private - */ - p._parseXML = function (text, type) { - var xml = null; - try { - // CocoonJS does not support XML parsing with either method. - // Windows (?) Opera DOMParser throws DOMException: NOT_SUPPORTED_ERR // potential solution https://gist.github.com/1129031 - if (window.DOMParser) { - var parser = new DOMParser(); - xml = parser.parseFromString(text, type); - } else { // IE - xml = new ActiveXObject("Microsoft.XMLDOM"); - xml.async = false; - xml.loadXML(text); - } - } catch (e) {} - return xml; - }; - - /** - * A generated tag is now ready for use. - * @method _handleTagReady - * @private - */ - p._handleTagReady = function () { - this._sendComplete(); - }; - - p.toString = function () { - return "[PreloadJS XHRLoader]"; - }; - - createjs.XHRLoader = XHRLoader; - -}()); - -/** - * Include json2 here, to correctly parse json. - * Used on browsers that don't have a native JSON object. - * - */ -/* - json2.js - 2012-10-08 - - Public Domain. - - NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. - - See http://www.JSON.org/js.html - - - This code should be minified before deployment. - See http://javascript.crockford.com/jsmin.html - - USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO - NOT CONTROL. - */ - - -// Create a JSON object only if one does not already exist. We create the -// methods in a closure to avoid creating global variables. - -if (typeof JSON !== 'object') { - JSON = {}; -} - -(function () { - 'use strict'; - - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - if (typeof Date.prototype.toJSON !== 'function') { - - Date.prototype.toJSON = function (key) { - - return isFinite(this.valueOf()) - ? this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z' - : null; - }; - - String.prototype.toJSON = - Number.prototype.toJSON = - Boolean.prototype.toJSON = function (key) { - return this.valueOf(); - }; - } - - var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - gap, - indent, - meta = { // table of character substitutions - '\b':'\\b', - '\t':'\\t', - '\n':'\\n', - '\f':'\\f', - '\r':'\\r', - '"':'\\"', - '\\':'\\\\' - }, - rep; - - - function quote(string) { - -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can safely slap some quotes around it. -// Otherwise we must also replace the offending characters with safe escape -// sequences. - - escapable.lastIndex = 0; - return escapable.test(string) ? '"' + string.replace(escapable, function (a) { - var c = meta[a]; - return typeof c === 'string' - ? c - : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }) + '"' : '"' + string + '"'; - } - - - function str(key, holder) { - -// Produce a string from holder[key]. - - var i, // The loop counter. - k, // The member key. - v, // The member value. - length, - mind = gap, - partial, - value = holder[key]; - -// If the value has a toJSON method, call it to obtain a replacement value. - - if (value && typeof value === 'object' && - typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - -// If we were called with a replacer function, then call the replacer to -// obtain a replacement value. - - if (typeof rep === 'function') { - value = rep.call(holder, key, value); - } - -// What happens next depends on the value's type. - - switch (typeof value) { - case 'string': - return quote(value); - - case 'number': - -// JSON numbers must be finite. Encode non-finite numbers as null. - - return isFinite(value) ? String(value) : 'null'; - - case 'boolean': - case 'null': - -// If the value is a boolean or null, convert it to a string. Note: -// typeof null does not produce 'null'. The case is included here in -// the remote chance that this gets fixed someday. - - return String(value); - -// If the type is 'object', we might be dealing with an object or an array or -// null. - - case 'object': - -// Due to a specification blunder in ECMAScript, typeof null is 'object', -// so watch out for that case. - - if (!value) { - return 'null'; - } - -// Make an array to hold the partial results of stringifying this object value. - - gap += indent; - partial = []; - -// Is the value an array? - - if (Object.prototype.toString.apply(value) === '[object Array]') { - -// The value is an array. Stringify every element. Use null as a placeholder -// for non-JSON values. - - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || 'null'; - } - -// Join all of the elements together, separated with commas, and wrap them in -// brackets. - - v = partial.length === 0 - ? '[]' - : gap - ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' - : '[' + partial.join(',') + ']'; - gap = mind; - return v; - } - -// If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === 'object') { - length = rep.length; - for (i = 0; i < length; i += 1) { - if (typeof rep[i] === 'string') { - k = rep[i]; - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } else { - -// Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } - -// Join all of the member texts together, separated with commas, -// and wrap them in braces. - - v = partial.length === 0 - ? '{}' - : gap - ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' - : '{' + partial.join(',') + '}'; - gap = mind; - return v; - } - } - -// If the JSON object does not yet have a stringify method, give it one. - - if (typeof JSON.stringify !== 'function') { - JSON.stringify = function (value, replacer, space) { - -// The stringify method takes a value and an optional replacer, and an optional -// space parameter, and returns a JSON text. The replacer can be a function -// that can replace values, or an array of strings that will select the keys. -// A default replacer method can be provided. Use of the space parameter can -// produce text that is more easily readable. - - var i; - gap = ''; - indent = ''; - -// If the space parameter is a number, make an indent string containing that -// many spaces. - - if (typeof space === 'number') { - for (i = 0; i < space; i += 1) { - indent += ' '; - } - -// If the space parameter is a string, it will be used as the indent string. - - } else if (typeof space === 'string') { - indent = space; - } - -// If there is a replacer, it must be a function or an array. -// Otherwise, throw an error. - - rep = replacer; - if (replacer && typeof replacer !== 'function' && - (typeof replacer !== 'object' || - typeof replacer.length !== 'number')) { - throw new Error('JSON.stringify'); - } - -// Make a fake root object containing our value under the key of ''. -// Return the result of stringifying the value. - - return str('', {'':value}); - }; - } - - -// If the JSON object does not yet have a parse method, give it one. - - if (typeof JSON.parse !== 'function') { - JSON.parse = function (text, reviver) { - -// The parse method takes a text and an optional reviver function, and returns -// a JavaScript value if the text is a valid JSON text. - - var j; - - function walk(holder, key) { - -// The walk method is used to recursively walk the resulting structure so -// that modifications can be made. - - var k, v, value = holder[key]; - if (value && typeof value === 'object') { - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - } - - -// Parsing happens in four stages. In the first stage, we replace certain -// Unicode characters with escape sequences. JavaScript handles many characters -// incorrectly, either silently deleting them, or treating them as line endings. - - text = String(text); - cx.lastIndex = 0; - if (cx.test(text)) { - text = text.replace(cx, function (a) { - return '\\u' + - ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }); - } - -// In the second stage, we run the text against regular expressions that look -// for non-JSON patterns. We are especially concerned with '()' and 'new' -// because they can cause invocation, and '=' because it can cause mutation. -// But just to be safe, we want to reject all unexpected forms. - -// We split the second stage into 4 regexp operations in order to work around -// crippling inefficiencies in IE's and Safari's regexp engines. First we -// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we -// replace all simple value tokens with ']' characters. Third, we delete all -// open brackets that follow a colon or comma or that begin the text. Finally, -// we look to see that the remaining characters are only whitespace or ']' or -// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. - - if (/^[\],:{}\s]*$/ - .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') - .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') - .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { - -// In the third stage we use the eval function to compile the text into a -// JavaScript structure. The '{' operator is subject to a syntactic ambiguity -// in JavaScript: it can begin a block or an object literal. We wrap the text -// in parens to eliminate the ambiguity. - - j = eval('(' + text + ')'); - -// In the optional fourth stage, we recursively walk the new structure, passing -// each name/value pair to a reviver function for possible transformation. - - return typeof reviver === 'function' - ? walk({'':j}, '') - : j; - } - -// If the text is not JSON parseable, then a SyntaxError is thrown. - - throw new SyntaxError('JSON.parse'); - }; - } -}()); diff --git a/lib/preloadjs-0.4.1.min.js b/lib/preloadjs-0.4.1.min.js deleted file mode 100644 index b61cea1c..00000000 --- a/lib/preloadjs-0.4.1.min.js +++ /dev/null @@ -1,12 +0,0 @@ -/*! -* @license PreloadJS -* Visit http://createjs.com/ for documentation, updates and examples. -* -* Copyright (c) 2011-2013 gskinner.com, inc. -* -* Distributed under the terms of the MIT license. -* http://www.opensource.org/licenses/mit-license.html -* -* This notice shall be included in all copies or substantial portions of the Software. -*/ -this.createjs=this.createjs||{},function(){"use strict";var a=createjs.PreloadJS=createjs.PreloadJS||{};a.version="0.4.1",a.buildDate="Thu, 12 Dec 2013 23:33:38 GMT"}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c){this.initialize(a,b,c)},b=a.prototype;b.type=null,b.target=null,b.currentTarget=null,b.eventPhase=0,b.bubbles=!1,b.cancelable=!1,b.timeStamp=0,b.defaultPrevented=!1,b.propagationStopped=!1,b.immediatePropagationStopped=!1,b.removed=!1,b.initialize=function(a,b,c){this.type=a,this.bubbles=b,this.cancelable=c,this.timeStamp=(new Date).getTime()},b.preventDefault=function(){this.defaultPrevented=!0},b.stopPropagation=function(){this.propagationStopped=!0},b.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},b.remove=function(){this.removed=!0},b.clone=function(){return new a(this.type,this.bubbles,this.cancelable)},b.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){},b=a.prototype;a.initialize=function(a){a.addEventListener=b.addEventListener,a.on=b.on,a.removeEventListener=a.off=b.removeEventListener,a.removeAllEventListeners=b.removeAllEventListeners,a.hasEventListener=b.hasEventListener,a.dispatchEvent=b.dispatchEvent,a._dispatchEvent=b._dispatchEvent,a.willTrigger=b.willTrigger},b._listeners=null,b._captureListeners=null,b.initialize=function(){},b.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},b.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},b.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},b.off=b.removeEventListener,b.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},b.dispatchEvent=function(a,b){if("string"==typeof a){var c=this._listeners;if(!c||!c[a])return!1;a=new createjs.Event(a)}if(a.target=b||this,a.bubbles&&this.parent){for(var d=this,e=[d];d.parent;)e.push(d=d.parent);var f,g=e.length;for(f=g-1;f>=0&&!a.propagationStopped;f--)e[f]._dispatchEvent(a,1+(0==f));for(f=1;g>f&&!a.propagationStopped;f++)e[f]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return a.defaultPrevented},b.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},b.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},b.toString=function(){return"[EventDispatcher]"},b._dispatchEvent=function(a,b){var c,d=1==b?this._captureListeners:this._listeners;if(a&&d){var e=d[a.type];if(!e||!(c=e.length))return;a.currentTarget=this,a.eventPhase=b,a.removed=!1,e=e.slice();for(var f=0;c>f&&!a.immediatePropagationStopped;f++){var g=e[f];g.handleEvent?g.handleEvent(a):g(a),a.removed&&(this.off(a.type,g,1==b),a.removed=!1)}}},createjs.EventDispatcher=a}(),this.createjs=this.createjs||{},function(){"use strict";createjs.indexOf=function(a,b){for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1}}(),this.createjs=this.createjs||{},function(){"use strict";createjs.proxy=function(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){return a.apply(b,Array.prototype.slice.call(arguments,0).concat(c))}}}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){this.init()};a.prototype=new createjs.EventDispatcher;var b=a.prototype,c=a;c.FILE_PATTERN=/^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?)|(.{0,2}\/{1}))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/,c.PATH_PATTERN=/^(?:(\w+:)\/{2})|(.{0,2}\/{1})?([/.]*?(?:[^?]+)?\/?)?$/,b.loaded=!1,b.canceled=!1,b.progress=0,b._item=null,b.getItem=function(){return this._item},b.init=function(){},b.load=function(){},b.close=function(){},b._sendLoadStart=function(){this._isCanceled()||this.dispatchEvent("loadstart")},b._sendProgress=function(a){if(!this._isCanceled()){var b=null;"number"==typeof a?(this.progress=a,b=new createjs.Event("progress"),b.loaded=this.progress,b.total=1):(b=a,this.progress=a.loaded/a.total,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0)),b.progress=this.progress,this.hasEventListener("progress")&&this.dispatchEvent(b)}},b._sendComplete=function(){this._isCanceled()||this.dispatchEvent("complete")},b._sendError=function(a){!this._isCanceled()&&this.hasEventListener("error")&&(null==a&&(a=new createjs.Event("error")),this.dispatchEvent(a))},b._isCanceled=function(){return null==window.createjs||this.canceled?!0:!1},b._parseURI=function(a){return a?a.match(c.FILE_PATTERN):null},b._parsePath=function(a){return a?a.match(c.PATH_PATTERN):null},b._formatQueryString=function(a,b){if(null==a)throw new Error("You must specify data.");var c=[];for(var d in a)c.push(d+"="+escape(a[d]));return b&&(c=c.concat(b)),c.join("&")},b.buildPath=function(a,b){if(null==b)return a;var c=[],d=a.indexOf("?");if(-1!=d){var e=a.slice(d+1);c=c.concat(e.split("&"))}return-1!=d?a.slice(0,d)+"?"+this._formatQueryString(b,c):a+"?"+this._formatQueryString(b,c)},b._isCrossDomain=function(a){var b=document.createElement("a");b.href=a.src;var c=document.createElement("a");c.href=location.href;var d=""!=b.hostname&&(b.port!=c.port||b.protocol!=c.protocol||b.hostname!=c.hostname);return d},b._isLocal=function(a){var b=document.createElement("a");return b.href=a.src,""==b.hostname&&"file:"==b.protocol},b.toString=function(){return"[PreloadJS AbstractLoader]"},createjs.AbstractLoader=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c){this.init(a,b,c)},b=a.prototype=new createjs.AbstractLoader,c=a;c.loadTimeout=8e3,c.LOAD_TIMEOUT=0,c.BINARY="binary",c.CSS="css",c.IMAGE="image",c.JAVASCRIPT="javascript",c.JSON="json",c.JSONP="jsonp",c.MANIFEST="manifest",c.SOUND="sound",c.SVG="svg",c.TEXT="text",c.XML="xml",c.POST="POST",c.GET="GET",b._basePath=null,b._crossOrigin="",b.useXHR=!0,b.stopOnError=!1,b.maintainScriptOrder=!0,b.next=null,b._typeCallbacks=null,b._extensionCallbacks=null,b._loadStartWasDispatched=!1,b._maxConnections=1,b._currentlyLoadingScript=null,b._currentLoads=null,b._loadQueue=null,b._loadQueueBackup=null,b._loadItemsById=null,b._loadItemsBySrc=null,b._loadedResults=null,b._loadedRawResults=null,b._numItems=0,b._numItemsLoaded=0,b._scriptOrder=null,b._loadedScripts=null,b.init=function(a,b,c){this._numItems=this._numItemsLoaded=0,this._paused=!1,this._loadStartWasDispatched=!1,this._currentLoads=[],this._loadQueue=[],this._loadQueueBackup=[],this._scriptOrder=[],this._loadedScripts=[],this._loadItemsById={},this._loadItemsBySrc={},this._loadedResults={},this._loadedRawResults={},this._typeCallbacks={},this._extensionCallbacks={},this._basePath=b,this.setUseXHR(a),this._crossOrigin=c===!0?"Anonymous":c===!1||null==c?"":c},b.setUseXHR=function(a){return this.useXHR=0!=a&&null!=window.XMLHttpRequest,this.useXHR},b.removeAll=function(){this.remove()},b.remove=function(a){var b=null;if(!a||a instanceof Array){if(a)b=a;else if(arguments.length>0)return}else b=[a];var c=!1;if(b){for(;b.length;){var d=b.pop(),e=this.getResult(d);for(f=this._loadQueue.length-1;f>=0;f--)if(g=this._loadQueue[f].getItem(),g.id==d||g.src==d){this._loadQueue.splice(f,1)[0].cancel();break}for(f=this._loadQueueBackup.length-1;f>=0;f--)if(g=this._loadQueueBackup[f].getItem(),g.id==d||g.src==d){this._loadQueueBackup.splice(f,1)[0].cancel();break}if(e)delete this._loadItemsById[e.id],delete this._loadItemsBySrc[e.src],this._disposeItem(e);else for(var f=this._currentLoads.length-1;f>=0;f--){var g=this._currentLoads[f].getItem();if(g.id==d||g.src==d){this._currentLoads.splice(f,1)[0].cancel(),c=!0;break}}}c&&this._loadNext()}else{this.close();for(var h in this._loadItemsById)this._disposeItem(this._loadItemsById[h]);this.init(this.useXHR)}},b.reset=function(){this.close();for(var a in this._loadItemsById)this._disposeItem(this._loadItemsById[a]);for(var b=[],c=0,d=this._loadQueueBackup.length;d>c;c++)b.push(this._loadQueueBackup[c].getItem());this.loadManifest(b,!1)},c.isBinary=function(a){switch(a){case createjs.LoadQueue.IMAGE:case createjs.LoadQueue.BINARY:return!0;default:return!1}},c.isText=function(a){switch(a){case createjs.LoadQueue.TEXT:case createjs.LoadQueue.JSON:case createjs.LoadQueue.MANIFEST:case createjs.LoadQueue.XML:case createjs.LoadQueue.HTML:case createjs.LoadQueue.CSS:case createjs.LoadQueue.SVG:case createjs.LoadQueue.JAVASCRIPT:return!0;default:return!1}},b.installPlugin=function(a){if(null!=a&&null!=a.getPreloadHandlers){var b=a.getPreloadHandlers();if(b.scope=a,null!=b.types)for(var c=0,d=b.types.length;d>c;c++)this._typeCallbacks[b.types[c]]=b;if(null!=b.extensions)for(c=0,d=b.extensions.length;d>c;c++)this._extensionCallbacks[b.extensions[c]]=b}},b.setMaxConnections=function(a){this._maxConnections=a,!this._paused&&this._loadQueue.length>0&&this._loadNext()},b.loadFile=function(a,b,c){if(null==a){var d=new createjs.Event("error");return d.text="PRELOAD_NO_FILE",this._sendError(d),void 0}this._addItem(a,null,c),b!==!1?this.setPaused(!1):this.setPaused(!0)},b.loadManifest=function(a,b,d){var e=null,f=null;if(a instanceof Array){if(0==a.length){var g=new createjs.Event("error");return g.text="PRELOAD_MANIFEST_EMPTY",this._sendError(g),void 0}e=a}else if("string"==typeof a)e=[{src:a,type:c.MANIFEST}];else{if("object"!=typeof a){var g=new createjs.Event("error");return g.text="PRELOAD_MANIFEST_NULL",this._sendError(g),void 0}if(void 0!==a.src){if(null==a.type)a.type=c.MANIFEST;else if(a.type!=c.MANIFEST){var g=new createjs.Event("error");g.text="PRELOAD_MANIFEST_ERROR",this._sendError(g)}e=[a]}else void 0!==a.manifest&&(e=a.manifest,f=a.path)}for(var h=0,i=e.length;i>h;h++)this._addItem(e[h],f,d);b!==!1?this.setPaused(!1):this.setPaused(!0)},b.load=function(){this.setPaused(!1)},b.getItem=function(a){return this._loadItemsById[a]||this._loadItemsBySrc[a]},b.getResult=function(a,b){var c=this._loadItemsById[a]||this._loadItemsBySrc[a];if(null==c)return null;var d=c.id;return b&&this._loadedRawResults[d]?this._loadedRawResults[d]:this._loadedResults[d]},b.setPaused=function(a){this._paused=a,this._paused||this._loadNext()},b.close=function(){for(;this._currentLoads.length;)this._currentLoads.pop().cancel();this._scriptOrder.length=0,this._loadedScripts.length=0,this.loadStartWasDispatched=!1},b._addItem=function(a,b,c){var d=this._createLoadItem(a,b,c);if(null!=d){var e=this._createLoader(d);null!=e&&(this._loadQueue.push(e),this._loadQueueBackup.push(e),this._numItems++,this._updateProgress(),this.maintainScriptOrder&&d.type==createjs.LoadQueue.JAVASCRIPT&&e instanceof createjs.XHRLoader&&(this._scriptOrder.push(d),this._loadedScripts.push(null)))}},b._createLoadItem=function(a,b,c){var d=null;switch(typeof a){case"string":d={src:a};break;case"object":d=window.HTMLAudioElement&&a instanceof window.HTMLAudioElement?{tag:a,src:d.tag.src,type:createjs.LoadQueue.SOUND}:a;break;default:return null}var e=this._parseURI(d.src);null!=e&&(d.ext=e[6]),null==d.type&&(d.type=this._getTypeByExtension(d.ext));var f="",g=c||this._basePath,h=d.src;if(e&&null==e[1]&&null==e[3])if(b){f=b;var i=this._parsePath(b);h=b+h,null!=g&&i&&null==i[1]&&null==i[2]&&(f=g+f)}else null!=g&&(f=g);if(d.src=f+d.src,d.path=f,(d.type==createjs.LoadQueue.JSON||d.type==createjs.LoadQueue.MANIFEST)&&(d._loadAsJSONP=null!=d.callback),d.type==createjs.LoadQueue.JSONP&&null==d.callback)throw new Error("callback is required for loading JSONP requests.");(void 0===d.tag||null===d.tag)&&(d.tag=this._createTag(d)),(void 0===d.id||null===d.id||""===d.id)&&(d.id=h);var j=this._typeCallbacks[d.type]||this._extensionCallbacks[d.ext];if(j){var k=j.callback.call(j.scope,d.src,d.type,d.id,d.data,f,this);if(k===!1)return null;k===!0||(null!=k.src&&(d.src=k.src),null!=k.id&&(d.id=k.id),null!=k.tag&&(d.tag=k.tag),null!=k.completeHandler&&(d.completeHandler=k.completeHandler),k.type&&(d.type=k.type),e=this._parseURI(d.src),null!=e&&null!=e[6]&&(d.ext=e[6].toLowerCase()))}return this._loadItemsById[d.id]=d,this._loadItemsBySrc[d.src]=d,d},b._createLoader=function(a){var b=this.useXHR;switch(a.type){case createjs.LoadQueue.JSON:case createjs.LoadQueue.MANIFEST:b=!a._loadAsJSONP;break;case createjs.LoadQueue.XML:case createjs.LoadQueue.TEXT:b=!0;break;case createjs.LoadQueue.SOUND:case createjs.LoadQueue.JSONP:b=!1;break;case null:return null}return b?new createjs.XHRLoader(a,this._crossOrigin):new createjs.TagLoader(a)},b._loadNext=function(){if(!this._paused){this._loadStartWasDispatched||(this._sendLoadStart(),this._loadStartWasDispatched=!0),this._numItems==this._numItemsLoaded?(this.loaded=!0,this._sendComplete(),this.next&&this.next.load&&this.next.load()):this.loaded=!1;for(var a=0;a=this._maxConnections);a++){var b=this._loadQueue[a];if(this.maintainScriptOrder&&b instanceof createjs.TagLoader&&b.getItem().type==createjs.LoadQueue.JAVASCRIPT){if(this._currentlyLoadingScript)continue;this._currentlyLoadingScript=!0}this._loadQueue.splice(a,1),a--,this._loadItem(b)}}},b._loadItem=function(a){a.on("progress",this._handleProgress,this),a.on("complete",this._handleFileComplete,this),a.on("error",this._handleFileError,this),this._currentLoads.push(a),this._sendFileStart(a.getItem()),a.load()},b._handleFileError=function(a){var b=a.target;this._numItemsLoaded++,this._updateProgress();var c=new createjs.Event("error");c.text="FILE_LOAD_ERROR",c.item=b.getItem(),this._sendError(c),this.stopOnError||(this._removeLoadItem(b),this._loadNext())},b._handleFileComplete=function(a){var b=a.target,c=b.getItem();if(this._loadedResults[c.id]=b.getResult(),b instanceof createjs.XHRLoader&&(this._loadedRawResults[c.id]=b.getResult(!0)),this._removeLoadItem(b),this.maintainScriptOrder&&c.type==createjs.LoadQueue.JAVASCRIPT){if(!(b instanceof createjs.TagLoader))return this._loadedScripts[createjs.indexOf(this._scriptOrder,c)]=c,this._checkScriptLoadOrder(b),void 0;this._currentlyLoadingScript=!1}if(delete c._loadAsJSONP,c.type==createjs.LoadQueue.MANIFEST){var d=b.getResult();null!=d&&void 0!==d.manifest&&this.loadManifest(d,!0)}this._processFinishedLoad(c,b)},b._processFinishedLoad=function(a,b){this._numItemsLoaded++,this._updateProgress(),this._sendFileComplete(a,b),this._loadNext()},b._checkScriptLoadOrder=function(){for(var a=this._loadedScripts.length,b=0;a>b;b++){var c=this._loadedScripts[b];if(null===c)break;if(c!==!0){var d=this._loadedResults[c.id];(document.body||document.getElementsByTagName("body")[0]).appendChild(d),this._processFinishedLoad(c),this._loadedScripts[b]=!0}}},b._removeLoadItem=function(a){for(var b=this._currentLoads.length,c=0;b>c;c++)if(this._currentLoads[c]==a){this._currentLoads.splice(c,1);break}},b._handleProgress=function(a){var b=a.target;this._sendFileProgress(b.getItem(),b.progress),this._updateProgress()},b._updateProgress=function(){var a=this._numItemsLoaded/this._numItems,b=this._numItems-this._numItemsLoaded;if(b>0){for(var c=0,d=0,e=this._currentLoads.length;e>d;d++)c+=this._currentLoads[d].progress;a+=c/b*(b/this._numItems)}this._sendProgress(a)},b._disposeItem=function(a){delete this._loadedResults[a.id],delete this._loadedRawResults[a.id],delete this._loadItemsById[a.id],delete this._loadItemsBySrc[a.src]},b._createTag=function(a){var b=null;switch(a.type){case createjs.LoadQueue.IMAGE:return b=document.createElement("img"),""==this._crossOrigin||this._isLocal(a)||(b.crossOrigin=this._crossOrigin),b;case createjs.LoadQueue.SOUND:return b=document.createElement("audio"),b.autoplay=!1,b;case createjs.LoadQueue.JSON:case createjs.LoadQueue.JSONP:case createjs.LoadQueue.JAVASCRIPT:case createjs.LoadQueue.MANIFEST:return b=document.createElement("script"),b.type="text/javascript",b;case createjs.LoadQueue.CSS:return b=this.useXHR?document.createElement("style"):document.createElement("link"),b.rel="stylesheet",b.type="text/css",b;case createjs.LoadQueue.SVG:return this.useXHR?b=document.createElement("svg"):(b=document.createElement("object"),b.type="image/svg+xml"),b}return null},b._getTypeByExtension=function(a){if(null==a)return createjs.LoadQueue.TEXT;switch(a.toLowerCase()){case"jpeg":case"jpg":case"gif":case"png":case"webp":case"bmp":return createjs.LoadQueue.IMAGE;case"ogg":case"mp3":case"wav":return createjs.LoadQueue.SOUND;case"json":return createjs.LoadQueue.JSON;case"xml":return createjs.LoadQueue.XML;case"css":return createjs.LoadQueue.CSS;case"js":return createjs.LoadQueue.JAVASCRIPT;case"svg":return createjs.LoadQueue.SVG;default:return createjs.LoadQueue.TEXT}},b._sendFileProgress=function(a,b){if(this._isCanceled())return this._cleanUp(),void 0;if(this.hasEventListener("fileprogress")){var c=new createjs.Event("fileprogress");c.progress=b,c.loaded=b,c.total=1,c.item=a,this.dispatchEvent(c)}},b._sendFileComplete=function(a,b){if(!this._isCanceled()){var c=new createjs.Event("fileload");c.loader=b,c.item=a,c.result=this._loadedResults[a.id],c.rawResult=this._loadedRawResults[a.id],a.completeHandler&&a.completeHandler(c),this.hasEventListener("fileload")&&this.dispatchEvent(c)}},b._sendFileStart=function(a){var b=new createjs.Event("filestart");b.item=a,this.hasEventListener("filestart")&&this.dispatchEvent(b)},b.toString=function(){return"[PreloadJS LoadQueue]"},createjs.LoadQueue=a;var d=function(){};d.init=function(){var a=navigator.userAgent;d.isFirefox=a.indexOf("Firefox")>-1,d.isOpera=null!=window.opera,d.isChrome=a.indexOf("Chrome")>-1,d.isIOS=a.indexOf("iPod")>-1||a.indexOf("iPhone")>-1||a.indexOf("iPad")>-1},d.init(),createjs.LoadQueue.BrowserDetect=d}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a){this.init(a)},b=a.prototype=new createjs.AbstractLoader;b._loadTimeout=null,b._tagCompleteProxy=null,b._isAudio=!1,b._tag=null,b._jsonResult=null,b.init=function(a){this._item=a,this._tag=a.tag,this._isAudio=window.HTMLAudioElement&&a.tag instanceof window.HTMLAudioElement,this._tagCompleteProxy=createjs.proxy(this._handleLoad,this)},b.getResult=function(){return this._item.type==createjs.LoadQueue.JSONP||this._item.type==createjs.LoadQueue.MANIFEST?this._jsonResult:this._tag},b.cancel=function(){this.canceled=!0,this._clean()},b.load=function(){var a=this._item,b=this._tag;clearTimeout(this._loadTimeout);var c=createjs.LoadQueue.LOAD_TIMEOUT;0==c&&(c=createjs.LoadQueue.loadTimeout),this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),c),this._isAudio&&(b.src=null,b.preload="auto"),b.onerror=createjs.proxy(this._handleError,this),this._isAudio?(b.onstalled=createjs.proxy(this._handleStalled,this),b.addEventListener("canplaythrough",this._tagCompleteProxy,!1)):(b.onload=createjs.proxy(this._handleLoad,this),b.onreadystatechange=createjs.proxy(this._handleReadyStateChange,this));var d=this.buildPath(a.src,a.values);switch(a.type){case createjs.LoadQueue.CSS:b.href=d;break;case createjs.LoadQueue.SVG:b.data=d;break;default:b.src=d}if(a.type==createjs.LoadQueue.JSONP||a.type==createjs.LoadQueue.JSON||a.type==createjs.LoadQueue.MANIFEST){if(null==a.callback)throw new Error("callback is required for loading JSONP requests.");if(null!=window[a.callback])throw new Error('JSONP callback "'+a.callback+'" already exists on window. You need to specify a different callback. Or re-name the current one.');window[a.callback]=createjs.proxy(this._handleJSONPLoad,this)}(a.type==createjs.LoadQueue.SVG||a.type==createjs.LoadQueue.JSONP||a.type==createjs.LoadQueue.JSON||a.type==createjs.LoadQueue.MANIFEST||a.type==createjs.LoadQueue.JAVASCRIPT||a.type==createjs.LoadQueue.CSS)&&(this._startTagVisibility=b.style.visibility,b.style.visibility="hidden",(document.body||document.getElementsByTagName("body")[0]).appendChild(b)),null!=b.load&&b.load()},b._handleJSONPLoad=function(a){this._jsonResult=a},b._handleTimeout=function(){this._clean();var a=new createjs.Event("error");a.text="PRELOAD_TIMEOUT",this._sendError(a)},b._handleStalled=function(){},b._handleError=function(){this._clean();var a=new createjs.Event("error");this._sendError(a)},b._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this.getItem().tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleLoad()},b._handleLoad=function(){if(!this._isCanceled()){var a=this.getItem(),b=a.tag;if(!(this.loaded||this._isAudio&&4!==b.readyState)){switch(this.loaded=!0,a.type){case createjs.LoadQueue.SVG:case createjs.LoadQueue.JSON:case createjs.LoadQueue.JSONP:case createjs.LoadQueue.MANIFEST:case createjs.LoadQueue.CSS:b.style.visibility=this._startTagVisibility,(document.body||document.getElementsByTagName("body")[0]).removeChild(b)}this._clean(),this._sendComplete()}}},b._clean=function(){clearTimeout(this._loadTimeout);var a=this.getItem(),b=a.tag;null!=b&&(b.onload=null,b.removeEventListener&&b.removeEventListener("canplaythrough",this._tagCompleteProxy,!1),b.onstalled=null,b.onprogress=null,b.onerror=null,null!=b.parentNode&&a.type==createjs.LoadQueue.SVG&&a.type==createjs.LoadQueue.JSON&&a.type==createjs.LoadQueue.MANIFEST&&a.type==createjs.LoadQueue.CSS&&a.type==createjs.LoadQueue.JSONP&&b.parentNode.removeChild(b));var a=this.getItem();(a.type==createjs.LoadQueue.JSONP||a.type==createjs.LoadQueue.MANIFEST)&&(window[a.callback]=null)},b.toString=function(){return"[PreloadJS TagLoader]"},createjs.TagLoader=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b){this.init(a,b)},b=a.prototype=new createjs.AbstractLoader;b._request=null,b._loadTimeout=null,b._xhrLevel=1,b._response=null,b._rawResponse=null,b._crossOrigin="",b.init=function(a,b){this._item=a,this._crossOrigin=b,!this._createXHR(a)},b.getResult=function(a){return a&&this._rawResponse?this._rawResponse:this._response},b.cancel=function(){this.canceled=!0,this._clean(),this._request.abort()},b.load=function(){if(null==this._request)return this._handleError(),void 0;if(this._request.onloadstart=createjs.proxy(this._handleLoadStart,this),this._request.onprogress=createjs.proxy(this._handleProgress,this),this._request.onabort=createjs.proxy(this._handleAbort,this),this._request.onerror=createjs.proxy(this._handleError,this),this._request.ontimeout=createjs.proxy(this._handleTimeout,this),1==this._xhrLevel){var a=createjs.LoadQueue.LOAD_TIMEOUT;if(0==a)a=createjs.LoadQueue.loadTimeout;else try{console.warn("LoadQueue.LOAD_TIMEOUT has been deprecated in favor of LoadQueue.loadTimeout")}catch(b){}this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),a)}this._request.onload=createjs.proxy(this._handleLoad,this),this._request.onreadystatechange=createjs.proxy(this._handleReadyStateChange,this);try{this._item.values&&this._item.method!=createjs.LoadQueue.GET?this._item.method==createjs.LoadQueue.POST&&this._request.send(this._formatQueryString(this._item.values)):this._request.send()}catch(c){var d=new createjs.Event("error");d.error=c,this._sendError(d)}},b.getAllResponseHeaders=function(){return this._request.getAllResponseHeaders instanceof Function?this._request.getAllResponseHeaders():null},b.getResponseHeader=function(a){return this._request.getResponseHeader instanceof Function?this._request.getResponseHeader(a):null},b._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.Event("progress");b.loaded=a.loaded,b.total=a.total,this._sendProgress(b)}},b._handleLoadStart=function(){clearTimeout(this._loadTimeout),this._sendLoadStart()},b._handleAbort=function(){this._clean();var a=new createjs.Event("error");a.text="XHR_ABORTED",this._sendError(a)},b._handleError=function(){this._clean();var a=new createjs.Event("error");this._sendError(a)},b._handleReadyStateChange=function(){4==this._request.readyState&&this._handleLoad()},b._handleLoad=function(){if(!this.loaded){if(this.loaded=!0,!this._checkError())return this._handleError(),void 0;this._response=this._getResponse(),this._clean();var a=this._generateTag();a&&this._sendComplete()}},b._handleTimeout=function(a){this._clean();var b=new createjs.Event("error");b.text="PRELOAD_TIMEOUT",this._sendError(a)},b._checkError=function(){var a=parseInt(this._request.status);switch(a){case 404:case 0:return!1}return!0},b._getResponse=function(){if(null!=this._response)return this._response;if(null!=this._request.response)return this._request.response;try{if(null!=this._request.responseText)return this._request.responseText}catch(a){}try{if(null!=this._request.responseXML)return this._request.responseXML}catch(a){}return null},b._createXHR=function(a){var b=this._isCrossDomain(a),c=null;if(b&&window.XDomainRequest)c=new XDomainRequest;else if(window.XMLHttpRequest)c=new XMLHttpRequest;else try{c=new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(d){try{c=new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(d){try{c=new ActiveXObject("Msxml2.XMLHTTP")}catch(d){return!1}}}createjs.LoadQueue.isText(a.type)&&c.overrideMimeType&&c.overrideMimeType("text/plain; charset=utf-8"),this._xhrLevel="string"==typeof c.responseType?2:1;var e=null;return e=a.method==createjs.LoadQueue.GET?this.buildPath(a.src,a.values):a.src,c.open(a.method||createjs.LoadQueue.GET,e,!0),b&&c instanceof XMLHttpRequest&&1==this._xhrLevel&&c.setRequestHeader("Origin",location.origin),a.values&&a.method==createjs.LoadQueue.POST&&c.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),createjs.LoadQueue.isBinary(a.type)&&(c.responseType="arraybuffer"),this._request=c,!0},b._clean=function(){clearTimeout(this._loadTimeout);var a=this._request;a.onloadstart=null,a.onprogress=null,a.onabort=null,a.onerror=null,a.onload=null,a.ontimeout=null,a.onloadend=null,a.onreadystatechange=null},b._generateTag=function(){var a=this._item.type,b=this._item.tag;switch(a){case createjs.LoadQueue.IMAGE:return b.onload=createjs.proxy(this._handleTagReady,this),""!=this._crossOrigin&&(b.crossOrigin="Anonymous"),b.src=this.buildPath(this._item.src,this._item.values),this._rawResponse=this._response,this._response=b,!1;case createjs.LoadQueue.JAVASCRIPT:return b=document.createElement("script"),b.text=this._response,this._rawResponse=this._response,this._response=b,!0;case createjs.LoadQueue.CSS:var c=document.getElementsByTagName("head")[0];if(c.appendChild(b),b.styleSheet)b.styleSheet.cssText=this._response;else{var d=document.createTextNode(this._response);b.appendChild(d)}return this._rawResponse=this._response,this._response=b,!0;case createjs.LoadQueue.XML:var e=this._parseXML(this._response,"text/xml");return this._rawResponse=this._response,this._response=e,!0;case createjs.LoadQueue.SVG:var e=this._parseXML(this._response,"image/svg+xml");return this._rawResponse=this._response,null!=e.documentElement?(b.appendChild(e.documentElement),this._response=b):this._response=e,!0;case createjs.LoadQueue.JSON:case createjs.LoadQueue.MANIFEST:var f={};try{f=JSON.parse(this._response)}catch(g){f=g}return this._rawResponse=this._response,this._response=f,!0}return!0},b._parseXML=function(a,b){var c=null;try{if(window.DOMParser){var d=new DOMParser;c=d.parseFromString(a,b)}else c=new ActiveXObject("Microsoft.XMLDOM"),c.async=!1,c.loadXML(a)}catch(e){}return c},b._handleTagReady=function(){this._sendComplete()},b.toString=function(){return"[PreloadJS XHRLoader]"},createjs.XHRLoader=a}(),"object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(a){return 10>a?"0"+a:a}function quote(a){return escapable.lastIndex=0,escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return"string"==typeof b?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function str(a,b){var c,d,e,f,g,h=gap,i=b[a];switch(i&&"object"==typeof i&&"function"==typeof i.toJSON&&(i=i.toJSON(a)),"function"==typeof rep&&(i=rep.call(b,a,i)),typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";if(gap+=indent,g=[],"[object Array]"===Object.prototype.toString.apply(i)){for(f=i.length,c=0;f>c;c+=1)g[c]=str(c,i)||"null";return e=0===g.length?"[]":gap?"[\n"+gap+g.join(",\n"+gap)+"\n"+h+"]":"["+g.join(",")+"]",gap=h,e}if(rep&&"object"==typeof rep)for(f=rep.length,c=0;f>c;c+=1)"string"==typeof rep[c]&&(d=rep[c],e=str(d,i),e&&g.push(quote(d)+(gap?": ":":")+e));else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&g.push(quote(d)+(gap?": ":":")+e));return e=0===g.length?"{}":gap?"{\n"+gap+g.join(",\n"+gap)+"\n"+h+"}":"{"+g.join(",")+"}",gap=h,e}}"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;"function"!=typeof JSON.stringify&&(JSON.stringify=function(a,b,c){var d;if(gap="",indent="","number"==typeof c)for(d=0;c>d;d+=1)indent+=" ";else"string"==typeof c&&(indent=c);if(rep=b,b&&"function"!=typeof b&&("object"!=typeof b||"number"!=typeof b.length))throw new Error("JSON.stringify");return str("",{"":a})}),"function"!=typeof JSON.parse&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&"object"==typeof e)for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),void 0!==d?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;if(text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})),/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(); \ No newline at end of file diff --git a/lib/preloadjs-NEXT.combined.js b/lib/preloadjs-NEXT.combined.js deleted file mode 100644 index 7698ec9c..00000000 --- a/lib/preloadjs-NEXT.combined.js +++ /dev/null @@ -1,4590 +0,0 @@ -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - /** - * Static class holding library specific information such as the version and buildDate of - * the library. - * - * The old PreloadJS class has been renamed to LoadQueue. Please see the {{#crossLink "LoadQueue"}}{{/crossLink}} - * class for information on loading files. - * @class PreloadJS - **/ - var s = createjs.PreloadJS = createjs.PreloadJS || {}; - - /** - * The version string for this release. - * @property version - * @type String - * @static - **/ - s.version = /*version*/"NEXT"; // injected by build process - - /** - * The build date for this release in UTC format. - * @property buildDate - * @type String - * @static - **/ - s.buildDate = /*date*/"Wed, 02 Apr 2014 17:54:19 GMT"; // injected by build process - -})(); -/* -* Event -* Visit http://createjs.com/ for documentation, updates and examples. -* -* Copyright (c) 2010 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * A collection of Classes that are shared across all the CreateJS libraries. The classes are included in the minified - * files of each library and are available on the createsjs namespace directly. - * - *

    Example

    - * myObject.addEventListener("change", createjs.proxy(myMethod, scope)); - * - * @module CreateJS - * @main CreateJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - -/** - * Contains properties and methods shared by all events for use with - * {{#crossLink "EventDispatcher"}}{{/crossLink}}. - * - * Note that Event objects are often reused, so you should never - * rely on an event object's state outside of the call stack it was received in. - * @class Event - * @param {String} type The event type. - * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. - * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. - * @constructor - **/ -var Event = function(type, bubbles, cancelable) { - this.initialize(type, bubbles, cancelable); -}; -var p = Event.prototype; - -// events: - -// public properties: - - /** - * The type of event. - * @property type - * @type String - **/ - p.type = null; - - /** - * The object that generated an event. - * @property target - * @type Object - * @default null - * @readonly - */ - p.target = null; - - /** - * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will - * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event - * is generated from childObj, then a listener on parentObj would receive the event with - * target=childObj (the original target) and currentTarget=parentObj (where the listener was added). - * @property currentTarget - * @type Object - * @default null - * @readonly - */ - p.currentTarget = null; - - /** - * For bubbling events, this indicates the current event phase:
      - *
    1. capture phase: starting from the top parent to the target
    2. - *
    3. at target phase: currently being dispatched from the target
    4. - *
    5. bubbling phase: from the target to the top parent
    6. - *
    - * @property eventPhase - * @type Number - * @default 0 - * @readonly - */ - p.eventPhase = 0; - - /** - * Indicates whether the event will bubble through the display list. - * @property bubbles - * @type Boolean - * @default false - * @readonly - */ - p.bubbles = false; - - /** - * 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 - */ - p.cancelable = false; - - /** - * The epoch time at which this event was created. - * @property timeStamp - * @type Number - * @default 0 - * @readonly - */ - p.timeStamp = 0; - - /** - * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called - * on this event. - * @property defaultPrevented - * @type Boolean - * @default false - * @readonly - */ - p.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 - */ - p.propagationStopped = false; - - /** - * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called - * on this event. - * @property immediatePropagationStopped - * @type Boolean - * @default false - * @readonly - */ - p.immediatePropagationStopped = false; - - /** - * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event. - * @property removed - * @type Boolean - * @default false - * @readonly - */ - p.removed = false; - -// constructor: - /** - * Initialization method. - * @method initialize - * @param {String} type The event type. - * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. - * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. - * @protected - **/ - p.initialize = function(type, bubbles, cancelable) { - this.type = type; - this.bubbles = bubbles; - this.cancelable = cancelable; - this.timeStamp = (new Date()).getTime(); - }; - -// public methods: - - /** - * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true. - * Mirrors the DOM event standard. - * @method preventDefault - **/ - p.preventDefault = function() { - this.defaultPrevented = 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); - }; - - /** - * 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; -}()); -/* -* EventDispatcher -* Visit http://createjs.com/ for documentation, updates and examples. -* -* Copyright (c) 2010 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * @module CreateJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - -/** - * EventDispatcher provides methods for managing queues of event listeners and dispatching events. - * - * You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the - * EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method. - * - * Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the - * DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports - * bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent. - * - * EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier - * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The - * {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to - * {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}. - * - * Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}} - * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also - * includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener. - * - *

    Example

    - * Add EventDispatcher capabilities to the "MyClass" class. - * - * EventDispatcher.initialize(MyClass.prototype); - * - * Add an event (see {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}}). - * - * instance.addEventListener("eventName", handlerMethod); - * function handlerMethod(event) { - * console.log(event.target + " Was Clicked"); - * } - * - * Maintaining proper scope
    - * Scope (ie. "this") can be be a challenge with events. Using the {{#crossLink "EventDispatcher/on"}}{{/crossLink}} - * method to subscribe to events simplifies this. - * - * instance.addEventListener("click", function(event) { - * console.log(instance == this); // false, scope is ambiguous. - * }); - * - * instance.on("click", function(event) { - * console.log(instance == this); // true, "on" uses dispatcher scope by default. - * }); - * - * If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage scope. - * - * - * @class EventDispatcher - * @constructor - **/ -var EventDispatcher = function() { -/* this.initialize(); */ // not needed. -}; -var p = EventDispatcher.prototype; - - - /** - * 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; - }; - -// constructor: - -// private properties: - /** - * @protected - * @property _listeners - * @type Object - **/ - p._listeners = null; - - /** - * @protected - * @property _captureListeners - * @type Object - **/ - p._captureListeners = null; - -// constructor: - /** - * Initialization method. - * @method initialize - * @protected - **/ - p.initialize = function() {}; - -// public methods: - /** - * Adds the specified event listener. Note that adding multiple listeners to the same function will result in - * multiple callbacks getting fired. - * - *

    Example

    - * - * displayObject.addEventListener("click", handleClick); - * function handleClick(event) { - * // Click happened. - * } - * - * @method addEventListener - * @param {String} type The string type of the event. - * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when - * the event is dispatched. - * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. - * @return {Function | Object} Returns the listener for chaining or assignment. - **/ - p.addEventListener = function(type, listener, useCapture) { - var listeners; - if (useCapture) { - listeners = this._captureListeners = this._captureListeners||{}; - } else { - listeners = this._listeners = this._listeners||{}; - } - var arr = listeners[type]; - if (arr) { this.removeEventListener(type, listener, useCapture); } - arr = listeners[type]; // remove may have deleted the array - if (!arr) { listeners[type] = [listener]; } - else { arr.push(listener); } - return listener; - }; - - /** - * A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener - * only run once, associate arbitrary data with the listener, and remove the listener. - * - * This method works by creating an anonymous wrapper function and subscribing it with addEventListener. - * The created anonymous function is returned for use with .removeEventListener (or .off). - * - *

    Example

    - * - * var listener = myBtn.on("click", handleClick, null, false, {count:3}); - * function handleClick(evt, data) { - * data.count -= 1; - * console.log(this == myBtn); // true - scope defaults to the dispatcher - * if (data.count == 0) { - * alert("clicked 3 times!"); - * myBtn.off("click", listener); - * // alternately: evt.remove(); - * } - * } - * - * @method on - * @param {String} type The string type of the event. - * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when - * the event is dispatched. - * @param {Object} [scope] The scope to execute the listener in. Defaults to the dispatcher/currentTarget for function listeners, and to the listener itself for object listeners (ie. using handleEvent). - * @param {Boolean} [once=false] If true, the listener will remove itself after the first time it is triggered. - * @param {*} [data] Arbitrary data that will be included as the second parameter when the listener is called. - * @param {Boolean} [useCapture=false] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. - * @return {Function} Returns the anonymous function that was created and assigned as the listener. This is needed to remove the listener later using .removeEventListener. - **/ - p.on = function(type, listener, scope, once, data, useCapture) { - if (listener.handleEvent) { - scope = scope||listener; - listener = listener.handleEvent; - } - scope = scope||this; - return this.addEventListener(type, function(evt) { - listener.call(scope, evt, data); - once&&evt.remove(); - }, useCapture); - }; - - /** - * Removes the specified event listener. - * - * Important Note: that you must pass the exact function reference used when the event was added. If a proxy - * function, or function closure is used as the callback, the proxy/closure reference must be used - a new proxy or - * closure will not work. - * - *

    Example

    - * - * displayObject.removeEventListener("click", handleClick); - * - * @method removeEventListener - * @param {String} type The string type of the event. - * @param {Function | Object} listener The listener function or object. - * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. - **/ - p.removeEventListener = function(type, listener, useCapture) { - var listeners = useCapture ? this._captureListeners : this._listeners; - if (!listeners) { return; } - var arr = listeners[type]; - if (!arr) { return; } - for (var i=0,l=arr.length; iExample - * - * // Remove all listeners - * displayObject.removeAllEventListeners(); - * - * // Remove all click listeners - * displayObject.removeAllEventListeners("click"); - * - * @method removeAllEventListeners - * @param {String} [type] The string type of the event. If omitted, all listeners for all types will be removed. - **/ - p.removeAllEventListeners = function(type) { - if (!type) { this._listeners = this._captureListeners = null; } - else { - if (this._listeners) { delete(this._listeners[type]); } - if (this._captureListeners) { delete(this._captureListeners[type]); } - } - }; - - /** - * Dispatches the specified event to all listeners. - * - *

    Example

    - * - * // Use a string event - * this.dispatchEvent("complete"); - * - * // Use an Event instance - * var event = new createjs.Event("progress"); - * this.dispatchEvent(event); - * - * @method dispatchEvent - * @param {Object | String | Event} eventObj An object with a "type" property, or a string type. - * While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used, - * dispatchEvent will construct an Event instance with the specified type. - * @param {Object} [target] The object to use as the target property of the event object. This will default to the - * dispatching object. This parameter is deprecated and will be removed. - * @return {Boolean} Returns the value of eventObj.defaultPrevented. - **/ - p.dispatchEvent = function(eventObj, target) { - if (typeof eventObj == "string") { - // won't bubble, so skip everything if there's no listeners: - var listeners = this._listeners; - if (!listeners || !listeners[eventObj]) { return false; } - eventObj = new createjs.Event(eventObj); - } - // TODO: deprecated. Target param is deprecated, only use case is MouseEvent/mousemove, remove. - eventObj.target = target||this; - - 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; iExample - * 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)); - }; - } - -}());/* -* AbstractLoader -* Visit http://createjs.com/ for documentation, updates and examples. -* -* -* Copyright (c) 2012 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * @module PreloadJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - /** - * The base loader, which defines all the generic callbacks and events. All loaders extend this class, including the - * {{#crossLink "LoadQueue"}}{{/crossLink}}. - * @class AbstractLoader - * @extends EventDispatcher - */ - var AbstractLoader = function () { - this.init(); - }; - - AbstractLoader.prototype = new createjs.EventDispatcher(); //TODO: TEST! - var p = AbstractLoader.prototype; - var s = AbstractLoader; - - /** - * The Regular Expression used to test file URLS for an absolute path. - * @property ABSOLUTE_PATH - * @static - * @type {RegExp} - * @since 0.4.2 - */ - s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i; - - /** - * The Regular Expression used to test file URLS for an absolute path. - * @property RELATIVE_PATH - * @static - * @type {RegExp} - * @since 0.4.2 - */ - 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 - * @static - * @type {RegExp} - * @since 0.4.2 - */ - s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i; - - /** - * 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 event. - * @property loaded - * @type {Boolean} - * @default false - */ - p.loaded = false; - - /** - * Determine if the loader was canceled. Canceled loads will not fire complete events. Note that - * {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "AbstractLoader/close"}}{{/crossLink}} - * instead of setting this property. - * @property canceled - * @type {Boolean} - * @default false - */ - p.canceled = false; - - /** - * The current load progress (percentage) for this item. This will be a number between 0 and 1. - * - *

    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 - */ - p.progress = 0; - - /** - * The item this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}}, but will - * be available on loaders such as {{#crossLink "XHRLoader"}}{{/crossLink}} and {{#crossLink "TagLoader"}}{{/crossLink}}. - * @property _item - * @type {Object} - * @private - */ - p._item = null; - -// Events - /** - * The event that is fired when the overall progress changes. - * @event progress - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Number} loaded The amount that has been loaded so far. Note that this is may just be a percentage of 1, - * since file sizes can not be determined before a load is kicked off, if at all. - * @param {Number} total The total number of bytes. Note that this may just be 1. - * @param {Number} progress The ratio that has been loaded between 0 and 1. - * @since 0.3.0 - */ - - /** - * The event that is fired when a load starts. - * @event loadstart - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.3.1 - */ - - /** - * The event that is fired when the entire queue has been loaded. - * @event complete - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.3.0 - */ - - /** - * The event that is fired when the loader encounters an error. If the error was encountered by a file, the event will - * contain the item that caused the error. There may be additional properties such as the error reason on event - * objects. - * @event error - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Object} [item] The item that was being loaded that caused the error. The item was specified in - * the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * call. If only a string path or tag was specified, the object will contain that value as a `src` property. - * @param {String} [error] The error object or text. - * @since 0.3.0 - */ - - //TODO: Deprecated - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}} - * event. - * @property onProgress - * @type {Function} - * @deprecated Use addEventListener and the "progress" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}} - * event. - * @property onLoadStart - * @type {Function} - * @deprecated Use addEventListener and the "loadstart" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} - * event. - * @property onComplete - * @type {Function} - * @deprecated Use addEventListener and the "complete" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} - * event. - * @property onError - * @type {Function} - * @deprecated Use addEventListener and the "error" event. - */ - - /** - * Get a reference to the manifest item that is loaded by this loader. In most cases this will be the value that was - * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or - * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will - * be an Object created by the LoadQueue. - * @return {Object} The manifest item that this loader is responsible for loading. - */ - p.getItem = function() { - return this._item; - }; - - /** - * Initialize the loader. This is called by the constructor. - * @method init - * @private - */ - p.init = function () {}; - - /** - * Begin loading the queued items. This method can be called when a {{#crossLink "LoadQueue"}}{{/crossLink}} is set - * up but not started immediately. - * @example - * var queue = new createjs.LoadQueue(); - * queue.addEventListener("complete", handleComplete); - * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet - * queue.load(); - * @method load - */ - p.load = function() {}; - - /** - * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from - * starting to download. Note that currently any active loads will remain open, and events may be processed. - * - * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead. - * @method close - */ - p.close = function() {}; - - -//Callback proxies - /** - * Dispatch a loadstart event. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}} event - * for details on the event payload. - * @method _sendLoadStart - * @protected - */ - p._sendLoadStart = function() { - if (this._isCanceled()) { return; } - this.dispatchEvent("loadstart"); - }; - - /** - * Dispatch a progress event. Please see the {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}} event for - * details on the event payload. - * @method _sendProgress - * @param {Number | Object} value The progress of the loaded item, or an object containing loaded - * and total properties. - * @protected - */ - p._sendProgress = function(value) { - if (this._isCanceled()) { return; } - var event = null; - if (typeof(value) == "number") { - this.progress = value; - event = new createjs.Event("progress"); - event.loaded = this.progress; - event.total = 1; - } else { - event = value; - this.progress = value.loaded / value.total; - if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } - } - event.progress = this.progress; - this.hasEventListener("progress") && this.dispatchEvent(event); - }; - - /** - * Dispatch a complete event. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event - * for details on the event payload. - * @method _sendComplete - * @protected - */ - p._sendComplete = function() { - if (this._isCanceled()) { return; } - this.dispatchEvent("complete"); - }; - - /** - * Dispatch an error event. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} event for - * details on the event payload. - * @method _sendError - * @param {Object} event The event object containing specific error properties. - * @protected - */ - p._sendError = function(event) { - if (this._isCanceled() || !this.hasEventListener("error")) { return; } - if (event == null) { - event = new createjs.Event("error"); - } - this.dispatchEvent(event); - }; - - /** - * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events - * do not cause issues after the queue has been cleaned up. - * @method _isCanceled - * @return {Boolean} If the loader has been canceled. - * @protected - */ - p._isCanceled = function() { - if (window.createjs == null || this.canceled) { - return true; - } - return false; - }; - - /** - * @method _parseURI - * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know: - *
      - *
    • If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or - * `//networkPath`)
    • - *
    • If the path is relative. Relative paths start with `../` or `/path` (or similar)
    • - *
    • The file extension. This is determined by the filename with an extension. Query strings are dropped, and - * the file path is expected to follow the format `name.ext`.
    • - *
    - * - * Note: This has changed from earlier versions, which used a single, complicated Regular Expression, which - * was difficult to maintain, and over-aggressive in determining all file properties. It has been simplified to - * only pull out what it needs. - * @param path - * @returns {Object} An Object with an `absolute` and `relative` Boolean, as well as an optional 'extension` String - * property, which is the lowercase extension. - * @private - */ - p._parseURI = function(path) { - var info = { absolute: false, relative:false }; - if (path == null) { return info; }; - - // Drop the query string - var queryIndex = path.indexOf("?"); - if (queryIndex > -1) { - path = path.substr(0,queryIndex); - } - - // Absolute - var match; - if (s.ABSOLUTE_PATT.test(path)) { - info.absolute = true; - - // Relative - } else if (s.RELATIVE_PATT.test(path)) { - info.relative = true; - } - - // Extension - if (match = path.match(s.EXTENSION_PATT)) { - info.extension = match[1].toLowerCase(); - } - return info; - }; - - /** - * Formats an object into a query string for either a POST or GET request. - * @method _formatQueryString - * @param {Object} data The data to convert to a query string. - * @param {Array} [query] Existing name/value pairs to append on to this query. - * @private - */ - p._formatQueryString = function(data, query) { - if (data == null) { - throw new Error('You must specify data.'); - } - var params = []; - for (var n in data) { - params.push(n+'='+escape(data[n])); - } - if (query) { - params = params.concat(query); - } - return params.join('&'); - }; - - /** - * A utility method that builds a file path using a source and a data object, and formats it into a new path. All - * of the loaders in PreloadJS use this method to compile paths when loading. - * @method buildPath - * @param {String} src The source path to add values to. - * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the - * path will be preserved. - * @returns {string} A formatted string that contains the path and the supplied parameters. - * @since 0.3.1 - */ - p.buildPath = function(src, 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 {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. - * @private - */ - p._isCrossDomain = function(item) { - var target = document.createElement("a"); - target.href = item.src; - - var host = document.createElement("a"); - host.href = location.href; - - var crossdomain = (target.hostname != "") && - (target.port != host.port || - target.protocol != host.protocol || - target.hostname != host.hostname); - return crossdomain; - } - - /** - * @method _isLocal - * @param {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. - * @private - */ - p._isLocal = function(item) { - var target = document.createElement("a"); - target.href = item.src; - return target.hostname == "" && target.protocol == "file:"; - }; - - /** - * @method toString - * @return {String} a string representation of the instance. - */ - p.toString = function() { - return "[PreloadJS AbstractLoader]"; - }; - - createjs.AbstractLoader = AbstractLoader; - -}()); -/* -* LoadQueue -* Visit http://createjs.com/ for documentation, updates and examples. -* -* -* Copyright (c) 2012 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ -/** - * PreloadJS provides a consistent way to preload content for use in HTML applications. Preloading can be done using - * HTML tags, as well as XHR. - * - * By default, PreloadJS will try and load content using XHR, since it provides better support for progress and - * completion events, however due to cross-domain issues, it may still be preferable to use tag-based loading - * instead. Note that some content requires XHR to work (plain text, web audio), and some requires tags (HTML audio). - * Note this is handled automatically where possible. - * - * PreloadJS currently supports all modern browsers, and we have done our best to include support for most older - * browsers. If you find an issue with any specific OS/browser combination, please visit http://community.createjs.com/ - * and report it. - * - *

    Getting Started

    - * To get started, check out the {{#crossLink "LoadQueue"}}{{/crossLink}} class, which includes a quick overview of how - * to load files and process results. - * - *

    Example

    - * - * var queue = new createjs.LoadQueue(); - * queue.installPlugin(createjs.Sound); - * queue.on("complete", handleComplete, this); - * queue.loadFile({id:"sound", src:"http://path/to/sound.mp3"}); - * queue.loadManifest([ - * {id: "myImage", src:"path/to/myImage.jpg"} - * ]); - * function handleComplete() { - * createjs.Sound.play("sound"); - * var image = queue.getResult("myImage"); - * document.body.appendChild(image); - * } - * - * Important note on plugins: Plugins must be installed before items are added to the queue, otherwise - * they will not be processed, even if the load has not actually kicked off yet. Plugin functionality is handled when - * the items are added to the LoadQueue. - * - *

    Browser Support

    - * PreloadJS is partially supported in all browsers, and fully supported in all modern browsers. Known exceptions: - *
    • XHR loading of any content will not work in many older browsers (See a matrix here: http://caniuse.com/xhr2). - * In many cases, you can fall back on tag loading (images, audio, CSS, scripts, SVG, and JSONP). Text and - * WebAudio will only work with XHR.
    • - *
    • Some formats have poor support for complete events in IE 6, 7, and 8 (SVG, tag loading of scripts, XML/JSON)
    • - *
    • Opera has poor support for SVG loading with XHR
    • - *
    • CSS loading in Android and Safari will not work with tags (currently, a workaround is in progress)
    • - *
    • Local loading is not permitted with XHR, which is required by some file formats. When testing local content - * use either a local server, or enable tag loading, which is supported for most formats. See {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} - * for more information.
    • - *
    - * - *

    Cross-domain Loading

    - * Most content types can be loaded cross-domain, as long as the server supports CORS. PreloadJS also has internal - * support for images served from a CORS-enabled server, via the `crossOrigin` argument on the {{#crossLink "LoadQueue"}}{{/crossLink}} - * constructor. If set to a string value (such as "Anonymous"), the "crossOrigin" property of images generated by - * PreloadJS is set to that value. Please note that setting a `crossOrigin` value on an image that is served from a - * server without CORS will cause other errors. For more info on CORS, visit https://en.wikipedia.org/wiki/Cross-origin_resource_sharing. - * - * @module PreloadJS - * @main PreloadJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -/* -TODO: WINDOWS ISSUES - * No error for HTML audio in IE 678 - * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR - * No script complete handler in IE 67 TAGS (XHR is fine) - * No XML/JSON in IE6 TAGS - * Need to hide loading SVG in Opera TAGS - * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking) - * SVG no load or failure in Opera XHR - * Reported issues with IE7/8 - */ - -(function() { - "use strict"; - - /** - * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either - * a single file, or queue of files. - * - * Creating a Queue
    - * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the useXHR - * argument to false. - * - * var queue = new createjs.LoadQueue(true); - * - * Listening for Events
    - * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}} - * lets you add as many listeners as you want for events. You can subscribe to the following events:
      - *
    • {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all - * files
    • - *
    • {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with - * any file.
    • - *
    • {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has - * changed.
    • - *
    • {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.
    • - *
    • {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note - * that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.
    • - *
    - * - * queue.on("fileload", handleFileLoad, this); - * queue.on("complete", handleComplete, this); - * - * Adding files and manifests
    - * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a - * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are - * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you - * like. - * - * queue.loadFile("filePath/file.jpg"); - * queue.loadFile({id:"image", src:"filePath/file.jpg"}); - * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]); - * - * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not - * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin - * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a - * `loadNow` argument of `true`. - * - * queue.load(); - * - * File Types
    - * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS - * should handle the majority of standard file and url formats, and works with common file extensions. If you have - * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a - * type property with any manifest item. - * - * queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.LoadQueue.SOUND}); - * - * // Note that PreloadJS will not read a file extension from the query string - * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:createjs.LoadQueue.IMAGE}); - * - * Supported types are defined on the LoadQueue class, and include: - *
      - *
    • {{#crossLink "LoadQueue/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
    • - *
    • {{#crossLink "LoadQueue/CSS:property"}}{{/crossLink}}: CSS files
    • - *
    • {{#crossLink "LoadQueue/IMAGE:property"}}{{/crossLink}}: Common image formats
    • - *
    • {{#crossLink "LoadQueue/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
    • - *
    • {{#crossLink "LoadQueue/JSON:property"}}{{/crossLink}}: JSON data
    • - *
    • {{#crossLink "LoadQueue/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
    • - *
    • {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see - * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
    • - *
    • {{#crossLink "LoadQueue/SOUND:property"}}{{/crossLink}}: Audio file formats
    • - *
    • {{#crossLink "LoadQueue/SVG:property"}}{{/crossLink}}: SVG files
    • - *
    • {{#crossLink "LoadQueue/TEXT:property"}}{{/crossLink}}: Text files - XHR only
    • - *
    • {{#crossLink "LoadQueue/XML:property"}}{{/crossLink}}: XML data
    • - *
    - * - * Handling Results
    - * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is - * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a - * resolved object that can be used immediately, including: - *
      - *
    • Image: An <img /> tag
    • - *
    • Audio: An <audio /> tag - *
    • JavaScript: A <script /> tag
    • - *
    • CSS: A <link /> tag
    • - *
    • XML: An XML DOM node
    • - *
    • SVG: An <object /> tag
    • - *
    • JSON: A formatted JavaScript Object
    • - *
    • Text: Raw text
    • - *
    • Binary: The binary loaded result
    • - *
    - * - * function handleFileLoad(event) { - * var item = event.item; // A reference to the item that was passed in to the LoadQueue - * var type = item.type; - * - * // Add any images to the page body. - * if (type == createjs.LoadQueue.IMAGE) { - * document.body.appendChild(event.result); - * } - * } - * - * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up - * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the "src" or - * file path can be used instead, including the `path` defined by a manifest, but not including a - * base path defined on the LoadQueue. It is recommended to always pass an id. - * - * var image = queue.getResult("image"); - * document.body.appendChild(image); - * - * Raw loaded content can be accessed using the rawResult property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} - * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd - * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript, - * CSS, XML, SVG, and JSON objects, or anything loaded with XHR. - * - * var image = queue.getResult("image", true); // load the binary image data loaded with XHR. - * - * Plugins
    - * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio, - * make sure to install the SoundJS Sound class, which will help load HTML audio, - * Flash audio, and WebAudio files. This should be installed before loading any audio files. - * - * queue.installPlugin(createjs.Sound); - * - *

    Known Browser Issues

    - *
      - *
    • Browsers without audio support can not load audio files.
    • - *
    • Safari on Mac OS X can only play HTML audio if QuickTime is installed
    • - *
    • HTML Audio tags will only download until their canPlayThrough event is fired. Browsers other - * than Chrome will continue to download in the background.
    • - *
    • When loading scripts using tags, they are automatically added to the document.
    • - *
    • Scripts loaded via XHR may not be properly inspectable with browser tools.
    • - *
    • IE6 and IE7 (and some other browsers) may not be able to load XML, Text, or JSON, since they require - * XHR to work.
    • - *
    • Content loaded via tags will not show progress, and will continue to download in the background when - * canceled, although no events will be dispatched.
    • - *
    - * - * @class LoadQueue - * @param {Boolean} [useXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP - * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR - * when necessary. - * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue - * before they are loaded. Sources beginning with a protocol such as `http://` or a relative path such as `../` - * will not receive a base path. - * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To - * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any - * string value will be passed through, but only "" and "Anonymous" are recommended. - * @constructor - * @extends AbstractLoader - */ - var LoadQueue = function(useXHR, basePath, crossOrigin) { - this.init(useXHR, basePath, crossOrigin); - }; - - var p = LoadQueue.prototype = new createjs.AbstractLoader(); - var s = LoadQueue; - - /** - * Time in milliseconds to assume a load has failed. An {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} - * event is dispatched if the timeout is reached before any data is received. - * @property loadTimeout - * @type {Number} - * @default 8000 - * @static - * @since 0.4.1 - */ - s.loadTimeout = 8000; - - /** - * Time in milliseconds to assume a load has failed. - * @type {Number} - * @deprecated in favor of the {{#crossLink "LoadQueue/loadTimeout:property"}}{{/crossLink}} property. - */ - s.LOAD_TIMEOUT = 0; - -// Preload Types - /** - * 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 - */ - 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 - */ - s.CSS = "css"; - - /** - * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag. - * @property IMAGE - * @type {String} - * @default image - * @static - */ - s.IMAGE = "image"; - - /** - * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a - * <script> tag. - * - * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into - * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier, - * only tag-loaded scripts are injected. - * @property JAVASCRIPT - * @type {String} - * @default javascript - * @static - */ - s.JAVASCRIPT = "javascript"; - - /** - * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a - * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP, - * no matter what the {{#crossLink "LoadQueue/useXHR:property"}}{{/crossLink}} property is set to, and the JSON - * must contain a matching wrapper function. - * @property JSON - * @type {String} - * @default json - * @static - */ - s.JSON = "json"; - - /** - * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a - * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON. - * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/useXHR:property"}}{{/crossLink}} - * property is set to. - * @property JSONP - * @type {String} - * @default jsonp - * @static - */ - s.JSONP = "jsonp"; - - /** - * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded - * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an - * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead, - * regardless of what the {{#crossLink "LoadQueue/useXHR:property"}}{{/crossLink}} property is set to. - * @property MANIFEST - * @type {String} - * @default manifest - * @static - * @since 0.4.1 - */ - s.MANIFEST = "manifest"; - - /** - * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an - * <audio> tag. - * @property SOUND - * @type {String} - * @default sound - * @static - */ - s.SOUND = "sound"; - - /** - * The preload type for SVG files. - * @property SVG - * @type {String} - * @default svg - * @static - */ - s.SVG = "svg"; - - /** - * The preload type for text files, which is also the default file type if the type can not be determined. Text is - * loaded as raw text. - * @property TEXT - * @type {String} - * @default text - * @static - */ - s.TEXT = "text"; - - /** - * The preload type for xml files. XML is loaded into an XML document. - * @property XML - * @type {String} - * @default xml - * @static - */ - s.XML = "xml"; - - /** - * Defines a POST request, use for a method value when loading data. - * - * @type {string} - */ - s.POST = 'POST'; - - /** - * Defines a GET request, use for a method value when loading data. - * - * @type {string} - */ - s.GET = 'GET'; - - -// Prototype - /** - * A path that will be prepended on to the item's `src`. The `_basePath` property will only be used if an item's - * source is relative, and does not include a protocol such as `http://`, or a relative path such as `../`. - * @property _basePath - * @type {String} - * @private - * @since 0.3.1 - */ - p._basePath = null; - - /** - * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded - * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by - * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues, - * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are "" - * and "Anonymous". - * @property _crossOrigin - * @type {String} - * @defaultValue "" - * @private - * @since 0.4.1 - */ - p._crossOrigin = ""; - - /** - * Use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR loading depending - * on the requirements for a media type. For example, HTML audio can not be loaded with XHR, and WebAudio can not be - * loaded with tags, so it will default the the correct type instead of using the user-defined type. - * - * Note: This property is read-only. To change it, please use the {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} - * method, or specify the `useXHR` argument in the LoadQueue constructor. - * - * @property useXHR - * @type {Boolean} - * @readOnly - * @default true - */ - p.useXHR = true; - - /** - * Determines if the LoadQueue will stop processing the current queue when an error is encountered. - * @property stopOnError - * @type {Boolean} - * @default false - */ - p.stopOnError = false; - - /** - * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head - * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas - * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order - * specified. - * - * Any items can be set to load in order by setting the `maintainOrder` property on the load item, or by ensuring - * that only one connection can be open at a time using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. - * Note that when the `maintainScriptOrder` property is set to `true`, scripts items are automatically set to - * `maintainOrder=true`, and changing the `maintainScriptOrder` to `false` during a load will not change items - * already in a queue. - * - *

    Example

    - * - * var queue = new createjs.LoadQueue(); - * queue.setMaxConnections(3); // Set a higher number to load multiple items at once - * queue.maintainScriptOrder = true; // Ensure scripts are loaded in order - * queue.loadManifest([ - * "script1.js", - * "script2.js", - * "image.png", // Load any time - * {src: "image2.png", maintainOrder: true} // Will wait for script2.js - * "image3.png", - * "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR) - * ]); - * - * @property maintainScriptOrder - * @type {Boolean} - * @default true - */ - p.maintainScriptOrder = true; - - /** - * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and - * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed. - * @property next - * @type {LoadQueue} - * @default null - */ - p.next = null; - -// Events - /** - * This event is fired when an individual file has loaded, and been processed. - * @event fileload - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the - * object will contain that value as a `src` property. - * @param {Object} result The HTML tag or parsed result of the loaded item. - * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted - * to a usable object. - * @since 0.3.0 - */ - - /** - * This event is fired when an an individual file progress changes. - * @event fileprogress - * @param {Object} The object that dispatched the event. - * @param {String} type The event type. - * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the - * object will contain that value as a `src` property. - * @param {Number} loaded The number of bytes that have been loaded. Note that this may just be a percentage of 1. - * @param {Number} total The total number of bytes. If it is unknown, the value is 1. - * @param {Number} progress The amount that has been loaded between 0 and 1. - * @since 0.3.0 - */ - - /** - * This event is fired when an individual file starts to load. - * @event filestart - * @param {Object} The object that dispatched the event. - * @param {String} type The event type. - * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the - * object will contain that value as a property. - */ - - //TODO: Deprecated - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} - * event. - * @property onFileLoad - * @type {Function} - * @deprecated Use addEventListener and the "fileload" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}} - * event. - * @property onFileProgress - * @type {Function} - * @deprecated Use addEventListener and the "fileprogress" event. - */ - - -// Protected - /** - * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the - * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} - * method for more information. - * @property _typeCallbacks - * @type {Object} - * @private - */ - p._typeCallbacks = null; - - /** - * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the - * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} - * method for more information. - * @property _extensionCallbacks - * @type {null} - * @private - */ - p._extensionCallbacks = null; - - /** - * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first - * file is requested. - * @property _loadStartWasDispatched - * @type {Boolean} - * @default false - * @private - */ - p._loadStartWasDispatched = false; - - /** - * The number of maximum open connections that a loadQueue tries to maintain. Please see - * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information. - * @property _maxConnections - * @type {Number} - * @default 1 - * @private - */ - p._maxConnections = 1; - - /** - * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when - * using a script tag to do preloading. - * @property _currentlyLoadingScript - * @type {Boolean} - * @private - */ - p._currentlyLoadingScript = null; - - /** - * An array containing the currently downloading files. - * @property _currentLoads - * @type {Array} - * @private - */ - p._currentLoads = null; - - /** - * An array containing the queued items that have not yet started downloading. - * @property _loadQueue - * @type {Array} - * @private - */ - p._loadQueue = null; - - /** - * An array containing downloads that have not completed, so that the LoadQueue can be properly reset. - * @property _loadQueueBackup - * @type {Array} - * @private - */ - p._loadQueueBackup = null; - - /** - * An object hash of items that have finished downloading, indexed by item IDs. - * @property _loadItemsById - * @type {Object} - * @private - */ - p._loadItemsById = null; - - /** - * An object hash of items that have finished downloading, indexed by item source. - * @property _loadItemsBySrc - * @type {Object} - * @private - */ - p._loadItemsBySrc = null; - - /** - * An object hash of loaded items, indexed by the ID of the load item. - * @property _loadedResults - * @type {Object} - * @private - */ - p._loadedResults = null; - - /** - * An object hash of un-parsed loaded items, indexed by the ID of the load item. - * @property _loadedRawResults - * @type {Object} - * @private - */ - p._loadedRawResults = null; - - /** - * The number of items that have been requested. This helps manage an overall progress without knowing how large - * the files are before they are downloaded. - * @property _numItems - * @type {Number} - * @default 0 - * @private - */ - p._numItems = 0; - - /** - * The number of items that have completed loaded. This helps manage an overall progress without knowing how large - * the files are before they are downloaded. - * @property _numItemsLoaded - * @type {Number} - * @default 0 - * @private - */ - p._numItemsLoaded = 0; - - /** - * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right - * order. - * @property _scriptOrder - * @type {Array} - * @private - */ - p._scriptOrder = null; - - /** - * A list of scripts that have been loaded. Items are added to this list as null when they are - * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true - * once they are complete and have been dispatched. - * @property _loadedScripts - * @type {Array} - * @private - */ - p._loadedScripts = null; - - // Overrides abstract method in AbstractLoader - p.init = function(useXHR, basePath, crossOrigin) { - this._numItems = this._numItemsLoaded = 0; - this._paused = false; - this._loadStartWasDispatched = false; - - this._currentLoads = []; - this._loadQueue = []; - this._loadQueueBackup = []; - this._scriptOrder = []; - this._loadedScripts = []; - this._loadItemsById = {}; - this._loadItemsBySrc = {}; - this._loadedResults = {}; - this._loadedRawResults = {}; - - // Callbacks for plugins - this._typeCallbacks = {}; - this._extensionCallbacks = {}; - - this._basePath = basePath; - this.setUseXHR(useXHR); - this._crossOrigin = (crossOrigin === true) - ? "Anonymous" : (crossOrigin === false || crossOrigin == null) - ? "" : crossOrigin; - }; - - /** - * Change the usXHR value. Note that if this is set to true, it may fail depending on the browser's capabilities. - * Additionally, some files require XHR in order to load, such as JSON (without JSONP), Text, and XML, so XHR will - * be used regardless of what is passed to this method. - * @method setUseXHR - * @param {Boolean} value The new useXHR value to set. - * @return {Boolean} The new useXHR value. If XHR is not supported by the browser, this will return false, even if - * the provided value argument was true. - * @since 0.3.0 - */ - p.setUseXHR = function(value) { - // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it. - //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR. - this.useXHR = (value != false && window.XMLHttpRequest != null); - return this.useXHR; - }; - - /** - * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded - * content, and allows the queue to be used again. - * @method removeAll - * @since 0.3.0 - */ - p.removeAll = function() { - this.remove(); - }; - - /** - * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed. - * This also removes internal references to loaded item(s). - * - *

    Example

    - * - * queue.loadManifest([ - * {src:"test.png", id:"png"}, - * {src:"test.jpg", id:"jpg"}, - * {src:"test.mp3", id:"mp3"} - * ]); - * queue.remove("png"); // Single item by ID - * queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src. - * queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src. - * - * @method remove - * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of - * items, or multiple items as arguments. - * @since 0.3.0 - */ - p.remove = function(idsOrUrls) { - var args = null; - - if (idsOrUrls && !(idsOrUrls instanceof Array)) { - args = [idsOrUrls]; - } else if (idsOrUrls) { - args = idsOrUrls; - } else if (arguments.length > 0) { - return; - } - - var itemsWereRemoved = false; - - // Destroy everything - if (!args) { - this.close(); - for (var n in this._loadItemsById) { - this._disposeItem(this._loadItemsById[n]); - } - this.init(this.useXHR); - - // Remove specific items - } else { - while (args.length) { - var item = args.pop(); - var r = this.getResult(item); - - //Remove from the main load Queue - for (i = this._loadQueue.length-1;i>=0;i--) { - loadItem = this._loadQueue[i].getItem(); - if (loadItem.id == item || loadItem.src == item) { - this._loadQueue.splice(i,1)[0].cancel(); - break; - } - } - - //Remove from the backup queue - for (i = this._loadQueueBackup.length-1;i>=0;i--) { - loadItem = this._loadQueueBackup[i].getItem(); - if (loadItem.id == item || loadItem.src == item) { - this._loadQueueBackup.splice(i,1)[0].cancel(); - break; - } - } - - if (r) { - delete this._loadItemsById[r.id]; - delete this._loadItemsBySrc[r.src]; - this._disposeItem(r); - } else { - for (var i=this._currentLoads.length-1;i>=0;i--) { - var loadItem = this._currentLoads[i].getItem(); - if (loadItem.id == item || loadItem.src == item) { - this._currentLoads.splice(i,1)[0].cancel(); - itemsWereRemoved = true; - break; - } - } - } - } - - // If this was called during a load, try to load the next item. - if (itemsWereRemoved) { - this._loadNext(); - } - } - }; - - /** - * Stops all open loads, destroys any loaded items, and resets the queue, so all items can - * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the - * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or - * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method. - * @method reset - * @since 0.3.0 - */ - p.reset = function() { - this.close(); - for (var n in this._loadItemsById) { - this._disposeItem(this._loadItemsById[n]); - } - - //Reset the queue to its start state - var a = []; - for (var i=0, l=this._loadQueueBackup.length; inot a binary type, as we can not play - * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get - * a binary result to work with. Binary files are loaded using XHR2. - * @method isBinary - * @param {String} type The item type. - * @return {Boolean} If the specified type is binary. - * @private - */ - s.isBinary = function(type) { - switch (type) { - case createjs.LoadQueue.IMAGE: - case createjs.LoadQueue.BINARY: - return true; - default: - return false; - } - }; - - - /** - * 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. - * @private - */ - s.isText = function(type) { - switch (type) { - case createjs.LoadQueue.TEXT: - case createjs.LoadQueue.JSON: - case createjs.LoadQueue.MANIFEST: - case createjs.LoadQueue.XML: - case createjs.LoadQueue.HTML: - case createjs.LoadQueue.CSS: - case createjs.LoadQueue.SVG: - case createjs.LoadQueue.JAVASCRIPT: - return true; - default: - return false; - } - }; - - /** - * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc). - * Currently, only one plugin can exist per type/extension. - * - * When a plugin is installed, a getPreloadHandlers() method will be called on it. For more information - * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the - * {{#crossLink "SamplePlugin"}}{{/crossLink}} class. - * - * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned - * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its - * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when - * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these - * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}} - * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}. - * - * @method installPlugin - * @param {Function} plugin The plugin class to install. - */ - p.installPlugin = function(plugin) { - if (plugin == null || plugin.getPreloadHandlers == null) { return; } - var map = plugin.getPreloadHandlers(); - map.scope = plugin; - - if (map.types != null) { - for (var i=0, l=map.types.length; iExample - * - * var queue = new createjs.LoadQueue(); - * queue.setMaxConnections(10); // Allow 10 concurrent loads - * - * @method setMaxConnections - * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue - * is open at any time. - */ - p.setMaxConnections = function (value) { - this._maxConnections = value; - if (!this._paused && this._loadQueue.length > 0) { - this._loadNext(); - } - }; - - /** - * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * method. - * - * Files are always appended to the current queue, so this method can be used multiple times to add files. - * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method. - * @method loadFile - * @param {Object | String} file The file object or path to load. A file can be either - *
      - *
    • A string path to a resource. Note that this kind of load item will be converted to an object (see below) - * in the background.
    • - *
    • OR an object that contains:
        - *
      • src: The source of the file that is being loaded. This property is required. The source can - * either be a string (recommended), or an HTML tag.
      • - *
      • type: The type of file that will be loaded (image, sound, json, etc). PreloadJS does auto-detection - * of types using the extension. Supported types are defined on LoadQueue, such as LoadQueue.IMAGE. - * It is recommended that a type is specified when a non-standard file URI (such as a php script) us used.
      • - *
      • id: A string identifier which can be used to reference the loaded object.
      • - *
      • maintainOrder: Set to `true` to ensure this asset loads in the order defined in the manifest. This - * will happen when the max connections has been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}), - * and will only affect other assets also defined as `maintainOrder`. Everything else 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`.
      • - *
      • callback: Optional, used for JSONP requests, to define what method to call when the JSONP is loaded.
      • - *
      • data: An arbitrary data object, which is included with the loaded object
      • - *
      • method: used to define if this request uses GET or POST when sending data to the server. The default - * value is "GET"
      • - *
      • values: Optional object of name/value pairs to send to the server.
      • - *
      • headers: Optional 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 if needed.
      • - *
      - *
    - * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default - * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is - * `true`, the queue will resume automatically. - * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the - * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}}, - * its files will NOT use the basePath parameter. The basePath parameter is deprecated. - * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue - * constructor, or a `path` property in a manifest definition. - */ - p.loadFile = function(file, loadNow, basePath) { - if (file == null) { - var event = new createjs.Event("error"); - event.text = "PRELOAD_NO_FILE"; - this._sendError(event); - return; - } - this._addItem(file, null, basePath); - - if (loadNow !== false) { - this.setPaused(false); - } else { - this.setPaused(true); - } - }; - - /** - * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method. - * The files in the manifest are requested in the same order, but may complete in a different order if the max - * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load - * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is - * default). - * - * Files are always appended to the current queue, so this method can be used multiple times to add files. - * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method. - * @method loadManifest - * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of - * manifests: - *
      - *
    1. A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property, - * which defines the list of files to load, and can optionally contain a "path" property, which will be - * prepended to each file in the list.
    2. - *
    3. An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP - * file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load, - * and can optionally contain a "path" property, which will be prepended to each file in the list.
    4. - *
    5. An object which contains a "manifest" property, which defines the list of files to load, and can - * optionally contain a "path" property, which will be prepended to each file in the list.
    6. - *
    7. An Array of files to load.
    8. - *
    - * - * Each "file" in a manifest can be either: - *
      - *
    • A string path to a resource (string). Note that this kind of load item will be converted to an object - * (see below) in the background.
    • - *
    • OR an object that contains:
        - *
      • src: The source of the file that is being loaded. This property is required. The source can - * either be a string (recommended), or an HTML tag.
      • - *
      • type: The type of file that will be loaded (image, sound, json, etc). PreloadJS does auto-detection - * of types using the extension. Supported types are defined on LoadQueue, such as {{#crossLink "LoadQueue/IMAGE:property"}}{{/crossLink}}. - * It is recommended that a type is specified when a non-standard file URI (such as a php script) us used.
      • - *
      • id: A string identifier which can be used to reference the loaded object.
      • - *
      • maintainOrder: Set to `true` to ensure this asset loads in the order defined in the manifest. This - * will happen when the max connections has been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}), - * and will only affect other assets also defined as `maintainOrder`. Everything else 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`.
      • - *
      • callback: Optional, used for JSONP requests, to define what method to call when the JSONP is loaded.
      • - *
      • data: An arbitrary data object, which is included with the loaded object
      • - *
      • method: used to define if this request uses GET or POST when sending data to the server. The default - * value is "GET"
      • - *
      • values: Optional object of name/value pairs to send to the server.
      • - *
      • headers: Optional 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 if needed.
      • - *
      - *
    - * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default - * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is - * `true`, the queue will resume automatically. - * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the - * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}}, - * its files will NOT use the basePath parameter. The basePath parameter is deprecated. - * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue - * constructor, or a `path` property in a manifest definition. - */ - p.loadManifest = function(manifest, loadNow, basePath) { - var fileList = null; - var path = null; - - // Array-based list of items - if (manifest instanceof Array) { - if (manifest.length == 0) { - var event = new createjs.Event("error"); - event.text = "PRELOAD_MANIFEST_EMPTY"; - this._sendError(event); - return; - } - fileList = manifest; - - // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded. - } else if (typeof(manifest) === "string") { - fileList = [{ - src: manifest, - type: s.MANIFEST - }]; - - } else if (typeof(manifest) == "object") { - - // An object that defines a manifest path - if (manifest.src !== undefined) { - if (manifest.type == null) { - manifest.type = s.MANIFEST; - } else if (manifest.type != s.MANIFEST) { - var event = new createjs.Event("error"); - event.text = "PRELOAD_MANIFEST_ERROR"; - this._sendError(event); - } - fileList = [manifest]; - - // An object that defines a manifest - } else if (manifest.manifest !== undefined) { - fileList = manifest.manifest; - path = manifest.path; - } - - // Unsupported. This will throw an error. - } else { - var event = new createjs.Event("error"); - event.text = "PRELOAD_MANIFEST_NULL"; - this._sendError(event); - return; - } - - for (var i=0, l=fileList.length; iid
    or src of the load item. - * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} - * event as the `item` parameter. - */ - p.getItem = function(value) { - return this._loadItemsById[value] || this._loadItemsBySrc[value]; - }; - - /** - * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id" - * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The - * `basePath` will not be part of the ID. - * @method getResult - * @param {String} value The id or src of the load item. - * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content - * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be - * returned instead. - * @return {Object} A result object containing the content that was loaded, such as: - *
      - *
    • An image tag (<image />) for images
    • - *
    • A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML - * DOM.
    • - *
    • A style tag for CSS (<style /> or <link >)
    • - *
    • Raw text for TEXT
    • - *
    • A formatted JavaScript object defined by JSON
    • - *
    • An XML document
    • - *
    • A binary arraybuffer loaded by XHR
    • - *
    • An audio tag (<audio >) for HTML audio. Note that it is recommended to use SoundJS APIs to play - * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method - * which can not be used to play audio back.
    • - *
    - * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item` - * parameter. Note that if a raw result is requested, but not found, the result will be returned instead. - */ - p.getResult = function(value, rawResult) { - var item = this._loadItemsById[value] || this._loadItemsBySrc[value]; - if (item == null) { return null; } - var id = item.id; - if (rawResult && this._loadedRawResults[id]) { - return this._loadedRawResults[id]; - } - return this._loadedResults[id]; - }; - - /** - * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not - * be processed when active loads complete. LoadQueues are not paused by default. - * - * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, - * a paused queue will be resumed, unless the `loadNow` argument is `false`. - * @method setPaused - * @param {Boolean} value Whether the queue should be paused or not. - */ - p.setPaused = function(value) { - this._paused = value; - if (!this._paused) { - this._loadNext(); - } - }; - - // Overrides abstract method in AbstractLoader - p.close = function() { - while (this._currentLoads.length) { - this._currentLoads.pop().cancel(); - } - this._scriptOrder.length = 0; - this._loadedScripts.length = 0; - this.loadStartWasDispatched = false; - }; - - -//Protected Methods - /** - * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to - * load the content. The load queue is populated with the loader instance that handles preloading, and not the load - * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}} - * method. - * @method _addItem - * @param {String|Object} value The item to add to the queue. - * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is - * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was - * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after. - * @param {String} [basePath] DeprecatedAn optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged - * version. - * @private - */ - p._addItem = function(value, path, basePath) { - var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src. - if (item == null) { return; } // Sometimes plugins or types should be skipped. - var loader = this._createLoader(item); - if (loader != null) { - item._loader = loader; - this._loadQueue.push(loader); - this._loadQueueBackup.push(loader); - - this._numItems++; - this._updateProgress(); - - // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time. - if ((this.maintainScriptOrder - && item.type == createjs.LoadQueue.JAVASCRIPT - //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way - ) - || item.maintainOrder === true) { - this._scriptOrder.push(item); - this._loadedScripts.push(null); - } - } - }; - - /** - * Create a refined load item, which contains all the required properties (src, type, extension, tag). The type of - * item is determined by browser support, requirements based on the file type, and developer settings. For example, - * XHR is only used for file types that support it in new browsers. - * - * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may - * alter the load item. - * @method _createLoadItem - * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded. - * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will - * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}} - * when it is added. - * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to - * the path argument. - * @return {Object} The loader instance that will be used. - * @private - */ - p._createLoadItem = function(value, path, basePath) { - var item = null; - - // Create/modify a load item - switch(typeof(value)) { - case "string": - item = { - src: value - }; break; - case "object": - if (window.HTMLAudioElement && value instanceof window.HTMLAudioElement) { - item = { - tag: value, - src: item.tag.src, - type: createjs.LoadQueue.SOUND - }; - } else { - item = value; - } - break; - default: - return null; - } - - // Determine Extension, etc. - var match = this._parseURI(item.src); - if (match.extension) { item.ext = match.extension; } - if (item.type == null) { - item.type = this._getTypeByExtension(item.ext); - } - - // Inject path & basePath - var bp = ""; // Store the generated basePath - var useBasePath = basePath || this._basePath; - var autoId = item.src; - if (!match.absolute && !match.relative) { - if (path) { - bp = path; - var pathMatch = this._parseURI(path); - autoId = path + autoId; - // Also append basePath - if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) { - bp = useBasePath + bp; - } - } else if (useBasePath != null) { - bp = useBasePath; - } - } - item.src = bp + item.src; - item.path = bp; - - if (item.type == createjs.LoadQueue.JSON || item.type == createjs.LoadQueue.MANIFEST) { - item._loadAsJSONP = (item.callback != null); - } - - if (item.type == createjs.LoadQueue.JSONP && item.callback == null) { - throw new Error('callback is required for loading JSONP requests.'); - } - - // Create a tag for the item. This ensures there is something to either load with or populate when finished. - if (item.tag === undefined || item.tag === null) { - item.tag = this._createTag(item); - } - - // If there's no id, set one now. - if (item.id === undefined || item.id === null || item.id === "") { - item.id = autoId; - } - - // Give plugins a chance to modify the loadItem: - var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext]; - if (customHandler) { - // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately) - var result = customHandler.callback.call(customHandler.scope, item.src, item.type, item.id, item.data, - bp, this); - // NOTE: BasePath argument is deprecated. We pass it to plugins.allow SoundJS to modify the file. to sanymore. The full path is sent to the plugin - - // The plugin will handle the load, or has canceled it. Ignore it. - if (result === false) { - return null; - - // Load as normal: - } else if (result === true) { - // Do Nothing - - // Result is a loader class: - } else { - if (result.src != null) { item.src = result.src; } - if (result.id != null) { item.id = result.id; } // TODO: Evaluate this. An overridden ID could be problematic - if (result.tag != null) { // Assumes that the returned tag either has a load method or a src setter. - item.tag = result.tag; - } - if (result.completeHandler != null) { item.completeHandler = result.completeHandler; } - - // Allow type overriding: - if (result.type) { item.type = result.type; } - - // Update the extension in case the type changed: - match = this._parseURI(item.src); - if (match.extension != null) { - item.ext = match.extension; - } - } - } - - // Store the item for lookup. This also helps clean-up later. - this._loadItemsById[item.id] = item; - this._loadItemsBySrc[item.src] = item; - - return item; - }; - - /** - * Create a loader for a load item. - * @method _createLoader - * @param {Object} item A formatted load item that can be used to generate a loader. - * @return {AbstractLoader} A loader that can be used to load content. - * @private - */ - p._createLoader = function(item) { - // Initially, try and use the provided/supported XHR mode: - var useXHR = this.useXHR; - - // Determine the XHR usage overrides: - switch (item.type) { - case createjs.LoadQueue.JSON: - case createjs.LoadQueue.MANIFEST: - useXHR = !item._loadAsJSONP; - break; - case createjs.LoadQueue.XML: - case createjs.LoadQueue.TEXT: - useXHR = true; // Always use XHR2 with text/XML - break; - case createjs.LoadQueue.SOUND: - case createjs.LoadQueue.JSONP: - useXHR = false; // Never load audio using XHR. WebAudio will provide its own loader. - break; - case null: - return null; - // Note: IMAGE, CSS, SCRIPT, SVG can all use TAGS or XHR. - } - - if (useXHR) { - return new createjs.XHRLoader(item, this._crossOrigin); - } else { - return new createjs.TagLoader(item); - } - }; - - - /** - * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event - * is processed. The queue will "fill up" any empty slots, up to the max connection specified using - * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded - * using tags, which have to be loaded one at a time to maintain load order. - * @method _loadNext - * @private - */ - p._loadNext = function() { - if (this._paused) { return; } - - // Only dispatch loadstart event when the first file is loaded. - if (!this._loadStartWasDispatched) { - this._sendLoadStart(); - this._loadStartWasDispatched = true; - } - - // The queue has completed. - if (this._numItems == this._numItemsLoaded) { - this.loaded = true; - this._sendComplete(); - - // Load the next queue, if it has been defined. - if (this.next && this.next.load) { - this.next.load(); - } - } else { - this.loaded = false; - } - - // Must iterate forwards to load in the right order. - for (var i=0; i= this._maxConnections) { break; } - var loader = this._loadQueue[i]; - - // Determine if we should be only loading one tag-script at a time: - // Note: maintainOrder items don't do anything here because we can hold onto their loaded value - if (!this._canStartLoad(loader)) { continue; } - this._loadQueue.splice(i, 1); - i--; - this._loadItem(loader); - } - }; - - /** - * Begin loading an item. Events are not added to the loaders until the load starts. - * @method _loadItem - * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader. - * @private - */ - p._loadItem = function(loader) { - loader.on("progress", this._handleProgress, this); - loader.on("complete", this._handleFileComplete, this); - loader.on("error", this._handleFileError, this); - this._currentLoads.push(loader); - this._sendFileStart(loader.getItem()); - loader.load(); - }; - - /** - * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} - * is set to `true`. - * @method _handleFileError - * @param {Object} event The error event, containing relevant error information. - * @private - */ - p._handleFileError = function(event) { - var loader = event.target; - this._numItemsLoaded++; - - this._finishOrderedItem(loader, true); - this._updateProgress(); - - var newEvent = new createjs.Event("error"); - newEvent.text = "FILE_LOAD_ERROR"; - newEvent.item = loader.getItem(); - // TODO: Propagate actual error message. - - this._sendError(newEvent); - - if (!this.stopOnError) { - this._removeLoadItem(loader); - this._loadNext(); - } - }; - - /** - * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and - * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML, - * CSS, JavaScript, etc) is available as the "rawResult" event, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. - * @method _handleFileComplete - * @param {Object} event The event object from the loader. - * @private - */ - p._handleFileComplete = function(event) { - var loader = event.target; - var item = loader.getItem(); - - this._loadedResults[item.id] = loader.getResult(); - if (loader instanceof createjs.XHRLoader) { - this._loadedRawResults[item.id] = loader.getResult(true); - } - - // Clean up the load item - this._removeLoadItem(loader); - - if (!this._finishOrderedItem(loader)) { - // The item was NOT managed, so process it now - this._processFinishedLoad(item, loader); - } - }; - - /** - * Flag an item as finished. If the item's order is being managed, then set it up to finish - * @method _finishOrderedItem - * @param {AbstractLoader} loader - * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate - * behaviour if it is. - * @private - */ - p._finishOrderedItem = function(loader, loadFailed) { - var item = loader.getItem(); - - if ((this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT) - || item.maintainOrder) { - - //TODO: Evaluate removal of the _currentlyLoadingScript - if (loader instanceof createjs.TagLoader && item.type == createjs.LoadQueue.JAVASCRIPT) { - this._currentlyLoadingScript = false; - } - - var index = createjs.indexOf(this._scriptOrder, item); - if (index == -1) { return false; } // This loader no longer exists - this._loadedScripts[index] = (loadFailed === true) ? true : item; - - this._checkScriptLoadOrder(); - return true; - } - - return false; - }; - - /** - * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the - * order they were added, but with a "null" value. When they are completed, the value is set to the load item, - * and then when they are processed and dispatched, the value is set to true. This method simply - * iterates the array, and ensures that any loaded items that are not preceded by a null value are - * dispatched. - * @method _checkScriptLoadOrder - * @private - */ - p._checkScriptLoadOrder = function () { - var l = this._loadedScripts.length; - - for (var i=0;ibefore - * the script can even be started, since it exist in the DOM while loading. - * @method _canStartLoad - * @param {XHRLoader|TagLoader} loader The loader for the item - * @return {Boolean} Whether the item can start a load or not. - * @private - */ - p._canStartLoad = function(loader) { - if (!this.maintainScriptOrder || loader instanceof createjs.XHRLoader) { return true; } - var item = loader.getItem(); - if (item.type != createjs.LoadQueue.JAVASCRIPT) { return true; } - if (this._currentlyLoadingScript) { return false; } - - var index = this._scriptOrder.indexOf(item); - var i = 0; - while (i < index) { - var checkItem = this._loadedScripts[i]; - if (checkItem == null) { return false; } - i++; - } - this._currentlyLoadingScript = true; - return true; - }; - - /** - * A load item is completed or was canceled, and needs to be removed from the LoadQueue. - * @method _removeLoadItem - * @param {AbstractLoader} loader A loader instance to remove. - * @private - */ - p._removeLoadItem = function(loader) { - var item = loader.getItem(); - delete item._loader; - delete item._loadAsJSONP; - - var l = this._currentLoads.length; - for (var i=0;i - *
  • 5/10 of the items in the queue (50%)
  • - *
  • plus 20% of item 6's slot (2%)
  • - *
  • equals 52%
  • - * @method _updateProgress - * @private - */ - p._updateProgress = function () { - var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress - var remaining = this._numItems-this._numItemsLoaded; - if (remaining > 0) { - var chunk = 0; - for (var i=0, l=this._currentLoads.length; iLoadQueue.IMAGE
    or null if it can not be - * determined by the extension. - * @private - */ - p._getTypeByExtension = function(extension) { - if (extension == null) { - return createjs.LoadQueue.TEXT; - } - switch (extension.toLowerCase()) { - case "jpeg": - case "jpg": - case "gif": - case "png": - case "webp": - case "bmp": - return createjs.LoadQueue.IMAGE; - case "ogg": - case "mp3": - case "wav": - return createjs.LoadQueue.SOUND; - case "json": - return createjs.LoadQueue.JSON; - case "xml": - return createjs.LoadQueue.XML; - case "css": - return createjs.LoadQueue.CSS; - case "js": - return createjs.LoadQueue.JAVASCRIPT; - case 'svg': - return createjs.LoadQueue.SVG; - default: - return createjs.LoadQueue.TEXT; - } - }; - - /** - * Dispatch a fileprogress event (and onFileProgress callback). Please see the LoadQueue.fileprogress - * event for details on the event payload. - * @method _sendFileProgress - * @param {Object} item The item that is being loaded. - * @param {Number} progress The amount the item has been loaded (between 0 and 1). - * @protected - */ - p._sendFileProgress = function(item, progress) { - if (this._isCanceled()) { - this._cleanUp(); - return; - } - if (!this.hasEventListener("fileprogress")) { return; } - - var event = new createjs.Event("fileprogress"); - event.progress = progress; - event.loaded = progress; - event.total = 1; - event.item = item; - - this.dispatchEvent(event); - }; - - /** - * Dispatch a fileload event. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for - * details on the event payload. - * @method _sendFileComplete - * @param {Object} item The item that is being loaded. - * @param {TagLoader | XHRLoader} loader - * @protected - */ - p._sendFileComplete = function(item, loader) { - if (this._isCanceled()) { return; } - - var event = new createjs.Event("fileload"); - event.loader = loader; - event.item = item; - event.result = this._loadedResults[item.id]; - event.rawResult = this._loadedRawResults[item.id]; - - // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this. - if (item.completeHandler) { - item.completeHandler(event); - } - - this.hasEventListener("fileload") && this.dispatchEvent(event); - }; - - /** - * Dispatch a filestart event immediately before a file starts to load. Please see the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} - * event for details on the event payload. - * @method _sendFileStart - * @param {Object} item The item that is being loaded. - * @protected - */ - p._sendFileStart = function(item) { - var event = new createjs.Event("filestart"); - event.item = item; - this.hasEventListener("filestart") && this.dispatchEvent(event); - }; - - /** - * REMOVED. Use createjs.proxy instead - * @method proxy - * @param {Function} method The function to call - * @param {Object} scope The scope to call the method name on - * @static - * @private - * @deprecated In favour of the createjs.proxy method (see LoadQueue source). - */ - - p.toString = function() { - return "[PreloadJS LoadQueue]"; - }; - - createjs.LoadQueue = LoadQueue; - - -// Helper methods - - // An additional module to determine the current browser, version, operating system, and other environmental variables. - var BrowserDetect = function() {} - - BrowserDetect.init = function() { - var agent = navigator.userAgent; - BrowserDetect.isFirefox = (agent.indexOf("Firefox") > -1); - BrowserDetect.isOpera = (window.opera != null); - BrowserDetect.isChrome = (agent.indexOf("Chrome") > -1); - BrowserDetect.isIOS = agent.indexOf("iPod") > -1 || agent.indexOf("iPhone") > -1 || agent.indexOf("iPad") > -1; - }; - - BrowserDetect.init(); - - createjs.LoadQueue.BrowserDetect = BrowserDetect; - -}()); -/* -* TagLoader -* Visit http://createjs.com/ for documentation, updates and examples. -* -* -* Copyright (c) 2012 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * @module PreloadJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - /** - * A preloader that loads items using a tag-based approach. HTML audio and images can use this loader to load - * content cross-domain without security errors, whereas anything loaded with XHR has potential issues with cross- - * domain requests. - * - * Note for audio tags, TagLoader relies on the canPlayThrough event, which fires when the buffer - * is full enough to play the audio all the way through at the current download speed. This completely preloads most - * sound effects, however longer tracks like background audio will only load a portion before the event is fired. - * Most browsers (all excluding Chrome) will continue to preload once this is fired, so this is considered good - * enough for most cases. - * @class TagLoader - * @constructor - * @extends AbstractLoader - * @param {Object} item The item to load. Please see {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} for - * information on load items. - */ - var TagLoader = function (item) { - this.init(item); - }; - - var p = TagLoader.prototype = new createjs.AbstractLoader(); - -// Protected - - /** - * The timeout that is fired if nothing is loaded after a certain delay. See the LoadQueue.LOAD_TIMEOUT - * for the timeout duration. - * @property _loadTimeout - * @type {Number} - * @private - */ - p._loadTimeout = null; - - /** - * A reference to a bound function, which we need in order to properly remove the event handler when the load - * completes. - * @property _tagCompleteProxy - * @type {Function} - * @private - */ - p._tagCompleteProxy = null; - - /** - * Determines if the load item is an audio tag, since we take some specific approaches to properly load audio. - * @property _isAudio - * @type {Boolean} - * @default false - * @protected - */ - p._isAudio = false; - - /** - * The HTML tag or JavaScript object this loader uses to preload content. Note that a tag may be a custom object - * that matches the API of an HTML tag (load method, onload callback). For example, flash audio from SoundJS passes - * in a custom object to handle preloading for Flash audio and WebAudio. - * @property _tag - * @type {HTMLAudioElement | Object} - * @private - */ - p._tag = null; - - /** - * When loading a JSONP request this will be the parsed JSON result. - * - * @type {Object} - * @private - */ - p._jsonResult = null; - - // Overrides abstract method in AbstractLoader - p.init = function (item) { - this._item = item; - this._tag = item.tag; - this._isAudio = (window.HTMLAudioElement && item.tag instanceof window.HTMLAudioElement); - this._tagCompleteProxy = createjs.proxy(this._handleLoad, this); - }; - - /** - * Get the loaded content. This is usually an HTML tag or other tag-style object that has been fully loaded. If the - * loader is not complete, this will be null. - * @method getResult - * @return {HTMLImageElement | HTMLAudioElement | Object} The loaded and parsed content. - */ - p.getResult = function() { - if (this._item.type == createjs.LoadQueue.JSONP || this._item.type == createjs.LoadQueue.MANIFEST) { - return this._jsonResult; - } else { - return this._tag; - } - }; - - // Overrides abstract method in AbstractLoader - p.cancel = function() { - this.canceled = true; - this._clean(); - }; - - // Overrides abstract method in AbstractLoader - p.load = function() { - var item = this._item; - var tag = this._tag; - - clearTimeout(this._loadTimeout); // Clear out any existing timeout - var duration = createjs.LoadQueue.LOAD_TIMEOUT; - if (duration == 0) { duration = createjs.LoadQueue.loadTimeout; } - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), duration); - - if (this._isAudio) { - tag.src = null; // Unset the source so we can set the preload type to "auto" without kicking off a load. This is only necessary for audio tags passed in by the developer. - tag.preload = "auto"; - } - - // Handlers for all tags - tag.onerror = createjs.proxy(this._handleError, this); - // Note: We only get progress events in Chrome, but do not fully load tags in Chrome due to its behaviour, so we ignore progress. - - if (this._isAudio) { - tag.onstalled = createjs.proxy(this._handleStalled, this); - // This will tell us when audio is buffered enough to play through, but not when its loaded. - // The tag doesn't keep loading in Chrome once enough has buffered, and we have decided that behaviour is sufficient. - tag.addEventListener("canplaythrough", this._tagCompleteProxy, false); // canplaythrough callback doesn't work in Chrome, so we use an event. - } else { - tag.onload = createjs.proxy(this._handleLoad, this); - tag.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this); - } - - var src = this.buildPath(item.src, item.values); - - // Set the src after the events are all added. - switch(item.type) { - case createjs.LoadQueue.CSS: - tag.href = src; - break; - case createjs.LoadQueue.SVG: - tag.data = src; - break; - default: - tag.src = src; - } - - // If we're loading JSONP, we need to add our callback now. - if (item.type == createjs.LoadQueue.JSONP - || item.type == createjs.LoadQueue.JSON - || item.type == createjs.LoadQueue.MANIFEST) { - if (item.callback == null) { - throw new Error('callback is required for loading JSONP requests.'); - } - - if (window[item.callback] != null) { - throw new Error('JSONP callback "' + item.callback + '" already exists on window. You need to specify a different callback. Or re-name the current one.'); - } - - window[item.callback] = createjs.proxy(this._handleJSONPLoad, this); - } - - // If its SVG, it needs to be on the DOM to load (we remove it before sending complete). - // It is important that this happens AFTER setting the src/data. - if (item.type == createjs.LoadQueue.SVG || - item.type == createjs.LoadQueue.JSONP || - item.type == createjs.LoadQueue.JSON || - item.type == createjs.LoadQueue.MANIFEST || - item.type == createjs.LoadQueue.JAVASCRIPT || - item.type == createjs.LoadQueue.CSS) { - this._startTagVisibility = tag.style.visibility; - tag.style.visibility = "hidden"; - var node = document.body || document.getElementsByTagName("body")[0]; - if (node == null) { - if (item.type == createjs.LoadQueue.SVG) { - this._handleSVGError(); - return; - } else { - node = document.head || document.getElementsByTagName("head"); - } - } - node.appendChild(tag); - } - - // Note: Previous versions didn't seem to work when we called load() for OGG tags in Firefox. Seems fixed in 15.0.1 - if (tag.load != null) { - tag.load(); - } - }; - - p._handleSVGError = function() { - this._clean(); - var event = new createjs.Event("error"); - event.text = "SVG_NO_BODY"; - this._sendError(event); - }; - - p._handleJSONPLoad = function(data) { - this._jsonResult = data; - }; - - /** - * Handle an audio timeout. Newer browsers get a callback from the tags, but older ones may require a setTimeout - * to handle it. The setTimeout is always running until a response is handled by the browser. - * @method _handleTimeout - * @private - */ - p._handleTimeout = function() { - this._clean(); - var event = new createjs.Event("error"); - event.text = "PRELOAD_TIMEOUT"; - this._sendError(event); - }; - - /** - * Handle a stalled audio event. The main place we seem to get these is with HTMLAudio in Chrome when we try and - * playback audio that is already in a load, but not complete. - * @method _handleStalled - * @private - */ - p._handleStalled = function() { - //Ignore, let the timeout take care of it. Sometimes its not really stopped. - }; - - /** - * Handle an error event generated by the tag. - * @method _handleError - * @private - */ - p._handleError = function(event) { - this._clean(); - - var newEvent = new createjs.Event("error"); - //TODO: Propagate actual event error? - this._sendError(newEvent); - }; - - /** - * Handle the readyStateChange event from a tag. We sometimes need this in place of the onload event (mainly SCRIPT - * and LINK tags), but other cases may exist. - * @method _handleReadyStateChange - * @private - */ - p._handleReadyStateChange = function() { - clearTimeout(this._loadTimeout); - // This is strictly for tags in browsers that do not support onload. - var tag = this.getItem().tag; - - // Complete is for old IE support. - if (tag.readyState == "loaded" || tag.readyState == "complete") { - this._handleLoad(); - } - }; - - /** - * Handle a load (complete) event. This is called by tag callbacks, but also by readyStateChange and canPlayThrough - * events. Once loaded, the item is dispatched to the {{#crossLink "LoadQueue"}}{{/crossLink}}. - * @method _handleLoad - * @param {Object} [event] A load event from a tag. This is sometimes called from other handlers without an event. - * @private - */ - p._handleLoad = function(event) { - if (this._isCanceled()) { return; } - - var item = this.getItem(); - var tag = item.tag; - - if (this.loaded || this._isAudio && tag.readyState !== 4) { return; } //LM: Not sure if we still need the audio check. - this.loaded = true; - - // Remove from the DOM - switch (item.type) { - case createjs.LoadQueue.SVG: - case createjs.LoadQueue.JSON: - case createjs.LoadQueue.JSONP: // Note: Removing script tags is a fool's errand. - case createjs.LoadQueue.MANIFEST: - case createjs.LoadQueue.CSS: - // case createjs.LoadQueue.CSS: - //LM: We may need to remove CSS tags loaded using a LINK - tag.style.visibility = this._startTagVisibility; - tag.parentNode && tag.parentNode.contains(tag) && tag.parentNode.removeChild(tag); - break; - default: - } - - this._clean(); - this._sendComplete(); - }; - - /** - * Clean up the loader. - * This stops any timers and removes references to prevent errant callbacks and clean up memory. - * @method _clean - * @private - */ - p._clean = function() { - clearTimeout(this._loadTimeout); - - // Delete handlers. - var item = this.getItem(); - var tag = item.tag; - if (tag != null) { - tag.onload = null; - tag.removeEventListener && tag.removeEventListener("canplaythrough", this._tagCompleteProxy, false); - tag.onstalled = null; - tag.onprogress = null; - tag.onerror = null; - - //TODO: Test this - if (tag.parentNode != null - && item.type == createjs.LoadQueue.SVG - && item.type == createjs.LoadQueue.JSON - && item.type == createjs.LoadQueue.MANIFEST - && item.type == createjs.LoadQueue.CSS - && item.type == createjs.LoadQueue.JSONP) { - // Note: Removing script tags is a fool's errand. - tag.parentNode.removeChild(tag); - } - } - - var item = this.getItem(); - if (item.type == createjs.LoadQueue.JSONP - || item.type == createjs.LoadQueue.MANIFEST) { - window[item.callback] = null; - } - }; - - p.toString = function() { - return "[PreloadJS TagLoader]"; - }; - - createjs.TagLoader = TagLoader; - -}()); -/* - * XHRLoader - * Visit http://createjs.com/ for documentation, updates and examples. - * - * - * Copyright (c) 2012 gskinner.com, inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * @module PreloadJS - */ - -// namespace: -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - /** - * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used - * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary. - * XHR requests load the content as text or binary data, provide progress and consistent completion events, and - * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for - * cross-domain loading. - * @class XHRLoader - * @constructor - * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * for an overview of supported file properties. - * @param {String} [crossOrigin] An optional flag to support images loaded from a CORS-enabled server. Please see - * {{#crossLink "LoadQueue/_crossOrigin:property"}}{{/crossLink}} for more info. - * @extends AbstractLoader - */ - var XHRLoader = function (item, crossOrigin) { - this.init(item, crossOrigin); - }; - - var s = XHRLoader; - - /** - * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE. - * @property ACTIVEX_VERSIONS - * @type {Array} - * @since 0.4.2 - * @private - */ - s.ACTIVEX_VERSIONS = [ - "Msxml2.XMLHTTP.6.0", - "Msxml2.XMLHTTP.5.0", - "Msxml2.XMLHTTP.4.0", - "MSXML2.XMLHTTP.3.0", - "MSXML2.XMLHTTP", - "Microsoft.XMLHTTP" - ]; - - var p = XHRLoader.prototype = new createjs.AbstractLoader(); - - //Protected - /** - * A reference to the XHR request used to load the content. - * @property _request - * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP} - * @private - */ - p._request = null; - - /** - * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1, - * typically IE9). - * @property _loadTimeout - * @type {Number} - * @private - */ - p._loadTimeout = null; - - /** - * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect - * the version, so we use capabilities to make a best guess. - * @property _xhrLevel - * @type {Number} - * @default 1 - * @private - */ - p._xhrLevel = 1; - - /** - * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be - * null until the file is loaded. - * @property _response - * @type {mixed} - * @private - */ - p._response = null; - - /** - * The response of the loaded file before it is modified. In most cases, content is converted from raw text to - * an HTML tag or a formatted object which is set to the result property, but the developer may still - * want to access the raw content as it was loaded. - * @property _rawResponse - * @type {String|Object} - * @private - */ - p._rawResponse = null; - - /** - * See {{#crossLink "LoadQueue/_crossOrigin:property"}}{{/crossLink}} - * @property _crossOrigin - * @type {String} - * @defaultValue "" - * @private - */ - p._crossOrigin = ""; - - // Overrides abstract method in AbstractLoader - p.init = function (item, crossOrigin) { - this._item = item; - this._crossOrigin = crossOrigin; - if (!this._createXHR(item)) { - //TODO: Throw error? - } - }; - - /** - * Look up the loaded result. - * @method getResult - * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content - * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be - * returned instead. - * @return {Object} A result object containing the content that was loaded, such as: - *
      - *
    • An image tag (<image />) for images
    • - *
    • A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the - * HTML head.
    • - *
    • A style tag for CSS (<style />)
    • - *
    • Raw text for TEXT
    • - *
    • A formatted JavaScript object defined by JSON
    • - *
    • An XML document
    • - *
    • An binary arraybuffer loaded by XHR
    • - *
    - * Note that if a raw result is requested, but not found, the result will be returned instead. - */ - p.getResult = function (rawResult) { - if (rawResult && this._rawResponse) { - return this._rawResponse; - } - return this._response; - }; - - // Overrides abstract method in AbstractLoader - 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 - this._request.onloadstart = createjs.proxy(this._handleLoadStart, this); - this._request.onprogress = createjs.proxy(this._handleProgress, this); - this._request.onabort = createjs.proxy(this._handleAbort, this); - this._request.onerror = createjs.proxy(this._handleError, this); - this._request.ontimeout = createjs.proxy(this._handleTimeout, this); - // Set up a timeout if we don't have XHR2 - if (this._xhrLevel == 1) { - var duration = createjs.LoadQueue.LOAD_TIMEOUT; - if (duration == 0) { - duration = createjs.LoadQueue.loadTimeout; - } else { - try { console.warn("LoadQueue.LOAD_TIMEOUT has been deprecated in favor of LoadQueue.loadTimeout");} catch(e) {} - } - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), duration); - } - - // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. - this._request.onload = createjs.proxy(this._handleLoad, this); - - this._request.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this); - - // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome - try { - if (!this._item.values || this._item.method == createjs.LoadQueue.GET) { - this._request.send(); - } else if (this._item.method == createjs.LoadQueue.POST) { - this._request.send(this._formatQueryString(this._item.values)); - } - } catch (error) { - var event = new createjs.Event("error"); - event.error = error; - this._sendError(event); - } - }; - - /** - * 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; - } - }; - - /** - * 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.Event("progress"); - newEvent.loaded = event.loaded; - newEvent.total = event.total; - this._sendProgress(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._sendLoadStart(); - }; - - /** - * The XHR request has reported an abort event. - * @method handleAbort - * @param {Object} event The XHR abort event. - * @private - */ - p._handleAbort = function (event) { - this._clean(); - var newEvent = new createjs.Event("error"); - newEvent.text = "XHR_ABORTED"; - this._sendError(newEvent); - }; - - /** - * The XHR request has reported an error event. - * @method _handleError - * @param {Object} event The XHR error event. - * @private - */ - p._handleError = function (event) { - this._clean(); - var newEvent = new createjs.Event("error"); - //TODO: Propagate event error - this._sendError(newEvent); - }; - - /** - * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload - * event, so we must monitor the readyStateChange to determine if the file is loaded. - * @method _handleReadyStateChange - * @param {Object} event The XHR readyStateChange event. - * @private - */ - p._handleReadyStateChange = function (event) { - if (this._request.readyState == 4) { - this._handleLoad(); - } - }; - - /** - * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has - * request.readyState == 4. Only the first call to this method will be processed. - * @method _handleLoad - * @param {Object} event The XHR load event. - * @private - */ - p._handleLoad = function (event) { - if (this.loaded) { - return; - } - this.loaded = true; - - if (!this._checkError()) { - this._handleError(); - return; - } - - this._response = this._getResponse(); - this._clean(); - var isComplete = this._generateTag(); - if (isComplete) { - this._sendComplete(); - } - }; - - /** - * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout - * callback. - * @method _handleTimeout - * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout. - * @private - */ - p._handleTimeout = function (event) { - this._clean(); - var newEvent = new createjs.Event("error"); - newEvent.text = "PRELOAD_TIMEOUT"; - //TODO: Propagate actual event error - this._sendError(event); - }; - - -// Protected - /** - * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note - * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code. - * @method _checkError - * @return {Boolean} If the request status returns an error code. - * @private - */ - p._checkError = function () { - //LM: Probably need additional handlers here, maybe 501 - var status = parseInt(this._request.status); - - switch (status) { - case 404: // Not Found - case 0: // Not Loaded - return false; - } - return true; - }; - - /** - * Validate the response. Different browsers have different approaches, some of which throw errors when accessed - * in other browsers. If there is no response, the _response property will remain null. - * @method _getResponse - * @private - */ - p._getResponse = function () { - if (this._response != null) { - return this._response; - } - - if (this._request.response != null) { - return this._request.response; - } - - // Android 2.2 uses .responseText - try { - if (this._request.responseText != null) { - return this._request.responseText; - } - } catch (e) { - } - - // When loading XML, IE9 does not return .response, instead it returns responseXML.xml - //TODO: TEST - try { - if (this._request.responseXML != null) { - return this._request.responseXML; - } - } catch (e) { - } - return null; - }; - - /** - * Create an XHR request. Depending on a number of factors, we get totally different results. - *
    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 = this._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; iExample + * + * 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)); + }; + } + +}()); + +//############################################################################## +// indexOf.js +//############################################################################## + +this.createjs = this.createjs||{}; + +/** + * @class Utility Methods + */ + +/** + * Finds the first occurrence of a specified value searchElement in the passed in array, and returns the index of + * that value. Returns -1 if value is not found. + * + * var i = createjs.indexOf(myArray, myElementToFind); + * + * @method indexOf + * @param {Array} array Array to search for searchElement + * @param searchElement Element to find in array. + * @return {Number} The first index of searchElement in array. + */ +createjs.indexOf = function (array, searchElement){ + "use strict"; + + for (var i = 0,l=array.length; i < l; i++) { + if (searchElement === array[i]) { + return i; + } + } + return -1; +}; + +//############################################################################## +// Event.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + +// constructor: + /** + * Contains properties and methods shared by all events for use with + * {{#crossLink "EventDispatcher"}}{{/crossLink}}. + * + * Note that Event objects are often reused, so you should never + * rely on an event object's state outside of the call stack it was received in. + * @class Event + * @param {String} type The event type. + * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. + * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. + * @constructor + **/ + function Event(type, bubbles, cancelable) { + + + // public properties: + /** + * The type of event. + * @property type + * @type String + **/ + this.type = type; + + /** + * The object that generated an event. + * @property target + * @type Object + * @default null + * @readonly + */ + this.target = null; + + /** + * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will + * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event + * is generated from childObj, then a listener on parentObj would receive the event with + * target=childObj (the original target) and currentTarget=parentObj (where the listener was added). + * @property currentTarget + * @type Object + * @default null + * @readonly + */ + this.currentTarget = null; + + /** + * For bubbling events, this indicates the current event phase:
      + *
    1. capture phase: starting from the top parent to the target
    2. + *
    3. at target phase: currently being dispatched from the target
    4. + *
    5. bubbling phase: from the target to the top parent
    6. + *
    + * @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 +//############################################################################## + +this.createjs = this.createjs||{}; + +(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"); + +}()); + +//############################################################################## +// EventDispatcher.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(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= 10.53. + isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 && + // Safari < 2.0.2 stores the internal millisecond time value correctly, + // but clips the values returned by the date methods to the range of + // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]). + isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708; + } catch (exception) {} + + // Internal: Determines whether the native `JSON.stringify` and `parse` + // implementations are spec-compliant. Based on work by Ken Snyder. + function has(name) { + if (has[name] !== undef) { + // Return cached feature test result. + return has[name]; + } + var isSupported; + if (name == "bug-string-char-index") { + // IE <= 7 doesn't support accessing string characters using square + // bracket notation. IE 8 only supports this for primitives. + isSupported = "a"[0] != "a"; + } else if (name == "json") { + // Indicates whether both `JSON.stringify` and `JSON.parse` are + // supported. + isSupported = has("json-stringify") && has("json-parse"); + } else { + var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'; + // Test `JSON.stringify`. + if (name == "json-stringify") { + var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended; + if (stringifySupported) { + // A test function object with a custom `toJSON` method. + (value = function () { + return 1; + }).toJSON = value; + try { + stringifySupported = + // Firefox 3.1b1 and b2 serialize string, number, and boolean + // primitives as object literals. + stringify(0) === "0" && + // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object + // literals. + stringify(new Number()) === "0" && + stringify(new String()) == '""' && + // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or + // does not define a canonical JSON representation (this applies to + // objects with `toJSON` properties as well, *unless* they are nested + // within an object or array). + stringify(getClass) === undef && + // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and + // FF 3.1b3 pass this test. + stringify(undef) === undef && + // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s, + // respectively, if the value is omitted entirely. + stringify() === undef && + // FF 3.1b1, 2 throw an error if the given value is not a number, + // string, array, object, Boolean, or `null` literal. This applies to + // objects with custom `toJSON` methods as well, unless they are nested + // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON` + // methods entirely. + stringify(value) === "1" && + stringify([value]) == "[1]" && + // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of + // `"[null]"`. + stringify([undef]) == "[null]" && + // YUI 3.0.0b1 fails to serialize `null` literals. + stringify(null) == "null" && + // FF 3.1b1, 2 halts serialization if an array contains a function: + // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3 + // elides non-JSON values from objects and arrays, unless they + // define custom `toJSON` methods. + stringify([undef, getClass, null]) == "[null,null,null]" && + // Simple serialization test. FF 3.1b1 uses Unicode escape sequences + // where character escape codes are expected (e.g., `\b` => `\u0008`). + stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized && + // FF 3.1b1 and b2 ignore the `filter` and `width` arguments. + stringify(null, value) === "1" && + stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" && + // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly + // serialize extended years. + stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' && + // The milliseconds are optional in ES 5, but required in 5.1. + stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' && + // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative + // four-digit years instead of six-digit years. Credits: @Yaffle. + stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' && + // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond + // values less than 1000. Credits: @Yaffle. + stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"'; + } catch (exception) { + stringifySupported = false; + } + } + isSupported = stringifySupported; + } + // Test `JSON.parse`. + if (name == "json-parse") { + var parse = exports.parse; + if (typeof parse == "function") { + try { + // FF 3.1b1, b2 will throw an exception if a bare literal is provided. + // Conforming implementations should also coerce the initial argument to + // a string prior to parsing. + if (parse("0") === 0 && !parse(false)) { + // Simple parsing test. + value = parse(serialized); + var parseSupported = value["a"].length == 5 && value["a"][0] === 1; + if (parseSupported) { + try { + // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings. + parseSupported = !parse('"\t"'); + } catch (exception) {} + if (parseSupported) { + try { + // FF 4.0 and 4.0.1 allow leading `+` signs and leading + // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow + // certain octal literals. + parseSupported = parse("01") !== 1; + } catch (exception) {} + } + if (parseSupported) { + try { + // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal + // points. These environments, along with FF 3.1b1 and 2, + // also allow trailing commas in JSON objects and arrays. + parseSupported = parse("1.") !== 1; + } catch (exception) {} + } + } + } + } catch (exception) { + parseSupported = false; + } + } + isSupported = parseSupported; + } + } + return has[name] = !!isSupported; + } + + if (!has("json")) { + // Common `[[Class]]` name aliases. + var functionClass = "[object Function]", + dateClass = "[object Date]", + numberClass = "[object Number]", + stringClass = "[object String]", + arrayClass = "[object Array]", + booleanClass = "[object Boolean]"; + + // Detect incomplete support for accessing string characters by index. + var charIndexBuggy = has("bug-string-char-index"); + + // Define additional utility methods if the `Date` methods are buggy. + if (!isExtended) { + var floor = Math.floor; + // A mapping between the months of the year and the number of days between + // January 1st and the first of the respective month. + var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; + // Internal: Calculates the number of days between the Unix epoch and the + // first day of the given month. + var getDay = function (year, month) { + return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400); + }; + } + + // Internal: Determines if a property is a direct property of the given + // object. Delegates to the native `Object#hasOwnProperty` method. + if (!(isProperty = objectProto.hasOwnProperty)) { + isProperty = function (property) { + var members = {}, constructor; + if ((members.__proto__ = null, members.__proto__ = { + // The *proto* property cannot be set multiple times in recent + // versions of Firefox and SeaMonkey. + "toString": 1 + }, members).toString != getClass) { + // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but + // supports the mutable *proto* property. + isProperty = function (property) { + // Capture and break the object's prototype chain (see section 8.6.2 + // of the ES 5.1 spec). The parenthesized expression prevents an + // unsafe transformation by the Closure Compiler. + var original = this.__proto__, result = property in (this.__proto__ = null, this); + // Restore the original prototype chain. + this.__proto__ = original; + return result; + }; + } else { + // Capture a reference to the top-level `Object` constructor. + constructor = members.constructor; + // Use the `constructor` property to simulate `Object#hasOwnProperty` in + // other environments. + isProperty = function (property) { + var parent = (this.constructor || constructor).prototype; + return property in this && !(property in parent && this[property] === parent[property]); + }; + } + members = null; + return isProperty.call(this, property); + }; + } + + // Internal: Normalizes the `for...in` iteration algorithm across + // environments. Each enumerated key is yielded to a `callback` function. + forEach = function (object, callback) { + var size = 0, Properties, members, property; + + // Tests for bugs in the current environment's `for...in` algorithm. The + // `valueOf` property inherits the non-enumerable flag from + // `Object.prototype` in older versions of IE, Netscape, and Mozilla. + (Properties = function () { + this.valueOf = 0; + }).prototype.valueOf = 0; + + // Iterate over a new instance of the `Properties` class. + members = new Properties(); + for (property in members) { + // Ignore all properties inherited from `Object.prototype`. + if (isProperty.call(members, property)) { + size++; + } + } + Properties = members = null; + + // Normalize the iteration algorithm. + if (!size) { + // A list of non-enumerable properties inherited from `Object.prototype`. + members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"]; + // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable + // properties. + forEach = function (object, callback) { + var isFunction = getClass.call(object) == functionClass, property, length; + var hasProperty = !isFunction && typeof object.constructor != "function" && objectTypes[typeof object.hasOwnProperty] && object.hasOwnProperty || isProperty; + for (property in object) { + // Gecko <= 1.0 enumerates the `prototype` property of functions under + // certain conditions; IE does not. + if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) { + callback(property); + } + } + // Manually invoke the callback for each non-enumerable property. + for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property)); + }; + } else if (size == 2) { + // Safari <= 2.0.4 enumerates shadowed properties twice. + forEach = function (object, callback) { + // Create a set of iterated properties. + var members = {}, isFunction = getClass.call(object) == functionClass, property; + for (property in object) { + // Store each property name to prevent double enumeration. The + // `prototype` property of functions is not enumerated due to cross- + // environment inconsistencies. + if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) { + callback(property); + } + } + }; + } else { + // No bugs detected; use the standard `for...in` algorithm. + forEach = function (object, callback) { + var isFunction = getClass.call(object) == functionClass, property, isConstructor; + for (property in object) { + if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) { + callback(property); + } + } + // Manually invoke the callback for the `constructor` property due to + // cross-environment inconsistencies. + if (isConstructor || isProperty.call(object, (property = "constructor"))) { + callback(property); + } + }; + } + return forEach(object, callback); + }; + + // Public: Serializes a JavaScript `value` as a JSON string. The optional + // `filter` argument may specify either a function that alters how object and + // array members are serialized, or an array of strings and numbers that + // indicates which properties should be serialized. The optional `width` + // argument may be either a string or number that specifies the indentation + // level of the output. + if (!has("json-stringify")) { + // Internal: A map of control characters and their escaped equivalents. + var Escapes = { + 92: "\\\\", + 34: '\\"', + 8: "\\b", + 12: "\\f", + 10: "\\n", + 13: "\\r", + 9: "\\t" + }; + + // Internal: Converts `value` into a zero-padded string such that its + // length is at least equal to `width`. The `width` must be <= 6. + var leadingZeroes = "000000"; + var toPaddedString = function (width, value) { + // The `|| 0` expression is necessary to work around a bug in + // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`. + return (leadingZeroes + (value || 0)).slice(-width); + }; + + // Internal: Double-quotes a string `value`, replacing all ASCII control + // characters (characters with code unit values between 0 and 31) with + // their escaped equivalents. This is an implementation of the + // `Quote(value)` operation defined in ES 5.1 section 15.12.3. + var unicodePrefix = "\\u00"; + var quote = function (value) { + var result = '"', index = 0, length = value.length, useCharIndex = !charIndexBuggy || length > 10; + var symbols = useCharIndex && (charIndexBuggy ? value.split("") : value); + for (; index < length; index++) { + var charCode = value.charCodeAt(index); + // If the character is a control character, append its Unicode or + // shorthand escape sequence; otherwise, append the character as-is. + switch (charCode) { + case 8: case 9: case 10: case 12: case 13: case 34: case 92: + result += Escapes[charCode]; + break; + default: + if (charCode < 32) { + result += unicodePrefix + toPaddedString(2, charCode.toString(16)); + break; + } + result += useCharIndex ? symbols[index] : value.charAt(index); + } + } + return result + '"'; + }; + + // Internal: Recursively serializes an object. Implements the + // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations. + var serialize = function (property, object, callback, properties, whitespace, indentation, stack) { + var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result; + try { + // Necessary for host object support. + value = object[property]; + } catch (exception) {} + if (typeof value == "object" && value) { + className = getClass.call(value); + if (className == dateClass && !isProperty.call(value, "toJSON")) { + if (value > -1 / 0 && value < 1 / 0) { + // Dates are serialized according to the `Date#toJSON` method + // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15 + // for the ISO 8601 date time string format. + if (getDay) { + // Manually compute the year, month, date, hours, minutes, + // seconds, and milliseconds if the `getUTC*` methods are + // buggy. Adapted from @Yaffle's `date-shim` project. + date = floor(value / 864e5); + for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++); + for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++); + date = 1 + date - getDay(year, month); + // The `time` value specifies the time within the day (see ES + // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used + // to compute `A modulo B`, as the `%` operator does not + // correspond to the `modulo` operation for negative numbers. + time = (value % 864e5 + 864e5) % 864e5; + // The hours, minutes, seconds, and milliseconds are obtained by + // decomposing the time within the day. See section 15.9.1.10. + hours = floor(time / 36e5) % 24; + minutes = floor(time / 6e4) % 60; + seconds = floor(time / 1e3) % 60; + milliseconds = time % 1e3; + } else { + year = value.getUTCFullYear(); + month = value.getUTCMonth(); + date = value.getUTCDate(); + hours = value.getUTCHours(); + minutes = value.getUTCMinutes(); + seconds = value.getUTCSeconds(); + milliseconds = value.getUTCMilliseconds(); + } + // Serialize extended years correctly. + value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) + + "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) + + // Months, dates, hours, minutes, and seconds should have two + // digits; milliseconds should have three. + "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) + + // Milliseconds are optional in ES 5.0, but required in 5.1. + "." + toPaddedString(3, milliseconds) + "Z"; + } else { + value = null; + } + } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) { + // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the + // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3 + // ignores all `toJSON` methods on these objects unless they are + // defined directly on an instance. + value = value.toJSON(property); + } + } + if (callback) { + // If a replacement function was provided, call it to obtain the value + // for serialization. + value = callback.call(object, property, value); + } + if (value === null) { + return "null"; + } + className = getClass.call(value); + if (className == booleanClass) { + // Booleans are represented literally. + return "" + value; + } else if (className == numberClass) { + // JSON numbers must be finite. `Infinity` and `NaN` are serialized as + // `"null"`. + return value > -1 / 0 && value < 1 / 0 ? "" + value : "null"; + } else if (className == stringClass) { + // Strings are double-quoted and escaped. + return quote("" + value); + } + // Recursively serialize objects and arrays. + if (typeof value == "object") { + // Check for cyclic structures. This is a linear search; performance + // is inversely proportional to the number of unique nested objects. + for (length = stack.length; length--;) { + if (stack[length] === value) { + // Cyclic structures cannot be serialized by `JSON.stringify`. + throw TypeError(); + } + } + // Add the object to the stack of traversed objects. + stack.push(value); + results = []; + // Save the current indentation level and indent one additional level. + prefix = indentation; + indentation += whitespace; + if (className == arrayClass) { + // Recursively serialize array elements. + for (index = 0, length = value.length; index < length; index++) { + element = serialize(index, value, callback, properties, whitespace, indentation, stack); + results.push(element === undef ? "null" : element); + } + result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]"; + } else { + // Recursively serialize object members. Members are selected from + // either a user-specified list of property names, or the object + // itself. + forEach(properties || value, function (property) { + var element = serialize(property, value, callback, properties, whitespace, indentation, stack); + if (element !== undef) { + // According to ES 5.1 section 15.12.3: "If `gap` {whitespace} + // is not the empty string, let `member` {quote(property) + ":"} + // be the concatenation of `member` and the `space` character." + // The "`space` character" refers to the literal space + // character, not the `space` {width} argument provided to + // `JSON.stringify`. + results.push(quote(property) + ":" + (whitespace ? " " : "") + element); + } + }); + result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}"; + } + // Remove the object from the traversed object stack. + stack.pop(); + return result; + } + }; + + // Public: `JSON.stringify`. See ES 5.1 section 15.12.3. + exports.stringify = function (source, filter, width) { + var whitespace, callback, properties, className; + if (objectTypes[typeof filter] && filter) { + if ((className = getClass.call(filter)) == functionClass) { + callback = filter; + } else if (className == arrayClass) { + // Convert the property names array into a makeshift set. + properties = {}; + for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1)); + } + } + if (width) { + if ((className = getClass.call(width)) == numberClass) { + // Convert the `width` to an integer and create a string containing + // `width` number of space characters. + if ((width -= width % 1) > 0) { + for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " "); + } + } else if (className == stringClass) { + whitespace = width.length <= 10 ? width : width.slice(0, 10); + } + } + // Opera <= 7.54u2 discards the values associated with empty string keys + // (`""`) only if they are used directly within an object member list + // (e.g., `!("" in { "": 1})`). + return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []); + }; + } + + // Public: Parses a JSON source string. + if (!has("json-parse")) { + var fromCharCode = String.fromCharCode; + + // Internal: A map of escaped control characters and their unescaped + // equivalents. + var Unescapes = { + 92: "\\", + 34: '"', + 47: "/", + 98: "\b", + 116: "\t", + 110: "\n", + 102: "\f", + 114: "\r" + }; + + // Internal: Stores the parser state. + var Index, Source; + + // Internal: Resets the parser state and throws a `SyntaxError`. + var abort = function () { + Index = Source = null; + throw SyntaxError(); + }; + + // Internal: Returns the next token, or `"$"` if the parser has reached + // the end of the source string. A token may be a string, number, `null` + // literal, or Boolean literal. + var lex = function () { + var source = Source, length = source.length, value, begin, position, isSigned, charCode; + while (Index < length) { + charCode = source.charCodeAt(Index); + switch (charCode) { + case 9: case 10: case 13: case 32: + // Skip whitespace tokens, including tabs, carriage returns, line + // feeds, and space characters. + Index++; + break; + case 123: case 125: case 91: case 93: case 58: case 44: + // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at + // the current position. + value = charIndexBuggy ? source.charAt(Index) : source[Index]; + Index++; + return value; + case 34: + // `"` delimits a JSON string; advance to the next character and + // begin parsing the string. String tokens are prefixed with the + // sentinel `@` character to distinguish them from punctuators and + // end-of-string tokens. + for (value = "@", Index++; Index < length;) { + charCode = source.charCodeAt(Index); + if (charCode < 32) { + // Unescaped ASCII control characters (those with a code unit + // less than the space character) are not permitted. + abort(); + } else if (charCode == 92) { + // A reverse solidus (`\`) marks the beginning of an escaped + // control character (including `"`, `\`, and `/`) or Unicode + // escape sequence. + charCode = source.charCodeAt(++Index); + switch (charCode) { + case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114: + // Revive escaped control characters. + value += Unescapes[charCode]; + Index++; + break; + case 117: + // `\u` marks the beginning of a Unicode escape sequence. + // Advance to the first character and validate the + // four-digit code point. + begin = ++Index; + for (position = Index + 4; Index < position; Index++) { + charCode = source.charCodeAt(Index); + // A valid sequence comprises four hexdigits (case- + // insensitive) that form a single hexadecimal value. + if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) { + // Invalid Unicode escape sequence. + abort(); + } + } + // Revive the escaped character. + value += fromCharCode("0x" + source.slice(begin, Index)); + break; + default: + // Invalid escape sequence. + abort(); + } + } else { + if (charCode == 34) { + // An unescaped double-quote character marks the end of the + // string. + break; + } + charCode = source.charCodeAt(Index); + begin = Index; + // Optimize for the common case where a string is valid. + while (charCode >= 32 && charCode != 92 && charCode != 34) { + charCode = source.charCodeAt(++Index); + } + // Append the string as-is. + value += source.slice(begin, Index); + } + } + if (source.charCodeAt(Index) == 34) { + // Advance to the next character and return the revived string. + Index++; + return value; + } + // Unterminated string. + abort(); + default: + // Parse numbers and literals. + begin = Index; + // Advance past the negative sign, if one is specified. + if (charCode == 45) { + isSigned = true; + charCode = source.charCodeAt(++Index); + } + // Parse an integer or floating-point value. + if (charCode >= 48 && charCode <= 57) { + // Leading zeroes are interpreted as octal literals. + if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) { + // Illegal octal literal. + abort(); + } + isSigned = false; + // Parse the integer component. + for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++); + // Floats cannot contain a leading decimal point; however, this + // case is already accounted for by the parser. + if (source.charCodeAt(Index) == 46) { + position = ++Index; + // Parse the decimal component. + for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); + if (position == Index) { + // Illegal trailing decimal. + abort(); + } + Index = position; + } + // Parse exponents. The `e` denoting the exponent is + // case-insensitive. + charCode = source.charCodeAt(Index); + if (charCode == 101 || charCode == 69) { + charCode = source.charCodeAt(++Index); + // Skip past the sign following the exponent, if one is + // specified. + if (charCode == 43 || charCode == 45) { + Index++; + } + // Parse the exponential component. + for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); + if (position == Index) { + // Illegal empty exponent. + abort(); + } + Index = position; + } + // Coerce the parsed value to a JavaScript number. + return +source.slice(begin, Index); + } + // A negative sign may only precede numbers. + if (isSigned) { + abort(); + } + // `true`, `false`, and `null` literals. + if (source.slice(Index, Index + 4) == "true") { + Index += 4; + return true; + } else if (source.slice(Index, Index + 5) == "false") { + Index += 5; + return false; + } else if (source.slice(Index, Index + 4) == "null") { + Index += 4; + return null; + } + // Unrecognized token. + abort(); + } + } + // Return the sentinel `$` character if the parser has reached the end + // of the source string. + return "$"; + }; + + // Internal: Parses a JSON `value` token. + var get = function (value) { + var results, hasMembers; + if (value == "$") { + // Unexpected end of input. + abort(); + } + if (typeof value == "string") { + if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") { + // Remove the sentinel `@` character. + return value.slice(1); + } + // Parse object and array literals. + if (value == "[") { + // Parses a JSON array, returning a new JavaScript array. + results = []; + for (;; hasMembers || (hasMembers = true)) { + value = lex(); + // A closing square bracket marks the end of the array literal. + if (value == "]") { + break; + } + // If the array literal contains elements, the current token + // should be a comma separating the previous element from the + // next. + if (hasMembers) { + if (value == ",") { + value = lex(); + if (value == "]") { + // Unexpected trailing `,` in array literal. + abort(); + } + } else { + // A `,` must separate each array element. + abort(); + } + } + // Elisions and leading commas are not permitted. + if (value == ",") { + abort(); + } + results.push(get(value)); + } + return results; + } else if (value == "{") { + // Parses a JSON object, returning a new JavaScript object. + results = {}; + for (;; hasMembers || (hasMembers = true)) { + value = lex(); + // A closing curly brace marks the end of the object literal. + if (value == "}") { + break; + } + // If the object literal contains members, the current token + // should be a comma separator. + if (hasMembers) { + if (value == ",") { + value = lex(); + if (value == "}") { + // Unexpected trailing `,` in object literal. + abort(); + } + } else { + // A `,` must separate each object member. + abort(); + } + } + // Leading commas are not permitted, object property names must be + // double-quoted strings, and a `:` must separate each property + // name and value. + if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") { + abort(); + } + results[value.slice(1)] = get(lex()); + } + return results; + } + // Unexpected token encountered. + abort(); + } + return value; + }; + + // Internal: Updates a traversed object member. + var update = function (source, property, callback) { + var element = walk(source, property, callback); + if (element === undef) { + delete source[property]; + } else { + source[property] = element; + } + }; + + // Internal: Recursively traverses a parsed JSON object, invoking the + // `callback` function for each value. This is an implementation of the + // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2. + var walk = function (source, property, callback) { + var value = source[property], length; + if (typeof value == "object" && value) { + // `forEach` can't be used to traverse an array in Opera <= 8.54 + // because its `Object#hasOwnProperty` implementation returns `false` + // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`). + if (getClass.call(value) == arrayClass) { + for (length = value.length; length--;) { + update(value, length, callback); + } + } else { + forEach(value, function (property) { + update(value, property, callback); + }); + } + } + return callback.call(source, property, value); + }; + + // Public: `JSON.parse`. See ES 5.1 section 15.12.2. + exports.parse = function (source, callback) { + var result, value; + Index = 0; + Source = "" + source; + result = get(lex()); + // If a JSON string contains multiple tokens, it is invalid. + if (lex() != "$") { + abort(); + } + // Reset the parser state. + Index = Source = null; + return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result; + }; + } + } + + exports["runInContext"] = runInContext; + return exports; + } + + if (freeExports && !isLoader) { + // Export for CommonJS environments. + runInContext(root, freeExports); + } else { + // Export for web browsers and JavaScript engines. + var nativeJSON = root.JSON, + previousJSON = root["JSON3"], + isRestored = false; + + var JSON3 = runInContext(root, (root["JSON3"] = { + // Public: Restores the original value of the global `JSON` object and + // returns a reference to the `JSON3` object. + "noConflict": function () { + if (!isRestored) { + isRestored = true; + root.JSON = nativeJSON; + root["JSON3"] = previousJSON; + nativeJSON = previousJSON = null; + } + return JSON3; + } + })); + + root.JSON = { + "parse": JSON3.parse, + "stringify": JSON3.stringify + }; + } + + // Export for asynchronous module loaders. + if (isLoader) { + define(function () { + return JSON3; + }); + } +}).call(this); + +//############################################################################## +// 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; + +}()); + +//############################################################################## +// 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: + *
      + *
    • If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or + * `//networkPath`)
    • + *
    • If the path is relative. Relative paths start with `../` or `/path` (or similar)
    • + *
    • The file extension. This is determined by the filename with an extension. Query strings are dropped, and + * the file path is expected to follow the format `name.ext`.
    • + *
    + * + * @method parseURI + * @param {String} path + * @returns {Object} An Object with an `absolute` and `relative` Boolean values, + * 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; + +}()); + +//############################################################################## +// 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; + +}()); + +//############################################################################## +// DataUtils.js +//############################################################################## + +(function () { + + /** + * A few data utilities for formatting different data types. + * @class DataUtils + */ + var s = {}; + + // static methods + /** + * Parse XML using the DOM. This is required when preloading XML or SVG. + * @method parseXML + * @param {String} text The raw text or XML that is loaded by XHR. + * @return {XML} An XML document + * @static + */ + s.parseXML = function (text) { + var xml = null; + // CocoonJS does not support XML parsing with either method. + + // Most browsers will use DOMParser + // IE fails on certain SVG files, so we have a fallback below. + try { + if (window.DOMParser) { + var parser = new DOMParser(); + xml = parser.parseFromString(text, "text/xml"); + } + } catch (e) { + } + + // Fallback for IE support. + if (!xml) { + try { + xml = new ActiveXObject("Microsoft.XMLDOM"); + xml.async = false; + xml.loadXML(text); + } catch (e) { + xml = null; + } + } + + return xml; + }; + + /** + * Parse a string into an Object. + * @method parseJSON + * @param {String} value The loaded JSON string + * @returns {Object} A JavaScript object. + */ + s.parseJSON = function (value) { + if (value == null) { + return null; + } + + try { + return JSON.parse(value); + } catch (e) { + // TODO; Handle this with a custom error? + throw e; + } + }; + + createjs.DataUtils = s; + +}()); + +//############################################################################## +// Types.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(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; +}()); + +//############################################################################## +// Methods.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(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; +}()); + +//############################################################################## +// LoadItem.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + /** + * All loaders accept an item containing the properties defined in this class. If a raw object is passed instead, + * it will not be affected, but it must contain at least a {{#crossLink "src:property"}}{{/crossLink}} property. A + * string path or HTML tag is also acceptable, but it will be automatically converted to a LoadItem using the + * {{#crossLink "create"}}{{/crossLink}} method by {{#crossLink "AbstractLoader"}}{{/crossLink}} + * @class LoadItem + * @constructor + * @since 0.6.0 + */ + function LoadItem() { + /** + * The source of the file that is being loaded. This property is required. The source can either be a + * string (recommended), or an HTML tag. + * This can also be an object, but in that case it has to include a type and be handled by a plugin. + * @property src + * @type {String} + * @default null + */ + this.src = null; + + /** + * 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. + *
      + *
    • String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
    • + *
    • LoadItem instances are returned as-is
    • + *
    • Objects are returned with any needed properties added
    • + *
    + * @method create + * @param {LoadItem|String|Object} value The load item value + * @returns {LoadItem|Object} + * @static + */ + s.create = function (value) { + if (typeof value == "string") { + var item = new LoadItem(); + item.src = value; + return item; + } else if (value instanceof s) { + return value; + } else if (value instanceof Object && value.src) { + if (value.loadTimeout == null) { + value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT; + } + return value; + } else { + throw new Error("Type not recognized."); + } + }; + + /** + * Provides a chainable shortcut method for setting a number of properties on the instance. + * + *

    Example

    + * + * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true}); + * + * @method set + * @param {Object} props A generic object containing properties to copy to the LoadItem instance. + * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.) + */ + p.set = function(props) { + for (var n in props) { this[n] = props[n]; } + return this; + }; + + createjs.LoadItem = s; + +}()); + +//############################################################################## +// 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; + +}()); + +//############################################################################## +// AbstractLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(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 +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * The AbstractMediaLoader is a base class that handles some of the shared methods and properties of loaders that + * handle HTML media elements, such as Video and Audio. + * @class AbstractMediaLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @param {String} type The type of media to load. Usually "video" or "audio". + * @extends AbstractLoader + * @constructor + */ + function AbstractMediaLoader(loadItem, preferXHR, type) { + this.AbstractLoader_constructor(loadItem, preferXHR, type); + + // public properties + this.resultFormatter = this._formatResult; + + // protected properties + this._tagSrcAttribute = "src"; + + this.on("initialize", this._updateXHR, this); + }; + + var p = createjs.extend(AbstractMediaLoader, createjs.AbstractLoader); + + // static properties + // public methods + p.load = function () { + // TagRequest will handle most of this, but Sound / Video need a few custom properties, so just handle them here. + if (!this._tag) { + this._tag = this._createTag(this._item.src); + } + + this._tag.preload = "auto"; + this._tag.load(); + + this.AbstractLoader_load(); + }; + + // protected methods + /** + * Creates a new tag for loading if it doesn't exist yet. + * @method _createTag + * @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 +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + /** + * A base class for actual data requests, such as {{#crossLink "XHRRequest"}}{{/crossLink}}, {{#crossLink "TagRequest"}}{{/crossLink}}, + * and {{#crossLink "MediaRequest"}}{{/crossLink}}. PreloadJS loaders will typically use a data loader under the + * hood to get data. + * @class AbstractRequest + * @param {LoadItem} item + * @constructor + */ + var AbstractRequest = function (item) { + this._item = item; + }; + + 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 +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * An {{#crossLink "AbstractRequest"}}{{/crossLink}} that loads HTML tags, such as images and scripts. + * @class TagRequest + * @param {LoadItem} loadItem + * @param {HTMLElement} tag + * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc. + */ + function TagRequest(loadItem, tag, srcAttribute) { + this.AbstractRequest_constructor(loadItem); + + // protected properties + /** + * The HTML tag instance that is used to load. + * @property _tag + * @type {HTMLElement} + * @protected + */ + this._tag = tag; + + /** + * The tag attribute that specifies the source, such as "src", "href", etc. + * @property _tagSrcAttribute + * @type {String} + * @protected + */ + this._tagSrcAttribute = srcAttribute; + + /** + * A method closure used for handling the tag load event. + * @property _loadedHandler + * @type {Function} + * @private + */ + this._loadedHandler = createjs.proxy(this._handleTagComplete, this); + + /** + * Determines if the element was added to the DOM automatically by PreloadJS, so it can be cleaned up after. + * @property _addedToDOM + * @type {Boolean} + * @private + */ + this._addedToDOM = false; + + }; + + 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 +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * An {{#crossLink "TagRequest"}}{{/crossLink}} that loads HTML tags for video and audio. + * @class MediaTagRequest + * @param {LoadItem} loadItem + * @param {HTMLAudioElement|HTMLVideoElement} tag + * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc. + * @constructor + */ + function MediaTagRequest(loadItem, tag, srcAttribute) { + this.AbstractRequest_constructor(loadItem); + + // protected properties + this._tag = tag; + this._tagSrcAttribute = srcAttribute; + this._loadedHandler = createjs.proxy(this._handleTagComplete, this); + }; + + var p = createjs.extend(MediaTagRequest, createjs.TagRequest); + var s = MediaTagRequest; + + // public methods + p.load = function () { + var sc = createjs.proxy(this._handleStalled, this); + this._stalledCallback = sc; + + var pc = createjs.proxy(this._handleProgress, this); + this._handleProgress = pc; + + this._tag.addEventListener("stalled", sc); + this._tag.addEventListener("progress", pc); + + // This will tell us when audio is buffered enough to play through, but not when its loaded. + // The tag doesn't keep loading in Chrome once enough has buffered, and we have decided that behaviour is sufficient. + this._tag.addEventListener && this._tag.addEventListener("canplaythrough", this._loadedHandler, false); // canplaythrough callback doesn't work in Chrome, so we use an event. + + this.TagRequest_load(); + }; + + // private methods + p._handleReadyStateChange = function () { + clearTimeout(this._loadTimeout); + // This is strictly for tags in browsers that do not support onload. + var tag = this._tag; + + // Complete is for old IE support. + if (tag.readyState == "loaded" || tag.readyState == "complete") { + this._handleTagComplete(); + } + }; + + p._handleStalled = function () { + //Ignore, let the timeout take care of it. Sometimes its not really stopped. + }; + + /** + * An XHR request has reported progress. + * @method _handleProgress + * @param {Object} event The XHR progress event. + * @private + */ + p._handleProgress = function (event) { + if (!event || event.loaded > 0 && event.total == 0) { + return; // Sometimes we get no "total", so just ignore the progress event. + } + + var newEvent = new createjs.ProgressEvent(event.loaded, event.total); + this.dispatchEvent(newEvent); + }; + + // protected methods + p._clean = function () { + this._tag.removeEventListener && this._tag.removeEventListener("canplaythrough", this._loadedHandler); + this._tag.removeEventListener("stalled", this._stalledCallback); + this._tag.removeEventListener("progress", this._progressCallback); + + this.TagRequest__clean(); + }; + + createjs.MediaTagRequest = createjs.promote(MediaTagRequest, "TagRequest"); + +}()); + +//############################################################################## +// XHRRequest.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + +// constructor + /** + * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used + * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary. + * XHR requests load the content as text or binary data, provide progress and consistent completion events, and + * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for + * cross-domain loading. + * @class XHRRequest + * @constructor + * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} + * for an overview of supported file properties. + * @extends AbstractLoader + */ + function XHRRequest (item) { + this.AbstractRequest_constructor(item); + + // protected properties + /** + * A reference to the XHR request used to load the content. + * @property _request + * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP} + * @private + */ + this._request = null; + + /** + * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1, + * typically IE9). + * @property _loadTimeout + * @type {Number} + * @private + */ + this._loadTimeout = null; + + /** + * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect + * the version, so we use capabilities to make a best guess. + * @property _xhrLevel + * @type {Number} + * @default 1 + * @private + */ + this._xhrLevel = 1; + + /** + * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be + * null until the file is loaded. + * @property _response + * @type {mixed} + * @private + */ + this._response = null; + + /** + * The response of the loaded file before it is modified. In most cases, content is converted from raw text to + * an HTML tag or a formatted object which is set to the result property, but the developer may still + * want to access the raw content as it was loaded. + * @property _rawResponse + * @type {String|Object} + * @private + */ + this._rawResponse = null; + + this._canceled = false; + + // Setup our event handlers now. + this._handleLoadStartProxy = createjs.proxy(this._handleLoadStart, this); + this._handleProgressProxy = createjs.proxy(this._handleProgress, this); + this._handleAbortProxy = createjs.proxy(this._handleAbort, this); + this._handleErrorProxy = createjs.proxy(this._handleError, this); + this._handleTimeoutProxy = createjs.proxy(this._handleTimeout, this); + this._handleLoadProxy = createjs.proxy(this._handleLoad, this); + this._handleReadyStateChangeProxy = createjs.proxy(this._handleReadyStateChange, this); + + if (!this._createXHR(item)) { + //TODO: Throw error? + } + }; + + var p = createjs.extend(XHRRequest, createjs.AbstractRequest); + +// static properties + /** + * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE. + * @property ACTIVEX_VERSIONS + * @type {Array} + * @since 0.4.2 + * @private + */ + XHRRequest.ACTIVEX_VERSIONS = [ + "Msxml2.XMLHTTP.6.0", + "Msxml2.XMLHTTP.5.0", + "Msxml2.XMLHTTP.4.0", + "MSXML2.XMLHTTP.3.0", + "MSXML2.XMLHTTP", + "Microsoft.XMLHTTP" + ]; + +// Public methods + /** + * Look up the loaded result. + * @method getResult + * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content + * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be + * returned instead. + * @return {Object} A result object containing the content that was loaded, such as: + *
      + *
    • An image tag (<image />) for images
    • + *
    • A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the + * HTML head.
    • + *
    • A style tag for CSS (<style />)
    • + *
    • Raw text for TEXT
    • + *
    • A formatted JavaScript object defined by JSON
    • + *
    • An XML document
    • + *
    • An binary arraybuffer loaded by XHR
    • + *
    + * Note that if a raw result is requested, but not found, the result will be returned instead. + */ + p.getResult = function (raw) { + if (raw && this._rawResponse) { + return this._rawResponse; + } + return this._response; + }; + + // Overrides abstract method in AbstractRequest + p.cancel = function () { + this.canceled = true; + this._clean(); + this._request.abort(); + }; + + // Overrides abstract method in AbstractLoader + p.load = function () { + if (this._request == null) { + this._handleError(); + return; + } + + //Events + if (this._request.addEventListener != null) { + this._request.addEventListener("loadstart", this._handleLoadStartProxy, false); + this._request.addEventListener("progress", this._handleProgressProxy, false); + this._request.addEventListener("abort", this._handleAbortProxy, false); + this._request.addEventListener("error", this._handleErrorProxy, false); + this._request.addEventListener("timeout", this._handleTimeoutProxy, false); + + // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. + this._request.addEventListener("load", this._handleLoadProxy, false); + this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false); + } else { + // IE9 support + this._request.onloadstart = this._handleLoadStartProxy; + this._request.onprogress = this._handleProgressProxy; + this._request.onabort = this._handleAbortProxy; + this._request.onerror = this._handleErrorProxy; + this._request.ontimeout = this._handleTimeoutProxy; + + // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. + this._request.onload = this._handleLoadProxy; + this._request.onreadystatechange = this._handleReadyStateChangeProxy; + } + + // Set up a timeout if we don't have XHR2 + if (this._xhrLevel == 1) { + this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); + } + + // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome + try { + if (!this._item.values) { + this._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: + *
      + *
    • Status codes between 400 and 599 (HTTP error range)
    • + *
    • A status of 0, but *only when the application is running on a server*. If the application is running + * on `file:`, then it may incorrectly treat an error on local (or embedded applications) as a successful + * load.
    • + *
    + * @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"); + +}()); + +//############################################################################## +// LoadQueue.js +//############################################################################## + +this.createjs = this.createjs || {}; + +/* + TODO: WINDOWS ISSUES + * No error for HTML audio in IE 678 + * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR + * No script complete handler in IE 67 TAGS (XHR is fine) + * No XML/JSON in IE6 TAGS + * Need to hide loading SVG in Opera TAGS + * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking) + * SVG no load or failure in Opera XHR + * Reported issues with IE7/8 + */ + +(function () { + "use strict"; + +// constructor + /** + * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either + * a single file, or queue of files. + * + * Creating a Queue
    + * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the preferXHR + * argument to false. + * + * var queue = new createjs.LoadQueue(true); + * + * Listening for Events
    + * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}} + * lets you add as many listeners as you want for events. You can subscribe to the following events:
      + *
    • {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all + * files
    • + *
    • {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with + * any file.
    • + *
    • {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has + * changed.
    • + *
    • {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.
    • + *
    • {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note + * that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.
    • + *
    + * + * queue.on("fileload", handleFileLoad, this); + * queue.on("complete", handleComplete, this); + * + * Adding files and manifests
    + * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a + * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are + * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you + * like. + * + * queue.loadFile("filePath/file.jpg"); + * queue.loadFile({id:"image", src:"filePath/file.jpg"}); + * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]); + * + * // Use an external manifest + * queue.loadManifest("path/to/manifest.json"); + * queue.loadManifest({src:"manifest.json", type:"manifest"}); + * + * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not + * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin + * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a + * `loadNow` argument of `true`. + * + * queue.load(); + * + * File Types
    + * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS + * should handle the majority of standard file and url formats, and works with common file extensions. If you have + * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a + * type property with any manifest item. + * + * queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.Types.SOUND}); + * + * // Note that PreloadJS will not read a file extension from the query string + * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:createjs.Types.IMAGE}); + * + * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include: + *
      + *
    • {{#crossLink "Types/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
    • + *
    • {{#crossLink "Types/CSS:property"}}{{/crossLink}}: CSS files
    • + *
    • {{#crossLink "Types/IMAGE:property"}}{{/crossLink}}: Common image formats
    • + *
    • {{#crossLink "Types/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
    • + *
    • {{#crossLink "Types/JSON:property"}}{{/crossLink}}: JSON data
    • + *
    • {{#crossLink "Types/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
    • + *
    • {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see + * {{#crossLink "AbstractLoader/loadManifest"}}{{/crossLink}}
    • + *
    • {{#crossLink "Types/SOUND:property"}}{{/crossLink}}: Audio file formats
    • + *
    • {{#crossLink "Types/SPRITESHEET:property"}}{{/crossLink}}: JSON SpriteSheet definitions. This + * will also load sub-images, and provide a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance.
    • + *
    • {{#crossLink "Types/SVG:property"}}{{/crossLink}}: SVG files
    • + *
    • {{#crossLink "Types/TEXT:property"}}{{/crossLink}}: Text files - XHR only
    • + *
    • {{#crossLink "Types/VIDEO:property"}}{{/crossLink}}: Video objects
    • + *
    • {{#crossLink "Types/XML:property"}}{{/crossLink}}: XML data
    • + *
    + * + * Note: Loader types used to be defined on LoadQueue, but have been moved to the Types class + * + * Handling Results
    + * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is + * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a + * formatted object that can be used immediately, including: + *
      + *
    • Binary: The binary loaded result
    • + *
    • CSS: A <link /> tag
    • + *
    • Image: An <img /> tag
    • + *
    • JavaScript: A <script /> tag
    • + *
    • JSON/JSONP: A formatted JavaScript Object
    • + *
    • Manifest: A JavaScript object. + *
    • Sound: An <audio /> tag + *
    • SpriteSheet: A {{#crossLink "SpriteSheet"}}{{/crossLink}} instance, containing loaded images. + *
    • SVG: An <object /> tag
    • + *
    • Text: Raw text
    • + *
    • Video: A Video DOM node
    • + *
    • XML: An XML DOM node
    • + *
    + * + * function handleFileLoad(event) { + * var item = event.item; // A reference to the item that was passed in to the LoadQueue + * var type = item.type; + * + * // Add any images to the page body. + * if (type == createjs.Types.IMAGE) { + * document.body.appendChild(event.result); + * } + * } + * + * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up + * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the + * "src" or file path can be used instead, including the `path` defined by a manifest, but not including + * a base path defined on the LoadQueue. It is recommended to always pass an id if you want to look up content. + * + * var image = queue.getResult("image"); + * document.body.appendChild(image); + * + * Raw loaded content can be accessed using the rawResult property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} + * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd + * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript, + * CSS, XML, SVG, and JSON objects, or anything loaded with XHR. + * + * var image = queue.getResult("image", true); // load the binary image data loaded with XHR. + * + * Plugins
    + * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio, + * make sure to install the SoundJS Sound class, which will help load HTML audio, + * Flash audio, and WebAudio files. This should be installed before loading any audio files. + * + * queue.installPlugin(createjs.Sound); + * + *

    Known Browser Issues

    + *
      + *
    • Browsers without audio support can not load audio files.
    • + *
    • Safari on Mac OS X can only play HTML audio if QuickTime is installed
    • + *
    • HTML Audio tags will only download until their canPlayThrough event is fired. Browsers other + * than Chrome will continue to download in the background.
    • + *
    • When loading scripts using tags, they are automatically added to the document.
    • + *
    • Scripts loaded via XHR may not be properly inspectable with browser tools.
    • + *
    • IE6 and IE7 (and some other browsers) may not be able to load XML, Text, or JSON, since they require + * XHR to work.
    • + *
    • Content loaded via tags will not show progress, and will continue to download in the background when + * canceled, although no events will be dispatched.
    • + *
    + * + * @class LoadQueue + * @param {Boolean} [preferXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP + * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR + * when necessary. + * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue + * before they are loaded. Sources beginning with a protocol such as `http://` or a relative path such as `../` + * will not receive a base path. + * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To + * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any + * string value will be passed through, but only "" and "Anonymous" are recommended. Note: The crossOrigin + * parameter is deprecated. Use LoadItem.crossOrigin instead + * + * @constructor + * @extends AbstractLoader + */ + function LoadQueue (preferXHR, basePath, crossOrigin) { + this.AbstractLoader_constructor(); + + /** + * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}. + * @property _plugins + * @type {Array} + * @private + * @since 0.6.1 + */ + this._plugins = []; + + /** + * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the + * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} + * method for more information. + * @property _typeCallbacks + * @type {Object} + * @private + */ + this._typeCallbacks = {}; + + /** + * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the + * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} + * method for more information. + * @property _extensionCallbacks + * @type {null} + * @private + */ + this._extensionCallbacks = {}; + + /** + * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and + * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed. + * @property next + * @type {LoadQueue} + * @default null + */ + this.next = null; + + /** + * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head + * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas + * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order + * specified. + * + * Any items can be set to load in order by setting the {{#crossLink "maintainOrder:property"}}{{/crossLink}} + * property on the load item, or by ensuring that only one connection can be open at a time using + * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Note that when the `maintainScriptOrder` property + * is set to `true`, scripts items are automatically set to `maintainOrder=true`, and changing the + * `maintainScriptOrder` to `false` during a load will not change items already in a queue. + * + *

    Example

    + * + * var queue = new createjs.LoadQueue(); + * queue.setMaxConnections(3); // Set a higher number to load multiple items at once + * queue.maintainScriptOrder = true; // Ensure scripts are loaded in order + * queue.loadManifest([ + * "script1.js", + * "script2.js", + * "image.png", // Load any time + * {src: "image2.png", maintainOrder: true} // Will wait for script2.js + * "image3.png", + * "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR) + * ]); + * + * @property maintainScriptOrder + * @type {Boolean} + * @default true + */ + this.maintainScriptOrder = true; + + /** + * Determines if the LoadQueue will stop processing the current queue when an error is encountered. + * @property stopOnError + * @type {Boolean} + * @default false + */ + this.stopOnError = false; + + /** + * The number of maximum open connections that a loadQueue tries to maintain. Please see + * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information. + * @property _maxConnections + * @type {Number} + * @default 1 + * @private + */ + this._maxConnections = 1; + + /** + * An internal list of all the default Loaders that are included with PreloadJS. Before an item is loaded, the + * available loader list is iterated, in the order they are included, and as soon as a loader indicates it can + * handle the content, it will be selected. The default loader, ({{#crossLink "TextLoader"}}{{/crossLink}} is + * last in the list, so it will be used if no other match is found. Typically, loaders will match based on the + * {{#crossLink "LoadItem/type"}}{{/crossLink}}, which is automatically determined using the file extension of + * the {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. + * + * Loaders can be removed from PreloadJS by simply not including them. + * + * Custom loaders installed using {{#crossLink "registerLoader"}}{{/crossLink}} will be prepended to this list + * so that they are checked first. + * @property _availableLoaders + * @type {Array} + * @private + * @since 0.6.0 + */ + this._availableLoaders = [ + createjs.FontLoader, + createjs.ImageLoader, + createjs.JavaScriptLoader, + createjs.CSSLoader, + createjs.JSONLoader, + createjs.JSONPLoader, + createjs.SoundLoader, + createjs.ManifestLoader, + createjs.SpriteSheetLoader, + createjs.XMLLoader, + createjs.SVGLoader, + createjs.BinaryLoader, + createjs.VideoLoader, + createjs.TextLoader + ]; + + /** + * The number of built in loaders, so they can't be removed by {{#crossLink "unregisterLoader"}}{{/crossLink}. + * @property _defaultLoaderLength + * @type {Number} + * @private + * @since 0.6.0 + */ + this._defaultLoaderLength = this._availableLoaders.length; + + this.init(preferXHR, basePath, crossOrigin); + } + + var p = createjs.extend(LoadQueue, createjs.AbstractLoader); + var s = LoadQueue; + + // 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) {} + + /** + * An internal initialization method, which is used for initial set up, but also to reset the LoadQueue. + * @method init + * @param preferXHR + * @param basePath + * @param crossOrigin + * @private + */ + p.init = function (preferXHR, basePath, crossOrigin) { + + // public properties + + /** + * Try and use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR + * loading depending on the requirements for a media type. For example, HTML audio can not be loaded with XHR, + * and plain text can not be loaded with tags, so it will default the the correct type instead of using the + * user-defined type. + * @type {Boolean} + * @default true + * @since 0.6.0 + */ + this.preferXHR = true; //TODO: Get/Set + this._preferXHR = true; + this.setPreferXHR(preferXHR); + + // protected properties + /** + * Whether the queue is currently paused or not. + * @property _paused + * @type {boolean} + * @private + */ + this._paused = false; + + /** + * A path that will be prepended on to the item's {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. The + * `_basePath` property will only be used if an item's source is relative, and does not include a protocol such + * as `http://`, or a relative path such as `../`. + * @property _basePath + * @type {String} + * @private + * @since 0.3.1 + */ + this._basePath = basePath; + + /** + * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded + * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by + * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues, + * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are "" + * and "Anonymous". + * @property _crossOrigin + * @type {String} + * @default "" + * @private + * @since 0.4.1 + */ + this._crossOrigin = crossOrigin; + + /** + * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first + * file is requested. + * @property _loadStartWasDispatched + * @type {Boolean} + * @default false + * @private + */ + this._loadStartWasDispatched = false; + + /** + * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when + * using a script tag to do preloading. + * @property _currentlyLoadingScript + * @type {Boolean} + * @private + */ + this._currentlyLoadingScript = null; + + /** + * An array containing the currently downloading files. + * @property _currentLoads + * @type {Array} + * @private + */ + this._currentLoads = []; + + /** + * An array containing the queued items that have not yet started downloading. + * @property _loadQueue + * @type {Array} + * @private + */ + this._loadQueue = []; + + /** + * An array containing downloads that have not completed, so that the LoadQueue can be properly reset. + * @property _loadQueueBackup + * @type {Array} + * @private + */ + this._loadQueueBackup = []; + + /** + * An object hash of items that have finished downloading, indexed by the {{#crossLink "LoadItem"}}{{/crossLink}} + * id. + * @property _loadItemsById + * @type {Object} + * @private + */ + this._loadItemsById = {}; + + /** + * An object hash of items that have finished downloading, indexed by {{#crossLink "LoadItem"}}{{/crossLink}} + * source. + * @property _loadItemsBySrc + * @type {Object} + * @private + */ + this._loadItemsBySrc = {}; + + /** + * An object hash of loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}. + * @property _loadedResults + * @type {Object} + * @private + */ + this._loadedResults = {}; + + /** + * An object hash of un-parsed loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}. + * @property _loadedRawResults + * @type {Object} + * @private + */ + this._loadedRawResults = {}; + + /** + * The number of items that have been requested. This helps manage an overall progress without knowing how large + * the files are before they are downloaded. This does not include items inside of loaders such as the + * {{#crossLink "ManifestLoader"}}{{/crossLink}}. + * @property _numItems + * @type {Number} + * @default 0 + * @private + */ + this._numItems = 0; + + /** + * The number of items that have completed loaded. This helps manage an overall progress without knowing how large + * the files are before they are downloaded. + * @property _numItemsLoaded + * @type {Number} + * @default 0 + * @private + */ + this._numItemsLoaded = 0; + + /** + * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right + * order. + * @property _scriptOrder + * @type {Array} + * @private + */ + this._scriptOrder = []; + + /** + * A list of scripts that have been loaded. Items are added to this list as null when they are + * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true + * once they are complete and have been dispatched. + * @property _loadedScripts + * @type {Array} + * @private + */ + this._loadedScripts = []; + + /** + * The last progress amount. This is used to suppress duplicate progress events. + * @property _lastProgress + * @type {Number} + * @private + * @since 0.6.0 + */ + this._lastProgress = NaN; + + }; + +// static properties + +// events + /** + * This event is fired when an individual file has loaded, and been processed. + * @event fileload + * @param {Object} target The object that dispatched the event. + * @param {String} type The event type. + * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} + * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the + * object will contain that value as a `src` property. + * @param {Object} result The HTML tag or parsed result of the loaded item. + * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted + * to a usable object. + * @since 0.3.0 + */ + + /** + * This {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when an an individual file's progress changes. + * @event fileprogress + * @since 0.3.0 + */ + + /** + * This event is fired when an individual file starts to load. + * @event filestart + * @param {Object} target The object that dispatched the event. + * @param {String} type The event type. + * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} + * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the + * object will contain that value as a property. + */ + + /** + * Although it extends {{#crossLink "AbstractLoader"}}{{/crossLink}}, the `initialize` event is never fired from + * a LoadQueue instance. + * @event initialize + * @private + */ + +// public methods + /** + * Register a custom loaders class. New loaders are given precedence over loaders added earlier and default loaders. + * It is recommended that loaders extend {{#crossLink "AbstractLoader"}}{{/crossLink}}. Loaders can only be added + * once, and will be prepended to the list of available loaders. + * @method registerLoader + * @param {Function|AbstractLoader} loader The AbstractLoader class to add. + * @since 0.6.0 + */ + p.registerLoader = function (loader) { + if (!loader || !loader.canLoadItem) { + throw new Error("loader is of an incorrect type."); + } else if (this._availableLoaders.indexOf(loader) != -1) { + throw new Error("loader already exists."); //LM: Maybe just silently fail here + } + + this._availableLoaders.unshift(loader); + }; + + /** + * Remove a custom loader added using {{#crossLink "registerLoader"}}{{/crossLink}}. Only custom loaders can be + * unregistered, the default loaders will always be available. + * @method unregisterLoader + * @param {Function|AbstractLoader} loader The AbstractLoader class to remove + */ + p.unregisterLoader = function (loader) { + var idx = this._availableLoaders.indexOf(loader); + if (idx != -1 && idx < this._defaultLoaderLength - 1) { + this._availableLoaders.splice(idx, 1); + } + }; + + /** + * Change the {{#crossLink "preferXHR:property"}}{{/crossLink}} value. Note that if this is set to `true`, it may + * fail, or be ignored depending on the browser's capabilities and the load type. + * @method setPreferXHR + * @param {Boolean} value + * @returns {Boolean} The value of {{#crossLink "preferXHR"}}{{/crossLink}} that was successfully set. + * @since 0.6.0 + */ + p.setPreferXHR = function (value) { + // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it. + //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR. + this.preferXHR = (value != false && window.XMLHttpRequest != null); + return this.preferXHR; + }; + + /** + * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded + * content, and allows the queue to be used again. + * @method removeAll + * @since 0.3.0 + */ + p.removeAll = function () { + this.remove(); + }; + + /** + * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed. + * This also removes internal references to loaded item(s). + * + *

    Example

    + * + * queue.loadManifest([ + * {src:"test.png", id:"png"}, + * {src:"test.jpg", id:"jpg"}, + * {src:"test.mp3", id:"mp3"} + * ]); + * queue.remove("png"); // Single item by ID + * queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src. + * queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src. + * + * @method remove + * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of + * items, or multiple items as arguments. + * @since 0.3.0 + */ + p.remove = function (idsOrUrls) { + var args = null; + + if (idsOrUrls && !Array.isArray(idsOrUrls)) { + args = [idsOrUrls]; + } else if (idsOrUrls) { + args = idsOrUrls; + } else if (arguments.length > 0) { + return; + } + + var itemsWereRemoved = false; + + // Destroy everything + if (!args) { + this.close(); + for (var n in this._loadItemsById) { + this._disposeItem(this._loadItemsById[n]); + } + this.init(this.preferXHR, this._basePath); + + // Remove specific items + } else { + while (args.length) { + var item = args.pop(); + var r = this.getResult(item); + + //Remove from the main load Queue + for (i = this._loadQueue.length - 1; i >= 0; i--) { + loadItem = this._loadQueue[i].getItem(); + if (loadItem.id == item || loadItem.src == item) { + this._loadQueue.splice(i, 1)[0].cancel(); + break; + } + } + + //Remove from the backup queue + for (i = this._loadQueueBackup.length - 1; i >= 0; i--) { + loadItem = this._loadQueueBackup[i].getItem(); + if (loadItem.id == item || loadItem.src == item) { + this._loadQueueBackup.splice(i, 1)[0].cancel(); + break; + } + } + + if (r) { + this._disposeItem(this.getItem(item)); + } else { + for (var i = this._currentLoads.length - 1; i >= 0; i--) { + var loadItem = this._currentLoads[i].getItem(); + if (loadItem.id == item || loadItem.src == item) { + this._currentLoads.splice(i, 1)[0].cancel(); + itemsWereRemoved = true; + break; + } + } + } + } + + // If this was called during a load, try to load the next item. + if (itemsWereRemoved) { + this._loadNext(); + } + } + }; + + /** + * Stops all open loads, destroys any loaded items, and resets the queue, so all items can + * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the + * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or + * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method. + * @method reset + * @since 0.3.0 + */ + p.reset = function () { + this.close(); + for (var n in this._loadItemsById) { + this._disposeItem(this._loadItemsById[n]); + } + + //Reset the queue to its start state + var a = []; + for (var i = 0, l = this._loadQueueBackup.length; i < l; i++) { + a.push(this._loadQueueBackup[i].getItem()); + } + + this.loadManifest(a, false); + }; + + /** + * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc). + * Currently, only one plugin can exist per type/extension. + * + * When a plugin is installed, a getPreloadHandlers() method will be called on it. For more information + * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the + * {{#crossLink "SamplePlugin"}}{{/crossLink}} class. + * + * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned + * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its + * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when + * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these + * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}} + * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}. + * + * @method installPlugin + * @param {Function} plugin The plugin class to install. + */ + p.installPlugin = function (plugin) { + if (plugin == null) { + return; + } + + if (plugin.getPreloadHandlers != null) { + this._plugins.push(plugin); + var map = plugin.getPreloadHandlers(); + map.scope = plugin; + + if (map.types != null) { + for (var i = 0, l = map.types.length; i < l; i++) { + this._typeCallbacks[map.types[i]] = map; + } + } + + if (map.extensions != null) { + for (i = 0, l = map.extensions.length; i < l; i++) { + this._extensionCallbacks[map.extensions[i]] = map; + } + } + } + }; + + /** + * Set the maximum number of concurrent connections. Note that browsers and servers may have a built-in maximum + * number of open connections, so any additional connections may remain in a pending state until the browser + * opens the connection. When loading scripts using tags, and when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}} + * is `true`, only one script is loaded at a time due to browser limitations. + * + *

    Example

    + * + * var queue = new createjs.LoadQueue(); + * queue.setMaxConnections(10); // Allow 10 concurrent loads + * + * @method setMaxConnections + * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue + * is open at any time. + */ + p.setMaxConnections = function (value) { + this._maxConnections = value; + if (!this._paused && this._loadQueue.length > 0) { + this._loadNext(); + } + }; + + /** + * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} + * method. + * + * Files are always appended to the current queue, so this method can be used multiple times to add files. + * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method. + * @method loadFile + * @param {LoadItem|Object|String} file The file object or path to load. A file can be either + *
      + *
    • A {{#crossLink "LoadItem"}}{{/crossLink}} instance
    • + *
    • An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
    • + *
    • OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}} + * in the background.
    • + *
    + * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default + * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is + * `true`, the queue will resume automatically. + * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the + * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}}, + * its files will NOT use the basePath parameter. The basePath parameter is deprecated. + * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue + * constructor, or a `path` property in a manifest definition. + */ + p.loadFile = function (file, loadNow, basePath) { + if (file == null) { + var event = new createjs.ErrorEvent("PRELOAD_NO_FILE"); + this._sendError(event); + return; + } + this._addItem(file, null, basePath); + + if (loadNow !== false) { + this.setPaused(false); + } else { + this.setPaused(true); + } + }; + + /** + * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method. + * The files in the manifest are requested in the same order, but may complete in a different order if the max + * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load + * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is + * default). + * + * Files are always appended to the current queue, so this method can be used multiple times to add files. + * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method. + * @method loadManifest + * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of + * manifests: + *
      + *
    1. A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property, + * which defines the list of files to load, and can optionally contain a "path" property, which will be + * prepended to each file in the list.
    2. + *
    3. An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP + * file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load, + * and can optionally contain a "path" property, which will be prepended to each file in the list.
    4. + *
    5. An object which contains a "manifest" property, which defines the list of files to load, and can + * optionally contain a "path" property, which will be prepended to each file in the list.
    6. + *
    7. An Array of files to load.
    8. + *
    + * + * Each "file" in a manifest can be either: + *
      + *
    • A {{#crossLink "LoadItem"}}{{/crossLink}} instance
    • + *
    • An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
    • + *
    • OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}} + * in the background.
    • + *
    + * + * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default + * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is + * `true`, the queue will resume automatically. + * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the + * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}}, + * its files will NOT use the basePath parameter. The basePath parameter is deprecated. + * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue + * constructor, or a `path` property in a manifest definition. + */ + p.loadManifest = function (manifest, loadNow, basePath) { + var fileList = null; + var path = null; + + // Array-based list of items + if (Array.isArray(manifest)) { + if (manifest.length == 0) { + var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_EMPTY"); + this._sendError(event); + return; + } + fileList = manifest; + + // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded. + } else if (typeof(manifest) === "string") { + fileList = [ + { + src: manifest, + type: s.MANIFEST + } + ]; + + } else if (typeof(manifest) == "object") { + + // An object that defines a manifest path + if (manifest.src !== undefined) { + if (manifest.type == null) { + manifest.type = s.MANIFEST; + } else if (manifest.type != s.MANIFEST) { + var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_TYPE"); + this._sendError(event); + } + fileList = [manifest]; + + // An object that defines a manifest + } else if (manifest.manifest !== undefined) { + fileList = manifest.manifest; + path = manifest.path; + } + + // Unsupported. This will throw an error. + } else { + var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_NULL"); + this._sendError(event); + return; + } + + for (var i = 0, l = fileList.length; i < l; i++) { + this._addItem(fileList[i], path, basePath); + } + + if (loadNow !== false) { + this.setPaused(false); + } else { + this.setPaused(true); + } + + }; + + /** + * Start a LoadQueue that was created, but not automatically started. + * @method load + */ + p.load = function () { + this.setPaused(false); + }; + + /** + * Look up a {{#crossLink "LoadItem"}}{{/crossLink}} using either the "id" or "src" that was specified when loading it. Note that if no "id" was + * supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The + * `basePath` will not be part of the ID. + * @method getItem + * @param {String} value The id or src of the load item. + * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} + * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} + * event as the `item` parameter. + */ + p.getItem = function (value) { + return this._loadItemsById[value] || this._loadItemsBySrc[value]; + }; + + /** + * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id" + * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The + * `basePath` will not be part of the ID. + * @method getResult + * @param {String} value The id or src of the load item. + * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content + * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be + * returned instead. + * @return {Object} A result object containing the content that was loaded, such as: + *
      + *
    • An image tag (<image />) for images
    • + *
    • A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML + * DOM.
    • + *
    • A style tag for CSS (<style /> or <link >)
    • + *
    • Raw text for TEXT
    • + *
    • A formatted JavaScript object defined by JSON
    • + *
    • An XML document
    • + *
    • A binary arraybuffer loaded by XHR
    • + *
    • An audio tag (<audio >) for HTML audio. Note that it is recommended to use SoundJS APIs to play + * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method + * which can not be used to play audio back.
    • + *
    + * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item` + * parameter. Note that if a raw result is requested, but not found, the result will be returned instead. + */ + p.getResult = function (value, rawResult) { + var item = this._loadItemsById[value] || this._loadItemsBySrc[value]; + if (item == null) { + return null; + } + var id = item.id; + if (rawResult && this._loadedRawResults[id]) { + return this._loadedRawResults[id]; + } + return this._loadedResults[id]; + }; + + /** + * Generate an list of items loaded by this queue. + * @method getItems + * @param {Boolean} loaded Determines if only items that have been loaded should be returned. If false, in-progress + * and failed load items will also be included. + * @returns {Array} A list of objects that have been loaded. Each item includes the {{#crossLink "LoadItem"}}{{/crossLink}}, + * result, and rawResult. + * @since 0.6.0 + */ + p.getItems = function (loaded) { + var arr = []; + for (var n in this._loadItemsById) { + var item = this._loadItemsById[n]; + var result = this.getResult(n); + if (loaded === true && result == null) { + continue; + } + arr.push({ + item: item, + result: result, + rawResult: this.getResult(n, true) + }); + } + return arr; + }; + + /** + * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not + * be processed when active loads complete. LoadQueues are not paused by default. + * + * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or + * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, a paused queue will be resumed, unless the `loadNow` + * argument is `false`. + * @method setPaused + * @param {Boolean} value Whether the queue should be paused or not. + */ + p.setPaused = function (value) { + this._paused = value; + if (!this._paused) { + this._loadNext(); + } + }; + + /** + * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from + * starting to download. Note that currently any active loads will remain open, and events may be processed. + * + * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead. + * @method close + */ + p.close = function () { + while (this._currentLoads.length) { + this._currentLoads.pop().cancel(); + } + this._scriptOrder.length = 0; + this._loadedScripts.length = 0; + this.loadStartWasDispatched = false; + this._itemCount = 0; + this._lastProgress = NaN; + }; + +// protected methods + /** + * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to + * load the content. The load queue is populated with the loader instance that handles preloading, and not the load + * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}} + * method. + * @method _addItem + * @param {String|Object} value The item to add to the queue. + * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is + * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was + * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after. + * @param {String} [basePath] DeprecatedAn optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} + * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged + * version. + * @private + */ + p._addItem = function (value, path, basePath) { + var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src. + if (item == null) { + return; + } // Sometimes plugins or types should be skipped. + var loader = this._createLoader(item); + if (loader != null) { + if ("plugins" in loader) { + loader.plugins = this._plugins; + } + item._loader = loader; + this._loadQueue.push(loader); + this._loadQueueBackup.push(loader); + + this._numItems++; + this._updateProgress(); + + // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time. + if ((this.maintainScriptOrder + && item.type == createjs.Types.JAVASCRIPT + //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way + ) + || item.maintainOrder === true) { + this._scriptOrder.push(item); + this._loadedScripts.push(null); + } + } + }; + + /** + * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of + * item is determined by browser support, requirements based on the file type, and developer settings. For example, + * XHR is only used for file types that support it in new browsers. + * + * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may + * alter the load item. + * @method _createLoadItem + * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded. + * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will + * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}} + * when it is added. + * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to + * the path argument. + * @return {Object} The loader instance that will be used. + * @private + */ + p._createLoadItem = function (value, path, basePath) { + var item = createjs.LoadItem.create(value); + if (item == null) { + return null; + } + + var bp = ""; // Store the generated basePath + var useBasePath = basePath || this._basePath; + + if (item.src instanceof Object) { + if (!item.type) { + return null; + } // the the src is an object, type is required to pass off to plugin + if (path) { + bp = path; + var pathMatch = createjs.URLUtils.parseURI(path); + // Also append basePath + if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) { + bp = useBasePath + bp; + } + } else if (useBasePath != null) { + bp = useBasePath; + } + } else { + // Determine Extension, etc. + var match = createjs.URLUtils.parseURI(item.src); + if (match.extension) { + item.ext = match.extension; + } + if (item.type == null) { + item.type = createjs.RequestUtils.getTypeByExtension(item.ext); + } + + // Inject path & basePath + var autoId = item.src; + if (!match.absolute && !match.relative) { + if (path) { + bp = path; + var pathMatch = createjs.URLUtils.parseURI(path); + autoId = path + autoId; + // Also append basePath + if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) { + bp = useBasePath + bp; + } + } else if (useBasePath != null) { + bp = useBasePath; + } + } + item.src = bp + item.src; + } + item.path = bp; + + // If there's no id, set one now. + if (item.id === undefined || item.id === null || item.id === "") { + item.id = autoId; + } + + // Give plugins a chance to modify the loadItem: + var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext]; + if (customHandler) { + // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately) + var result = customHandler.callback.call(customHandler.scope, item, this); + + // The plugin will handle the load, or has canceled it. Ignore it. + if (result === false) { + return null; + + // Load as normal: + } else if (result === true) { + // Do Nothing + + // Result is a loader class: + } else if (result != null) { + item._loader = result; + } + + // Update the extension in case the type changed: + match = createjs.URLUtils.parseURI(item.src); + if (match.extension != null) { + item.ext = match.extension; + } + } + + // Store the item for lookup. This also helps clean-up later. + this._loadItemsById[item.id] = item; + this._loadItemsBySrc[item.src] = item; + + if (item.crossOrigin == null) { + item.crossOrigin = this._crossOrigin; + } + + return item; + }; + + /** + * Create a loader for a load item. + * @method _createLoader + * @param {Object} item A formatted load item that can be used to generate a loader. + * @return {AbstractLoader} A loader that can be used to load content. + * @private + */ + p._createLoader = function (item) { + if (item._loader != null) { // A plugin already specified a loader + return item._loader; + } + + // Initially, try and use the provided/supported XHR mode: + var preferXHR = this.preferXHR; + + for (var i = 0; i < this._availableLoaders.length; i++) { + var loader = this._availableLoaders[i]; + if (loader && loader.canLoadItem(item)) { + return new loader(item, preferXHR); + } + } + + // TODO: Log error (requires createjs.log) + return null; + }; + + /** + * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event + * is processed. The queue will "fill up" any empty slots, up to the max connection specified using + * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded + * using tags, which have to be loaded one at a time to maintain load order. + * @method _loadNext + * @private + */ + p._loadNext = function () { + if (this._paused) { + return; + } + + // Only dispatch loadstart event when the first file is loaded. + if (!this._loadStartWasDispatched) { + this._sendLoadStart(); + this._loadStartWasDispatched = true; + } + + // The queue has completed. + if (this._numItems == this._numItemsLoaded) { + this.loaded = true; + this._sendComplete(); + + // Load the next queue, if it has been defined. + if (this.next && this.next.load) { + this.next.load(); + } + } else { + this.loaded = false; + } + + // Must iterate forwards to load in the right order. + for (var i = 0; i < this._loadQueue.length; i++) { + if (this._currentLoads.length >= this._maxConnections) { + break; + } + var loader = this._loadQueue[i]; + + // Determine if we should be only loading one tag-script at a time: + // Note: maintainOrder items don't do anything here because we can hold onto their loaded value + if (!this._canStartLoad(loader)) { + continue; + } + this._loadQueue.splice(i, 1); + i--; + this._loadItem(loader); + } + }; + + /** + * Begin loading an item. Event listeners are not added to the loaders until the load starts. + * @method _loadItem + * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader. + * @private + */ + p._loadItem = function (loader) { + loader.on("fileload", this._handleFileLoad, this); + loader.on("progress", this._handleProgress, this); + loader.on("complete", this._handleFileComplete, this); + loader.on("error", this._handleError, this); + loader.on("fileerror", this._handleFileError, this); + this._currentLoads.push(loader); + this._sendFileStart(loader.getItem()); + loader.load(); + }; + + /** + * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}} + * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}} + * events. + * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader. + * @private + * @since 0.6.0 + */ + p._handleFileLoad = function (event) { + event.target = null; + this.dispatchEvent(event); + }; + + /** + * The callback that is fired when a loader encounters an error from an internal file load operation. This enables + * loaders like M + * @param event + * @private + */ + p._handleFileError = function (event) { + var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, event.item); + this._sendError(newEvent); + }; + + /** + * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} + * is set to `true`. + * @method _handleError + * @param {ErrorEvent} event The error event, containing relevant error information. + * @private + */ + p._handleError = function (event) { + var loader = event.target; + this._numItemsLoaded++; + + this._finishOrderedItem(loader, true); + this._updateProgress(); + + var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem()); + // TODO: Propagate actual error message. + + this._sendError(newEvent); + + if (!this.stopOnError) { + this._removeLoadItem(loader); + this._cleanLoadItem(loader); + this._loadNext(); + } else { + this.setPaused(true); + } + }; + + /** + * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and + * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML, + * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. + * @method _handleFileComplete + * @param {Event} event The event object from the loader. + * @private + */ + p._handleFileComplete = function (event) { + var loader = event.target; + var item = loader.getItem(); + + var result = loader.getResult(); + this._loadedResults[item.id] = result; + var rawResult = loader.getResult(true); + if (rawResult != null && rawResult !== result) { + this._loadedRawResults[item.id] = rawResult; + } + + this._saveLoadedItems(loader); + + // Remove the load item + this._removeLoadItem(loader); + + if (!this._finishOrderedItem(loader)) { + // The item was NOT managed, so process it now + this._processFinishedLoad(item, loader); + } + + // Clean up the load item + this._cleanLoadItem(loader); + }; + + /** + * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}). + * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the + * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}} + * methods. + * @method _saveLoadedItems + * @param {AbstractLoader} loader + * @protected + * @since 0.6.0 + */ + p._saveLoadedItems = function (loader) { + // TODO: Not sure how to handle this. Would be nice to expose the items. + // Loaders may load sub-items. This adds them to this queue + var list = loader.getLoadedItems(); + if (list === null) { + return; + } + + for (var i = 0; i < list.length; i++) { + var item = list[i].item; + + // Store item lookups + this._loadItemsBySrc[item.src] = item; + this._loadItemsById[item.id] = item; + + // Store loaded content + this._loadedResults[item.id] = list[i].result; + this._loadedRawResults[item.id] = list[i].rawResult; + } + }; + + /** + * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if + * so, trigger prior items to trigger as well. + * @method _finishOrderedItem + * @param {AbstractLoader} loader + * @param {Boolean} loadFailed + * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate + * behaviour if it is. + * @private + */ + p._finishOrderedItem = function (loader, loadFailed) { + var item = loader.getItem(); + + if ((this.maintainScriptOrder && item.type == createjs.Types.JAVASCRIPT) + || item.maintainOrder) { + + //TODO: Evaluate removal of the _currentlyLoadingScript + if (loader instanceof createjs.JavaScriptLoader) { + this._currentlyLoadingScript = false; + } + + var index = createjs.indexOf(this._scriptOrder, item); + if (index == -1) { + return false; + } // This loader no longer exists + this._loadedScripts[index] = (loadFailed === true) ? true : item; + + this._checkScriptLoadOrder(); + return true; + } + + return false; + }; + + /** + * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the + * order they were added, but with a "null" value. When they are completed, the value is set to the load item, + * and then when they are processed and dispatched, the value is set to `true`. This method simply + * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are + * dispatched. + * @method _checkScriptLoadOrder + * @private + */ + p._checkScriptLoadOrder = function () { + var l = this._loadedScripts.length; + + for (var i = 0; i < l; i++) { + var item = this._loadedScripts[i]; + if (item === null) { + break; + } // This is still loading. Do not process further. + if (item === true) { + continue; + } // This has completed, and been processed. Move on. + + var loadItem = this._loadedResults[item.id]; + if (item.type == createjs.Types.JAVASCRIPT) { + // Append script tags to the head automatically. + createjs.DomUtils.appendToHead(loadItem); + } + + var loader = item._loader; + this._processFinishedLoad(item, loader); + this._loadedScripts[i] = true; + } + }; + + /** + * A file has completed loading, and the LoadQueue can move on. This triggers the complete event, and kick-starts + * the next item. + * @method _processFinishedLoad + * @param {LoadItem|Object} item + * @param {AbstractLoader} loader + * @protected + */ + p._processFinishedLoad = function (item, loader) { + this._numItemsLoaded++; + + // Since LoadQueue needs maintain order, we can't append scripts in the loader. + // So we do it here instead. Or in _checkScriptLoadOrder(); + if (!this.maintainScriptOrder && item.type == createjs.Types.JAVASCRIPT) { + var tag = loader.getTag(); + createjs.DomUtils.appendToHead(tag); + } + + this._updateProgress(); + this._sendFileComplete(item, loader); + this._loadNext(); + }; + + /** + * Ensure items with `maintainOrder=true` that are before the specified item have loaded. This only applies to + * JavaScript items that are being loaded with a TagLoader, since they have to be loaded and completed before + * the script can even be started, since it exist in the DOM while loading. + * @method _canStartLoad + * @param {AbstractLoader} loader The loader for the item + * @return {Boolean} Whether the item can start a load or not. + * @private + */ + p._canStartLoad = function (loader) { + if (!this.maintainScriptOrder || loader.preferXHR) { + return true; + } + var item = loader.getItem(); + if (item.type != createjs.Types.JAVASCRIPT) { + return true; + } + if (this._currentlyLoadingScript) { + return false; + } + + var index = this._scriptOrder.indexOf(item); + var i = 0; + while (i < index) { + var checkItem = this._loadedScripts[i]; + if (checkItem == null) { + return false; + } + i++; + } + this._currentlyLoadingScript = true; + return true; + }; + + /** + * A load item is completed or was canceled, and needs to be removed from the LoadQueue. + * @method _removeLoadItem + * @param {AbstractLoader} loader A loader instance to remove. + * @private + */ + p._removeLoadItem = function (loader) { + var l = this._currentLoads.length; + for (var i = 0; i < l; i++) { + if (this._currentLoads[i] == loader) { + this._currentLoads.splice(i, 1); + break; + } + } + }; + + /** + * Remove unneeded references from a loader. + * + * @param loader + * @private + */ + p._cleanLoadItem = function(loader) { + var item = loader.getItem(); + if (item) { + delete item._loader; + } + } + + /** + * An item has dispatched progress. Propagate that progress, and update the LoadQueue's overall progress. + * @method _handleProgress + * @param {ProgressEvent} event The progress event from the item. + * @private + */ + p._handleProgress = function (event) { + var loader = event.target; + this._sendFileProgress(loader.getItem(), loader.progress); + this._updateProgress(); + }; + + /** + * Overall progress has changed, so determine the new progress amount and dispatch it. This changes any time an + * item dispatches progress or completes. Note that since we don't always know the actual filesize of items before + * they are loaded. In this case, we define a "slot" for each item (1 item in 10 would get 10%), and then append + * loaded progress on top of the already-loaded items. + * + * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be: + *
      + *
    • 5/10 of the items in the queue (50%)
    • + *
    • plus 20% of item 6's slot (2%)
    • + *
    • equals 52%
    • + *
    + * @method _updateProgress + * @private + */ + p._updateProgress = function () { + var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress + var remaining = this._numItems - this._numItemsLoaded; + if (remaining > 0) { + var chunk = 0; + for (var i = 0, l = this._currentLoads.length; i < l; i++) { + chunk += this._currentLoads[i].progress; + } + loaded += (chunk / remaining) * (remaining / this._numItems); + } + + if (this._lastProgress != loaded) { + this._sendProgress(loaded); + this._lastProgress = loaded; + } + }; + + /** + * Clean out item results, to free them from memory. Mainly, the loaded item and results are cleared from internal + * hashes. + * @method _disposeItem + * @param {LoadItem|Object} item The item that was passed in for preloading. + * @private + */ + p._disposeItem = function (item) { + delete this._loadedResults[item.id]; + delete this._loadedRawResults[item.id]; + delete this._loadItemsById[item.id]; + delete this._loadItemsBySrc[item.src]; + }; + + /** + * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}} + * event for details on the event payload. + * @method _sendFileProgress + * @param {LoadItem|Object} item The item that is being loaded. + * @param {Number} progress The amount the item has been loaded (between 0 and 1). + * @protected + */ + p._sendFileProgress = function (item, progress) { + if (this._isCanceled() || this._paused) { + return; + } + if (!this.hasEventListener("fileprogress")) { + return; + } + + //LM: Rework ProgressEvent to support this? + var event = new createjs.Event("fileprogress"); + event.progress = progress; + event.loaded = progress; + event.total = 1; + event.item = item; + + this.dispatchEvent(event); + }; + + /** + * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for + * details on the event payload. + * @method _sendFileComplete + * @param {LoadItemObject} item The item that is being loaded. + * @param {AbstractLoader} loader + * @protected + */ + p._sendFileComplete = function (item, loader) { + if (this._isCanceled() || this._paused) { + return; + } + + var event = new createjs.Event("fileload"); + event.loader = loader; + event.item = item; + event.result = this._loadedResults[item.id]; + event.rawResult = this._loadedRawResults[item.id]; + + // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this. + if (item.completeHandler) { + item.completeHandler(event); + } + + this.hasEventListener("fileload") && this.dispatchEvent(event); + }; + + /** + * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see + * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload. + * @method _sendFileStart + * @param {LoadItem|Object} item The item that is being loaded. + * @protected + */ + p._sendFileStart = function (item) { + var event = new createjs.Event("filestart"); + event.item = item; + this.hasEventListener("filestart") && this.dispatchEvent(event); + }; + + p.toString = function () { + return "[PreloadJS LoadQueue]"; + }; + + createjs.LoadQueue = createjs.promote(LoadQueue, "AbstractLoader"); +}()); + +//############################################################################## +// TextLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for Text files. + * @class TextLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function TextLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, true, createjs.Types.TEXT); + }; + + var p = createjs.extend(TextLoader, createjs.AbstractLoader); + var s = TextLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader loads items that are of type {{#crossLink "Types/TEXT:property"}}{{/crossLink}}, + * but is also the default loader if a file type can not be determined. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.TEXT; + }; + + createjs.TextLoader = createjs.promote(TextLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// BinaryLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for binary files. This is useful for loading web audio, or content that requires an ArrayBuffer. + * @class BinaryLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function BinaryLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, true, createjs.Types.BINARY); + this.on("initialize", this._updateXHR, this); + }; + + var p = createjs.extend(BinaryLoader, createjs.AbstractLoader); + var s = BinaryLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/BINARY:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.BINARY; + }; + + // private methods + /** + * Before the item loads, set the response type to "arraybuffer" + * @property _updateXHR + * @param {Event} event + * @private + */ + p._updateXHR = function (event) { + event.loader.setResponseType("arraybuffer"); + }; + + createjs.BinaryLoader = createjs.promote(BinaryLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// CSSLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for CSS files. + * @class CSSLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @extends AbstractLoader + * @constructor + */ + function CSSLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.CSS); + + // public properties + this.resultFormatter = this._formatResult; + + // protected properties + this._tagSrcAttribute = "href"; + + if (preferXHR) { + this._tag = createjs.Elements.style(); + } else { + this._tag = createjs.Elements.link(); + } + + this._tag.rel = "stylesheet"; + this._tag.type = "text/css"; + }; + + var p = createjs.extend(CSSLoader, createjs.AbstractLoader); + var s = CSSLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/CSS:property"}}{{/crossLink}}. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.CSS; + }; + + // protected methods + /** + * The result formatter for CSS files. + * @method _formatResult + * @param {AbstractLoader} loader + * @returns {HTMLLinkElement|HTMLStyleElement} + * @private + */ + p._formatResult = function (loader) { + if (this._preferXHR) { + var tag = loader.getTag(); + + if (tag.styleSheet) { // IE + tag.styleSheet.cssText = loader.getResult(true); + } else { + var textNode = createjs.Elements.text(loader.getResult(true)); + tag.appendChild(textNode); + } + } else { + tag = this._tag; + } + + createjs.DomUtils.appendToHead(tag); + + return tag; + }; + + createjs.CSSLoader = createjs.promote(CSSLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// FontLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + +// constructor: + /** + * A loader that handles font files, CSS definitions, and CSS paths. FontLoader doesn't actually preload fonts + * themselves, but rather generates CSS definitions, and then tests the size changes on an HTML5 Canvas element. + * + * Note that FontLoader does not support tag-based loading due to the requirement that CSS be read to determine the + * font definitions to test for. + * @class FontLoader + * @param {LoadItem|object|string} loadItem The item to be loaded. + * @extends AbstractLoader + * @constructor + **/ + function FontLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, loadItem.type); + + // private properties: + /** + * A lookup of font faces to load. + * @property _faces + * @protected + * @type Object + **/ + this._faces = {}; + + /** + * A list of font faces currently being "watched". Watched fonts will be tested on a regular interval, and be + * removed from this list when they are complete. + * @oroperty _watched + * @type {Array} + * @protected + */ + this._watched = []; + + /** + * A count of the total font faces to load. + * @property _count + * @type {number} + * @protected + * @default 0 + */ + this._count = 0; + + /** + * The interval for checking if fonts have been loaded. + * @property _watchInterval + * @type {Number} + * @protected + */ + this._watchInterval = null; + + /** + * The timeout for determining if a font can't be loaded. Uses the LoadItem {{#crossLink "LoadImte/timeout:property"}}{{/crossLink}} + * value. + * @property _loadTimeout + * @type {Number} + * @protected + */ + this._loadTimeout = null; + /** + * Determines if generated CSS should be injected into the document. + * @property _injectCSS + * @type {boolean} + * @protected + */ + this._injectCSS = (loadItem.injectCSS === undefined) ? true : loadItem.injectCSS; + + this.dispatchEvent("initialize"); + } + var p = createjs.extend(FontLoader, createjs.AbstractLoader); + + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/FONT: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 + */ + FontLoader.canLoadItem = function (item) { + return item.type == createjs.Types.FONT || item.type == createjs.Types.FONTCSS; + }; + +// static properties: + /** + * Sample text used by the FontLoader to determine if the font has been loaded. The sample text size is compared + * to the loaded font size, and a change indicates that the font has completed. + * @property sampleText + * @type {String} + * @default abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ + * @static + * @private + */ + FontLoader.sampleText = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + /** + * The canvas context used to test the font size. Note that this currently requires an HTML DOM. + * @property _ctx + * @type {CanvasRenderingContext2D} + * @static + * @private + */ + FontLoader._ctx = document.createElement("canvas").getContext("2d"); // TODO: Consider a method to do this like EaselJS Stage has. + + /** + * A list of reference fonts to test. Multiple faces are tested to address the rare case of a loaded font being the + * exact same dimensions as the test font. + * @property _referenceFonts + * @type {Array} + * @default ["serif", "monospace"] + * @private + */ + FontLoader._referenceFonts = ["serif","monospace"]; + + /** + * A regular expression that pulls out possible style values from the font name. + *
      + *
    • This includes font names that include thin, normal, book, regular, medium, black, and heavy (such as + * "Arial Black")
    • + *
    • Weight modifiers including extra, ultra, semi, demi, light, and bold (such as "WorkSans SemiBold")
    • + *
    + * + * Weight descriptions map to font weight values by default using the following (from + * http://www.w3.org/TR/css3-fonts/#font-weight-numeric-values): + *
      + *
    • 100 - Thin
    • + *
    • 200 - Extra Light, Ultra Light
    • + *
    • 300 - Light, Semi Light, Demi Light
    • + *
    • 400 - Normal, Book, Regular
    • + *
    • 500 - Medium
    • + *
    • 600 - Semi Bold, Demi Bold
    • + *
    • 700 - Bold
    • + *
    • 800 - Extra Bold, Ultra Bold
    • + *
    • 900 - Black, Heavy
    • + *
    + * @property WEIGHT_REGEX + * @type {RegExp} + * @static + */ + FontLoader.WEIGHT_REGEX = /[- ._]*(thin|normal|book|regular|medium|black|heavy|[1-9]00|(?:extra|ultra|semi|demi)?[- ._]*(?:light|bold))[- ._]*/ig; + + /** + * A regular expression that pulls out possible style values from the font name. These include "italic" + * and "oblique". + * @property STYLE_REGEX + * @type {RegExp} + * @static + */ + FontLoader.STYLE_REGEX = /[- ._]*(italic|oblique)[- ._]*/ig; + + /** + * A lookup of font types for generating a CSS definition. For example, TTF fonts requires a "truetype" type. + * @property FONT_FORMAT + * @type {Object} + * @static + */ + FontLoader.FONT_FORMAT = {woff2:"woff2", woff:"woff", ttf:"truetype", otf:"truetype"}; + + /** + * A lookup of font weights based on a name. These values are from http://www.w3.org/TR/css3-fonts/#font-weight-numeric-values. + * @property FONT_WEIGHT + * @type {Object} + * @static + */ + FontLoader.FONT_WEIGHT = {thin:100, extralight:200, ultralight:200, light:300, semilight:300, demilight:300, book:"normal", regular:"normal", semibold:600, demibold:600, extrabold:800, ultrabold:800, black:900, heavy:900}; + + /** + * The frequency in milliseconds to check for loaded fonts. + * @property WATCH_DURATION + * @type {number} + * @default 10 + * @static + */ + FontLoader.WATCH_DURATION = 10; +// public methods: + p.load = function() { + if (this.type == createjs.Types.FONTCSS) { + var loaded = this._watchCSS(); + + // If the CSS is not ready, it will create a request, which AbstractLoader can handle. + if (!loaded) { + this.AbstractLoader_load(); + return; + } + + } else if (this._item.src instanceof Array) { + this._watchFontArray(); + } else { + var def = this._defFromSrc(this._item.src); + this._watchFont(def); + this._injectStyleTag(this._cssFromDef(def)); + } + + this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); + + this.dispatchEvent("loadstart"); + }; + + /** + * The font load has timed out. This is called via a setTimeout. + * callback. + * @method _handleTimeout + * @protected + */ + p._handleTimeout = function () { + this._stopWatching(); + this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT")); + }; + + // WatchCSS does the work for us, and provides a modified src. + p._createRequest = function() { + return this._request; + }; + + // Events come from the internal XHR loader. + p.handleEvent = function (event) { + switch (event.type) { + case "complete": + this._rawResult = event.target._response; + this._result = true; + this._parseCSS(this._rawResult); + break; + + case "error": + this._stopWatching(); + this.AbstractLoader_handleEvent(event); + break; + } + }; + +// private methods: + /** + * Determine if the provided CSS is a string definition, CSS HTML element, or a CSS file URI. Depending on the + * format, the CSS will be parsed, or loaded. + * @method _watchCSS + * @returns {boolean} Whether or not the CSS is ready + * @protected + */ + p._watchCSS = function() { + var src = this._item.src; + + // An HTMLElement was passed in. Just use it. + if (src instanceof HTMLStyleElement) { + if (this._injectCSS && !src.parentNode) { (document.head || document.getElementsByTagName('head')[0]).appendChild(src); } + this._injectCSS = false; + src = "\n"+src.textContent; + } + + // A CSS string was passed in. Parse and use it + if (src.search(/\n|\r|@font-face/i) !== -1) { // css string. + this._parseCSS(src); + return true; + } + + // Load a CSS Path. Note that we CAN NOT load it without XHR because we need to read the CSS definition + this._request = new createjs.XHRRequest(this._item); + return false; + }; + + /** + * Parse a CSS string to determine the fonts to load. + * @method _parseCSS + * @param {String} css The CSS string to parse + * @protected + */ + p._parseCSS = function(css) { + var regex = /@font-face\s*\{([^}]+)}/g + while (true) { + var result = regex.exec(css); + if (!result) { break; } + this._watchFont(this._parseFontFace(result[1])); + } + this._injectStyleTag(css); + }; + + /** + * The provided fonts were an array of object or string definitions. Parse them, and inject any that are ready. + * @method _watchFontArray + * @protected + */ + p._watchFontArray = function() { + var arr = this._item.src, css = "", def; + for (var i=arr.length-1; i>=0; i--) { + var o = arr[i]; + if (typeof o === "string") { def = this._defFromSrc(o) } + else { def = this._defFromObj(o); } + this._watchFont(def); + css += this._cssFromDef(def)+"\n"; + } + this._injectStyleTag(css); + }; + + /** + * Inject any style definitions into the document head. This is necessary when the definition is just a string or + * object definition in order for the styles to be applied to the document. If the loaded fonts are already HTML CSS + * elements, they don't need to be appended again. + * @method _injectStyleTag + * @param {String} css The CSS string content to be appended to the + * @protected + */ + p._injectStyleTag = function(css) { + if (!this._injectCSS) { return; } + var head = document.head || document.getElementsByTagName('head')[0]; + var styleTag = document.createElement("style"); + styleTag.type = "text/css"; + if (styleTag.styleSheet){ + styleTag.styleSheet.cssText = css; + } else { + styleTag.appendChild(document.createTextNode(css)); + } + head.appendChild(styleTag); + }; + + /** + * Determine the font face from a CSS definition. + * @method _parseFontFace + * @param {String} str The CSS string definition + * @protected + * @return {String} A modified CSS object containing family name, src, style, and weight + */ + p._parseFontFace = function(str) { + var family = this._getCSSValue(str, "font-family"), src = this._getCSSValue(str, "src"); + if (!family || !src) { return null; } + return this._defFromObj({ + family: family, + src: src, + style: this._getCSSValue(str, "font-style"), + weight: this._getCSSValue(str, "font-weight") + }); + }; + + /** + * Add a font to the list of fonts currently being watched. If the font is already watched or loaded, it won't be + * added again. + * @method _watchFont + * @param {Object} def The font definition + * @protected + */ + p._watchFont = function(def) { + if (!def || this._faces[def.id]) { return; } + this._faces[def.id] = def; + this._watched.push(def); + this._count++; + + this._calculateReferenceSizes(def); + this._startWatching(); + }; + + /** + * Create a interval to check for loaded fonts. Only one interval is used for all fonts. The fonts are checked based + * on the {{#crossLink "FontLoader/WATCH_DURATION:property"}}{{/crossLink}}. + * @method _startWatching + * @protected + */ + p._startWatching = function() { + if (this._watchInterval != null) { return; } + this._watchInterval = setInterval(createjs.proxy(this._watch, this), FontLoader.WATCH_DURATION); + }; + + /** + * Clear the interval used to check fonts. This happens when all fonts are loaded, or an error occurs, such as a + * CSS file error, or a load timeout. + * @method _stopWatching + * @protected + */ + p._stopWatching = function() { + clearInterval(this._watchInterval); + clearTimeout(this._loadTimeout); + this._watchInterval = null; + }; + + /** + * Check all the fonts that have not been loaded. The fonts are drawn to a canvas in memory, and if their font size + * varies from the default text size, then the font is considered loaded. + * + * A {{#crossLink "AbstractLoader/fileload"}}{{/crossLink}} event will be dispatched when each file is loaded, along + * with the font family name as the `item` value. A {{#crossLink "ProgressEvent"}}{{/crossLink}} is dispatched a + * maximum of one time per check when any fonts are loaded, with the {{#crossLink "ProgressEvent/progress:property"}}{{/crossLink}} + * value showing the percentage of fonts that have loaded. + * @method _watch + * @protected + */ + p._watch = function() { + var defs = this._watched, refFonts = FontLoader._referenceFonts, l = defs.length; + for (var i = l - 1; i >= 0; i--) { + var def = defs[i], refs = def.refs; + for (var j = refs.length - 1; j >= 0; j--) { + var w = this._getTextWidth(def.family + "," + refFonts[j], def.weight, def.style); + if (w != refs[j]) { + var event = new createjs.Event("fileload"); + def.type = "font-family"; + event.item = def; + this.dispatchEvent(event); + defs.splice(i, 1); + break; + } + } + } + if (l !== defs.length) { + var event = new createjs.ProgressEvent(this._count-defs.length, this._count); + this.dispatchEvent(event); + } + if (l === 0) { + this._stopWatching(); + this._sendComplete(); + } + }; + + /** + * Determine the default size of the reference fonts used to compare against loaded fonts. + * @method _calculateReferenceSizes + * @param {Object} def The font definition to get the size of. + * @protected + */ + p._calculateReferenceSizes = function(def) { + var refFonts = FontLoader._referenceFonts; + var refs = def.refs = []; + for (var i=0; iwithout requiring CORS. + * JSONP files are loaded as JavaScript, and the "callback" is executed once they are loaded. The callback in the + * JSONP must match the callback passed to the loadItem. + * + *

    Example JSONP

    + * + * callbackName({ + * "name": "value", + * "num": 3, + * "obj": { "bool":true } + * }); + * + *

    Example

    + * + * var loadItem = {id:"json", type:"jsonp", src:"http://server.com/text.json", callback:"callbackName"} + * var queue = new createjs.LoadQueue(); + * queue.on("complete", handleComplete); + * queue.loadItem(loadItem); + * + * function handleComplete(event) } + * var json = queue.getResult("json"); + * console.log(json.obj.bool); // true + * } + * + * JSONP files loaded concurrently require a unique callback. To ensure JSONP files are loaded in order, + * either use the {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} method (set to 1), or set + * {{#crossLink "LoadItem/maintainOrder:property"}}{{/crossLink}} on items with the same callback. + * + * Important note: Some browsers will prevent JSONP from firing the callback if the file was loaded as JSON, and not + * JavaScript. You may have to have your server give you a JavaScript mime-type for this to work. + * + * @class JSONPLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function JSONPLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, false, createjs.Types.JSONP); + this.setTag(createjs.Elements.script()); + this.getTag().type = "text/javascript"; + }; + + var p = createjs.extend(JSONPLoader, createjs.AbstractLoader); + var s = JSONPLoader; + + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/JSONP:property"}}{{/crossLink}}. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.JSONP; + }; + + // public methods + p.cancel = function () { + this.AbstractLoader_cancel(); + this._dispose(); + }; + + /** + * Loads the JSONp file. Because of the unique loading needs of JSONp + * we don't use the AbstractLoader.load() method. + * + * @method load + * + */ + p.load = function () { + if (this._item.callback == null) { + throw new Error('callback is required for loading JSONP requests.'); + } + + // TODO: Look into creating our own iFrame to handle the load + // In the first attempt, FF did not get the result + // result instanceof Object did not work either + // so we would need to clone the result. + if (window[this._item.callback] != null) { + throw new Error( + "JSONP callback '" + + this._item.callback + + "' already exists on window. You need to specify a different callback or re-name the current one."); + } + + window[this._item.callback] = createjs.proxy(this._handleLoad, this); + createjs.DomUtils.appendToBody(this._tag); + + this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); + + // Load the tag + this._tag.src = this._item.src; + }; + + // private methods + /** + * Handle the JSONP callback, which is a public method defined on `window`. + * @method _handleLoad + * @param {Object} data The formatted JSON data. + * @private + */ + p._handleLoad = function (data) { + this._result = this._rawResult = data; + this._sendComplete(); + + this._dispose(); + }; + + /** + * The tag request has not loaded within the time specfied in loadTimeout. + * @method _handleError + * @param {Object} event The XHR error event. + * @private + */ + p._handleTimeout = function () { + this._dispose(); + this.dispatchEvent(new createjs.ErrorEvent("timeout")); + }; + + /** + * Clean up the JSONP load. This clears out the callback and script tag that this loader creates. + * @method _dispose + * @private + */ + p._dispose = function () { + createjs.DomUtils.removeChild(this._tag); + delete window[this._item.callback]; + + clearTimeout(this._loadTimeout); + }; + + createjs.JSONPLoader = createjs.promote(JSONPLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// ManifestLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for JSON manifests. Items inside the manifest are loaded before the loader completes. To load manifests + * using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} as part of the + * {{#crossLink "LoadItem"}}{{/crossLink}}. + * + * The list of files in the manifest must be defined on the top-level JSON object in a `manifest` property. This + * example shows a sample manifest definition, as well as how to to include a sub-manifest. + * + * { + * "path": "assets/", + * "manifest": [ + * "image.png", + * {"src": "image2.png", "id":"image2"}, + * {"src": "sub-manifest.json", "type":"manifest", "callback":"jsonCallback"} + * ] + * } + * + * When a ManifestLoader has completed loading, the parent loader (usually a {{#crossLink "LoadQueue"}}{{/crossLink}}, + * but could also be another ManifestLoader) will inherit all the loaded items, so you can access them directly. + * + * Note that the {{#crossLink "JSONLoader"}}{{/crossLink}} and {{#crossLink "JSONPLoader"}}{{/crossLink}} are + * higher priority loaders, so manifests must set the {{#crossLink "LoadItem"}}{{/crossLink}} + * {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property to {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}}. + * + * Additionally, some browsers require the server to serve a JavaScript mime-type for JSONP, so it may not work in + * some conditions. + * @class ManifestLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function ManifestLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.MANIFEST); + + // Public Properties + /** + * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}, + * used to pass plugins to new LoadQueues that may be created. + * @property _plugins + * @type {Array} + * @private + * @since 0.6.1 + */ + this.plugins = null; + + + // Protected Properties + /** + * An internal {{#crossLink "LoadQueue"}}{{/crossLink}} that loads the contents of the manifest. + * @property _manifestQueue + * @type {LoadQueue} + * @private + */ + this._manifestQueue = null; + }; + + var p = createjs.extend(ManifestLoader, createjs.AbstractLoader); + var s = ManifestLoader; + + // static properties + /** + * The amount of progress that the manifest itself takes up. + * @property MANIFEST_PROGRESS + * @type {number} + * @default 0.25 (25%) + * @private + * @static + */ + s.MANIFEST_PROGRESS = 0.25; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.MANIFEST; + }; + + // public methods + p.load = function () { + this.AbstractLoader_load(); + }; + + // protected methods + p._createRequest = function() { + var callback = this._item.callback; + if (callback != null) { + this._request = new createjs.JSONPLoader(this._item); + } else { + this._request = new createjs.JSONLoader(this._item); + } + }; + + p.handleEvent = function (event) { + switch (event.type) { + case "complete": + this._rawResult = event.target.getResult(true); + this._result = event.target.getResult(); + this._sendProgress(s.MANIFEST_PROGRESS); + this._loadManifest(this._result); + return; + case "progress": + event.loaded *= s.MANIFEST_PROGRESS; + this.progress = event.loaded / event.total; + if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } + this._sendProgress(event); + return; + } + this.AbstractLoader_handleEvent(event); + }; + + p.destroy = function() { + this.AbstractLoader_destroy(); + this._manifestQueue.close(); + }; + + /** + * Create and load the manifest items once the actual manifest has been loaded. + * @method _loadManifest + * @param {Object} json + * @private + */ + p._loadManifest = function (json) { + if (json && json.manifest) { + var queue = this._manifestQueue = new createjs.LoadQueue(this._preferXHR); + queue.on("fileload", this._handleManifestFileLoad, this); + queue.on("progress", this._handleManifestProgress, this); + queue.on("complete", this._handleManifestComplete, this, true); + queue.on("error", this._handleManifestError, this, true); + for(var i = 0, l = this.plugins.length; i < l; i++) { // conserve order of plugins + queue.installPlugin(this.plugins[i]); + } + queue.loadManifest(json); + } else { + this._sendComplete(); + } + }; + + /** + * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed. + * @method _handleManifestFileLoad + * @param {Event} event + * @private + */ + p._handleManifestFileLoad = function (event) { + event.target = null; + this.dispatchEvent(event); + }; + + /** + * The manifest has completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} + * {{#crossLink "Event"}}{{/crossLink}} from the ManifestLoader. + * @method _handleManifestComplete + * @param {Event} event + * @private + */ + p._handleManifestComplete = function (event) { + this._loadedItems = this._manifestQueue.getItems(true); + this._sendComplete(); + }; + + /** + * The manifest has reported progress. + * @method _handleManifestProgress + * @param {ProgressEvent} event + * @private + */ + p._handleManifestProgress = function (event) { + this.progress = event.progress * (1 - s.MANIFEST_PROGRESS) + s.MANIFEST_PROGRESS; + this._sendProgress(this.progress); + }; + + /** + * The manifest has reported an error with one of the files. + * @method _handleManifestError + * @param {ErrorEvent} event + * @private + */ + p._handleManifestError = function (event) { + var newEvent = new createjs.Event("fileerror"); + newEvent.item = event.data; + this.dispatchEvent(newEvent); + }; + + createjs.ManifestLoader = createjs.promote(ManifestLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// SoundLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(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"); + +}()); + +//############################################################################## +// VideoLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for video files. + * @class VideoLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @extends AbstractMediaLoader + * @constructor + */ + function VideoLoader(loadItem, preferXHR) { + this.AbstractMediaLoader_constructor(loadItem, preferXHR, createjs.Types.VIDEO); + + if (createjs.DomUtils.isVideoTag(loadItem) || createjs.DomUtils.isVideoTag(loadItem.src)) { + this.setTag(createjs.DomUtils.isVideoTag(loadItem)?loadItem:loadItem.src); + + // We can't use XHR for a tag that's passed in. + this._preferXHR = false; + } else { + this.setTag(this._createTag()); + } + }; + + var p = createjs.extend(VideoLoader, createjs.AbstractMediaLoader); + var s = VideoLoader; + + /** + * Create a new video tag + * + * @returns {HTMLElement} + * @private + */ + p._createTag = function () { + return createjs.Elements.video(); + }; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/VIDEO:property"}}{{/crossLink}}. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.VIDEO; + }; + + createjs.VideoLoader = createjs.promote(VideoLoader, "AbstractMediaLoader"); + +}()); + +//############################################################################## +// SpriteSheetLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for EaselJS SpriteSheets. Images inside the spritesheet definition are loaded before the loader + * completes. To load SpriteSheets using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} + * as part of the {{#crossLink "LoadItem"}}{{/crossLink}}. Note that the {{#crossLink "JSONLoader"}}{{/crossLink}} + * and {{#crossLink "JSONPLoader"}}{{/crossLink}} are higher priority loaders, so SpriteSheets must + * set the {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property + * to {{#crossLink "Types/SPRITESHEET:property"}}{{/crossLink}}. + * + * The {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/crossOrigin:property"}}{{/crossLink}} as well + * as the {{#crossLink "LoadQueue's"}}{{/crossLink}} `basePath` argument and {{#crossLink "LoadQueue/_preferXHR"}}{{/crossLink}} + * property supplied to the {{#crossLink "LoadQueue"}}{{/crossLink}} are passed on to the sub-manifest that loads + * the SpriteSheet images. + * + * Note that the SpriteSheet JSON does not respect the {{#crossLink "LoadQueue/_preferXHR:property"}}{{/crossLink}} + * property, which should instead be determined by the presence of a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} + * property on the SpriteSheet load item. This is because the JSON loaded will have a different format depending on + * if it is loaded as JSON, so just changing `preferXHR` is not enough to change how it is loaded. + * @class SpriteSheetLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function SpriteSheetLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.SPRITESHEET); + + // protected properties + /** + * An internal queue which loads the SpriteSheet's images. + * @method _manifestQueue + * @type {LoadQueue} + * @private + */ + this._manifestQueue = null; + } + + var p = createjs.extend(SpriteSheetLoader, createjs.AbstractLoader); + var s = SpriteSheetLoader; + + // static properties + /** + * The amount of progress that the manifest itself takes up. + * @property SPRITESHEET_PROGRESS + * @type {number} + * @default 0.25 (25%) + * @private + * @static + */ + s.SPRITESHEET_PROGRESS = 0.25; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/SPRITESHEET:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.SPRITESHEET; + }; + + // public methods + p.destroy = function() { + this.AbstractLoader_destroy(); + this._manifestQueue.close(); + }; + + // protected methods + p._createRequest = function() { + var callback = this._item.callback; + if (callback != null) { + this._request = new createjs.JSONPLoader(this._item); + } else { + this._request = new createjs.JSONLoader(this._item); + } + }; + + p.handleEvent = function (event) { + switch (event.type) { + case "complete": + this._rawResult = event.target.getResult(true); + this._result = event.target.getResult(); + this._sendProgress(s.SPRITESHEET_PROGRESS); + this._loadManifest(this._result); + return; + case "progress": + event.loaded *= s.SPRITESHEET_PROGRESS; + this.progress = event.loaded / event.total; + if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } + this._sendProgress(event); + return; + } + this.AbstractLoader_handleEvent(event); + }; + + /** + * Create and load the images once the SpriteSheet JSON has been loaded. + * @method _loadManifest + * @param {Object} json + * @private + */ + p._loadManifest = function (json) { + if (json && json.images) { + var queue = this._manifestQueue = new createjs.LoadQueue(this._preferXHR, this._item.path, this._item.crossOrigin); + queue.on("complete", this._handleManifestComplete, this, true); + queue.on("fileload", this._handleManifestFileLoad, this); + queue.on("progress", this._handleManifestProgress, this); + queue.on("error", this._handleManifestError, this, true); + queue.loadManifest(json.images); + } + }; + + /** + * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed. + * @method _handleManifestFileLoad + * @param {Event} event + * @private + */ + p._handleManifestFileLoad = function (event) { + var image = event.result; + if (image != null) { + var images = this.getResult().images; + var pos = images.indexOf(event.item.src); + images[pos] = image; + } + }; + + /** + * The images have completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} + * {{#crossLink "Event"}}{{/crossLink}} from the SpriteSheetLoader. + * @method _handleManifestComplete + * @param {Event} event + * @private + */ + p._handleManifestComplete = function (event) { + this._result = new createjs.SpriteSheet(this._result); + this._loadedItems = this._manifestQueue.getItems(true); + this._sendComplete(); + }; + + /** + * The images {{#crossLink "LoadQueue"}}{{/crossLink}} has reported progress. + * @method _handleManifestProgress + * @param {ProgressEvent} event + * @private + */ + p._handleManifestProgress = function (event) { + this.progress = event.progress * (1 - s.SPRITESHEET_PROGRESS) + s.SPRITESHEET_PROGRESS; + this._sendProgress(this.progress); + }; + + /** + * An image has reported an error. + * @method _handleManifestError + * @param {ErrorEvent} event + * @private + */ + p._handleManifestError = function (event) { + var newEvent = new createjs.Event("fileerror"); + newEvent.item = event.data; + this.dispatchEvent(newEvent); + }; + + createjs.SpriteSheetLoader = createjs.promote(SpriteSheetLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// SVGLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for SVG files. + * @class SVGLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @extends AbstractLoader + * @constructor + */ + function SVGLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.SVG); + + // public properties + this.resultFormatter = this._formatResult; + + // protected properties + this._tagSrcAttribute = "data"; + + if (preferXHR) { + this.setTag(createjs.Elements.svg()); + } else { + this.setTag(createjs.Elements.object()); + this.getTag().type = "image/svg+xml"; + } + }; + + var p = createjs.extend(SVGLoader, createjs.AbstractLoader); + var s = SVGLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/SVG:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.SVG; + }; + + // protected methods + /** + * The result formatter for SVG files. + * @method _formatResult + * @param {AbstractLoader} loader + * @returns {Object} + * @private + */ + p._formatResult = function (loader) { + // mime should be image/svg+xml, but Opera requires text/xml + var xml = createjs.DataUtils.parseXML(loader.getResult(true)); + var tag = loader.getTag(); + + if (!this._preferXHR && document.body.contains(tag)) { + document.body.removeChild(tag); + } + + if (xml.documentElement != null) { + var element = xml.documentElement; + // Support loading an SVG from a different domain in ID + if (document.importNode) { + element = document.importNode(element, true); + } + tag.appendChild(element); + return tag; + } else { // For browsers that don't support SVG, just give them the XML. (IE 9-8) + return xml; + } + }; + + createjs.SVGLoader = createjs.promote(SVGLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// XMLLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for CSS files. + * @class XMLLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function XMLLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, true, createjs.Types.XML); + + // public properties + this.resultFormatter = this._formatResult; + }; + + var p = createjs.extend(XMLLoader, createjs.AbstractLoader); + var s = XMLLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/XML: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.XML; + }; + + // protected methods + /** + * The result formatter for XML files. + * @method _formatResult + * @param {AbstractLoader} loader + * @returns {XMLDocument} + * @private + */ + p._formatResult = function (loader) { + return createjs.DataUtils.parseXML(loader.getResult(true)); + }; + + createjs.XMLLoader = createjs.promote(XMLLoader, "AbstractLoader"); + +}()); \ No newline at end of file diff --git a/lib/preloadjs-NEXT.min.js b/lib/preloadjs-NEXT.min.js index bffc83f2..b241a03f 100644 --- a/lib/preloadjs-NEXT.min.js +++ b/lib/preloadjs-NEXT.min.js @@ -2,11 +2,13 @@ * @license PreloadJS * Visit http://createjs.com/ for documentation, updates and examples. * -* Copyright (c) 2011-2013 gskinner.com, inc. +* Copyright (c) 2011-2015 gskinner.com, inc. * * Distributed under the terms of the MIT license. * http://www.opensource.org/licenses/mit-license.html * * This notice shall be included in all copies or substantial portions of the Software. */ -this.createjs=this.createjs||{},function(){"use strict";var a=createjs.PreloadJS=createjs.PreloadJS||{};a.version="NEXT",a.buildDate="Wed, 02 Apr 2014 17:54:19 GMT"}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c){this.initialize(a,b,c)},b=a.prototype;b.type=null,b.target=null,b.currentTarget=null,b.eventPhase=0,b.bubbles=!1,b.cancelable=!1,b.timeStamp=0,b.defaultPrevented=!1,b.propagationStopped=!1,b.immediatePropagationStopped=!1,b.removed=!1,b.initialize=function(a,b,c){this.type=a,this.bubbles=b,this.cancelable=c,this.timeStamp=(new Date).getTime()},b.preventDefault=function(){this.defaultPrevented=!0},b.stopPropagation=function(){this.propagationStopped=!0},b.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},b.remove=function(){this.removed=!0},b.clone=function(){return new a(this.type,this.bubbles,this.cancelable)},b.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){},b=a.prototype;a.initialize=function(a){a.addEventListener=b.addEventListener,a.on=b.on,a.removeEventListener=a.off=b.removeEventListener,a.removeAllEventListeners=b.removeAllEventListeners,a.hasEventListener=b.hasEventListener,a.dispatchEvent=b.dispatchEvent,a._dispatchEvent=b._dispatchEvent,a.willTrigger=b.willTrigger},b._listeners=null,b._captureListeners=null,b.initialize=function(){},b.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},b.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},b.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},b.off=b.removeEventListener,b.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},b.dispatchEvent=function(a,b){if("string"==typeof a){var c=this._listeners;if(!c||!c[a])return!1;a=new createjs.Event(a)}if(a.target=b||this,a.bubbles&&this.parent){for(var d=this,e=[d];d.parent;)e.push(d=d.parent);var f,g=e.length;for(f=g-1;f>=0&&!a.propagationStopped;f--)e[f]._dispatchEvent(a,1+(0==f));for(f=1;g>f&&!a.propagationStopped;f++)e[f]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return a.defaultPrevented},b.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},b.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},b.toString=function(){return"[EventDispatcher]"},b._dispatchEvent=function(a,b){var c,d=1==b?this._captureListeners:this._listeners;if(a&&d){var e=d[a.type];if(!e||!(c=e.length))return;a.currentTarget=this,a.eventPhase=b,a.removed=!1,e=e.slice();for(var f=0;c>f&&!a.immediatePropagationStopped;f++){var g=e[f];g.handleEvent?g.handleEvent(a):g(a),a.removed&&(this.off(a.type,g,1==b),a.removed=!1)}}},createjs.EventDispatcher=a}(),this.createjs=this.createjs||{},function(){"use strict";createjs.indexOf=function(a,b){for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1}}(),this.createjs=this.createjs||{},function(){"use strict";createjs.proxy=function(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){return a.apply(b,Array.prototype.slice.call(arguments,0).concat(c))}}}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(){this.init()};a.prototype=new createjs.EventDispatcher;var b=a.prototype,c=a;c.ABSOLUTE_PATT=/^(?:\w+:)?\/{2}/i,c.RELATIVE_PATT=/^[./]*?\//i,c.EXTENSION_PATT=/\/?[^/]+\.(\w{1,5})$/i,b.loaded=!1,b.canceled=!1,b.progress=0,b._item=null,b.getItem=function(){return this._item},b.init=function(){},b.load=function(){},b.close=function(){},b._sendLoadStart=function(){this._isCanceled()||this.dispatchEvent("loadstart")},b._sendProgress=function(a){if(!this._isCanceled()){var b=null;"number"==typeof a?(this.progress=a,b=new createjs.Event("progress"),b.loaded=this.progress,b.total=1):(b=a,this.progress=a.loaded/a.total,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0)),b.progress=this.progress,this.hasEventListener("progress")&&this.dispatchEvent(b)}},b._sendComplete=function(){this._isCanceled()||this.dispatchEvent("complete")},b._sendError=function(a){!this._isCanceled()&&this.hasEventListener("error")&&(null==a&&(a=new createjs.Event("error")),this.dispatchEvent(a))},b._isCanceled=function(){return null==window.createjs||this.canceled?!0:!1},b._parseURI=function(a){var b={absolute:!1,relative:!1};if(null==a)return b;var d=a.indexOf("?");d>-1&&(a=a.substr(0,d));var e;return c.ABSOLUTE_PATT.test(a)?b.absolute=!0:c.RELATIVE_PATT.test(a)&&(b.relative=!0),(e=a.match(c.EXTENSION_PATT))&&(b.extension=e[1].toLowerCase()),b},b._formatQueryString=function(a,b){if(null==a)throw new Error("You must specify data.");var c=[];for(var d in a)c.push(d+"="+escape(a[d]));return b&&(c=c.concat(b)),c.join("&")},b.buildPath=function(a,b){if(null==b)return a;var c=[],d=a.indexOf("?");if(-1!=d){var e=a.slice(d+1);c=c.concat(e.split("&"))}return-1!=d?a.slice(0,d)+"?"+this._formatQueryString(b,c):a+"?"+this._formatQueryString(b,c)},b._isCrossDomain=function(a){var b=document.createElement("a");b.href=a.src;var c=document.createElement("a");c.href=location.href;var d=""!=b.hostname&&(b.port!=c.port||b.protocol!=c.protocol||b.hostname!=c.hostname);return d},b._isLocal=function(a){var b=document.createElement("a");return b.href=a.src,""==b.hostname&&"file:"==b.protocol},b.toString=function(){return"[PreloadJS AbstractLoader]"},createjs.AbstractLoader=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b,c){this.init(a,b,c)},b=a.prototype=new createjs.AbstractLoader,c=a;c.loadTimeout=8e3,c.LOAD_TIMEOUT=0,c.BINARY="binary",c.CSS="css",c.IMAGE="image",c.JAVASCRIPT="javascript",c.JSON="json",c.JSONP="jsonp",c.MANIFEST="manifest",c.SOUND="sound",c.SVG="svg",c.TEXT="text",c.XML="xml",c.POST="POST",c.GET="GET",b._basePath=null,b._crossOrigin="",b.useXHR=!0,b.stopOnError=!1,b.maintainScriptOrder=!0,b.next=null,b._typeCallbacks=null,b._extensionCallbacks=null,b._loadStartWasDispatched=!1,b._maxConnections=1,b._currentlyLoadingScript=null,b._currentLoads=null,b._loadQueue=null,b._loadQueueBackup=null,b._loadItemsById=null,b._loadItemsBySrc=null,b._loadedResults=null,b._loadedRawResults=null,b._numItems=0,b._numItemsLoaded=0,b._scriptOrder=null,b._loadedScripts=null,b.init=function(a,b,c){this._numItems=this._numItemsLoaded=0,this._paused=!1,this._loadStartWasDispatched=!1,this._currentLoads=[],this._loadQueue=[],this._loadQueueBackup=[],this._scriptOrder=[],this._loadedScripts=[],this._loadItemsById={},this._loadItemsBySrc={},this._loadedResults={},this._loadedRawResults={},this._typeCallbacks={},this._extensionCallbacks={},this._basePath=b,this.setUseXHR(a),this._crossOrigin=c===!0?"Anonymous":c===!1||null==c?"":c},b.setUseXHR=function(a){return this.useXHR=0!=a&&null!=window.XMLHttpRequest,this.useXHR},b.removeAll=function(){this.remove()},b.remove=function(a){var b=null;if(!a||a instanceof Array){if(a)b=a;else if(arguments.length>0)return}else b=[a];var c=!1;if(b){for(;b.length;){var d=b.pop(),e=this.getResult(d);for(f=this._loadQueue.length-1;f>=0;f--)if(g=this._loadQueue[f].getItem(),g.id==d||g.src==d){this._loadQueue.splice(f,1)[0].cancel();break}for(f=this._loadQueueBackup.length-1;f>=0;f--)if(g=this._loadQueueBackup[f].getItem(),g.id==d||g.src==d){this._loadQueueBackup.splice(f,1)[0].cancel();break}if(e)delete this._loadItemsById[e.id],delete this._loadItemsBySrc[e.src],this._disposeItem(e);else for(var f=this._currentLoads.length-1;f>=0;f--){var g=this._currentLoads[f].getItem();if(g.id==d||g.src==d){this._currentLoads.splice(f,1)[0].cancel(),c=!0;break}}}c&&this._loadNext()}else{this.close();for(var h in this._loadItemsById)this._disposeItem(this._loadItemsById[h]);this.init(this.useXHR)}},b.reset=function(){this.close();for(var a in this._loadItemsById)this._disposeItem(this._loadItemsById[a]);for(var b=[],c=0,d=this._loadQueueBackup.length;d>c;c++)b.push(this._loadQueueBackup[c].getItem());this.loadManifest(b,!1)},c.isBinary=function(a){switch(a){case createjs.LoadQueue.IMAGE:case createjs.LoadQueue.BINARY:return!0;default:return!1}},c.isText=function(a){switch(a){case createjs.LoadQueue.TEXT:case createjs.LoadQueue.JSON:case createjs.LoadQueue.MANIFEST:case createjs.LoadQueue.XML:case createjs.LoadQueue.HTML:case createjs.LoadQueue.CSS:case createjs.LoadQueue.SVG:case createjs.LoadQueue.JAVASCRIPT:return!0;default:return!1}},b.installPlugin=function(a){if(null!=a&&null!=a.getPreloadHandlers){var b=a.getPreloadHandlers();if(b.scope=a,null!=b.types)for(var c=0,d=b.types.length;d>c;c++)this._typeCallbacks[b.types[c]]=b;if(null!=b.extensions)for(c=0,d=b.extensions.length;d>c;c++)this._extensionCallbacks[b.extensions[c]]=b}},b.setMaxConnections=function(a){this._maxConnections=a,!this._paused&&this._loadQueue.length>0&&this._loadNext()},b.loadFile=function(a,b,c){if(null==a){var d=new createjs.Event("error");return d.text="PRELOAD_NO_FILE",this._sendError(d),void 0}this._addItem(a,null,c),b!==!1?this.setPaused(!1):this.setPaused(!0)},b.loadManifest=function(a,b,d){var e=null,f=null;if(a instanceof Array){if(0==a.length){var g=new createjs.Event("error");return g.text="PRELOAD_MANIFEST_EMPTY",this._sendError(g),void 0}e=a}else if("string"==typeof a)e=[{src:a,type:c.MANIFEST}];else{if("object"!=typeof a){var g=new createjs.Event("error");return g.text="PRELOAD_MANIFEST_NULL",this._sendError(g),void 0}if(void 0!==a.src){if(null==a.type)a.type=c.MANIFEST;else if(a.type!=c.MANIFEST){var g=new createjs.Event("error");g.text="PRELOAD_MANIFEST_ERROR",this._sendError(g)}e=[a]}else void 0!==a.manifest&&(e=a.manifest,f=a.path)}for(var h=0,i=e.length;i>h;h++)this._addItem(e[h],f,d);b!==!1?this.setPaused(!1):this.setPaused(!0)},b.load=function(){this.setPaused(!1)},b.getItem=function(a){return this._loadItemsById[a]||this._loadItemsBySrc[a]},b.getResult=function(a,b){var c=this._loadItemsById[a]||this._loadItemsBySrc[a];if(null==c)return null;var d=c.id;return b&&this._loadedRawResults[d]?this._loadedRawResults[d]:this._loadedResults[d]},b.setPaused=function(a){this._paused=a,this._paused||this._loadNext()},b.close=function(){for(;this._currentLoads.length;)this._currentLoads.pop().cancel();this._scriptOrder.length=0,this._loadedScripts.length=0,this.loadStartWasDispatched=!1},b._addItem=function(a,b,c){var d=this._createLoadItem(a,b,c);if(null!=d){var e=this._createLoader(d);null!=e&&(d._loader=e,this._loadQueue.push(e),this._loadQueueBackup.push(e),this._numItems++,this._updateProgress(),(this.maintainScriptOrder&&d.type==createjs.LoadQueue.JAVASCRIPT||d.maintainOrder===!0)&&(this._scriptOrder.push(d),this._loadedScripts.push(null)))}},b._createLoadItem=function(a,b,c){var d=null;switch(typeof a){case"string":d={src:a};break;case"object":d=window.HTMLAudioElement&&a instanceof window.HTMLAudioElement?{tag:a,src:d.tag.src,type:createjs.LoadQueue.SOUND}:a;break;default:return null}var e=this._parseURI(d.src);e.extension&&(d.ext=e.extension),null==d.type&&(d.type=this._getTypeByExtension(d.ext));var f="",g=c||this._basePath,h=d.src;if(!e.absolute&&!e.relative)if(b){f=b;var i=this._parseURI(b);h=b+h,null==g||i.absolute||i.relative||(f=g+f)}else null!=g&&(f=g);if(d.src=f+d.src,d.path=f,(d.type==createjs.LoadQueue.JSON||d.type==createjs.LoadQueue.MANIFEST)&&(d._loadAsJSONP=null!=d.callback),d.type==createjs.LoadQueue.JSONP&&null==d.callback)throw new Error("callback is required for loading JSONP requests.");(void 0===d.tag||null===d.tag)&&(d.tag=this._createTag(d)),(void 0===d.id||null===d.id||""===d.id)&&(d.id=h);var j=this._typeCallbacks[d.type]||this._extensionCallbacks[d.ext];if(j){var k=j.callback.call(j.scope,d.src,d.type,d.id,d.data,f,this);if(k===!1)return null;k===!0||(null!=k.src&&(d.src=k.src),null!=k.id&&(d.id=k.id),null!=k.tag&&(d.tag=k.tag),null!=k.completeHandler&&(d.completeHandler=k.completeHandler),k.type&&(d.type=k.type),e=this._parseURI(d.src),null!=e.extension&&(d.ext=e.extension))}return this._loadItemsById[d.id]=d,this._loadItemsBySrc[d.src]=d,d},b._createLoader=function(a){var b=this.useXHR;switch(a.type){case createjs.LoadQueue.JSON:case createjs.LoadQueue.MANIFEST:b=!a._loadAsJSONP;break;case createjs.LoadQueue.XML:case createjs.LoadQueue.TEXT:b=!0;break;case createjs.LoadQueue.SOUND:case createjs.LoadQueue.JSONP:b=!1;break;case null:return null}return b?new createjs.XHRLoader(a,this._crossOrigin):new createjs.TagLoader(a)},b._loadNext=function(){if(!this._paused){this._loadStartWasDispatched||(this._sendLoadStart(),this._loadStartWasDispatched=!0),this._numItems==this._numItemsLoaded?(this.loaded=!0,this._sendComplete(),this.next&&this.next.load&&this.next.load()):this.loaded=!1;for(var a=0;a=this._maxConnections);a++){var b=this._loadQueue[a];this._canStartLoad(b)&&(this._loadQueue.splice(a,1),a--,this._loadItem(b))}}},b._loadItem=function(a){a.on("progress",this._handleProgress,this),a.on("complete",this._handleFileComplete,this),a.on("error",this._handleFileError,this),this._currentLoads.push(a),this._sendFileStart(a.getItem()),a.load()},b._handleFileError=function(a){var b=a.target;this._numItemsLoaded++,this._finishOrderedItem(b,!0),this._updateProgress();var c=new createjs.Event("error");c.text="FILE_LOAD_ERROR",c.item=b.getItem(),this._sendError(c),this.stopOnError||(this._removeLoadItem(b),this._loadNext())},b._handleFileComplete=function(a){var b=a.target,c=b.getItem();this._loadedResults[c.id]=b.getResult(),b instanceof createjs.XHRLoader&&(this._loadedRawResults[c.id]=b.getResult(!0)),this._removeLoadItem(b),this._finishOrderedItem(b)||this._processFinishedLoad(c,b)},b._finishOrderedItem=function(a,b){var c=a.getItem();if(this.maintainScriptOrder&&c.type==createjs.LoadQueue.JAVASCRIPT||c.maintainOrder){a instanceof createjs.TagLoader&&c.type==createjs.LoadQueue.JAVASCRIPT&&(this._currentlyLoadingScript=!1);var d=createjs.indexOf(this._scriptOrder,c);return-1==d?!1:(this._loadedScripts[d]=b===!0?!0:c,this._checkScriptLoadOrder(),!0)}return!1},b._checkScriptLoadOrder=function(){for(var a=this._loadedScripts.length,b=0;a>b;b++){var c=this._loadedScripts[b];if(null===c)break;if(c!==!0){var d=this._loadedResults[c.id];c.type==createjs.LoadQueue.JAVASCRIPT&&(document.body||document.getElementsByTagName("body")[0]).appendChild(d);var e=c._loader;this._processFinishedLoad(c,e),this._loadedScripts[b]=!0}}},b._processFinishedLoad=function(a,b){if(a.type==createjs.LoadQueue.MANIFEST){var c=b.getResult();null!=c&&void 0!==c.manifest&&this.loadManifest(c,!0)}this._numItemsLoaded++,this._updateProgress(),this._sendFileComplete(a,b),this._loadNext()},b._canStartLoad=function(a){if(!this.maintainScriptOrder||a instanceof createjs.XHRLoader)return!0;var b=a.getItem();if(b.type!=createjs.LoadQueue.JAVASCRIPT)return!0;if(this._currentlyLoadingScript)return!1;for(var c=this._scriptOrder.indexOf(b),d=0;c>d;){var e=this._loadedScripts[d];if(null==e)return!1;d++}return this._currentlyLoadingScript=!0,!0},b._removeLoadItem=function(a){var b=a.getItem();delete b._loader,delete b._loadAsJSONP;for(var c=this._currentLoads.length,d=0;c>d;d++)if(this._currentLoads[d]==a){this._currentLoads.splice(d,1);break}},b._handleProgress=function(a){var b=a.target;this._sendFileProgress(b.getItem(),b.progress),this._updateProgress()},b._updateProgress=function(){var a=this._numItemsLoaded/this._numItems,b=this._numItems-this._numItemsLoaded;if(b>0){for(var c=0,d=0,e=this._currentLoads.length;e>d;d++)c+=this._currentLoads[d].progress;a+=c/b*(b/this._numItems)}this._sendProgress(a)},b._disposeItem=function(a){delete this._loadedResults[a.id],delete this._loadedRawResults[a.id],delete this._loadItemsById[a.id],delete this._loadItemsBySrc[a.src]},b._createTag=function(a){var b=null;switch(a.type){case createjs.LoadQueue.IMAGE:return b=document.createElement("img"),""==this._crossOrigin||this._isLocal(a)||(b.crossOrigin=this._crossOrigin),b;case createjs.LoadQueue.SOUND:return b=document.createElement("audio"),b.autoplay=!1,b;case createjs.LoadQueue.JSON:case createjs.LoadQueue.JSONP:case createjs.LoadQueue.JAVASCRIPT:case createjs.LoadQueue.MANIFEST:return b=document.createElement("script"),b.type="text/javascript",b;case createjs.LoadQueue.CSS:return b=this.useXHR?document.createElement("style"):document.createElement("link"),b.rel="stylesheet",b.type="text/css",b;case createjs.LoadQueue.SVG:return this.useXHR?b=document.createElement("svg"):(b=document.createElement("object"),b.type="image/svg+xml"),b}return null},b._getTypeByExtension=function(a){if(null==a)return createjs.LoadQueue.TEXT;switch(a.toLowerCase()){case"jpeg":case"jpg":case"gif":case"png":case"webp":case"bmp":return createjs.LoadQueue.IMAGE;case"ogg":case"mp3":case"wav":return createjs.LoadQueue.SOUND;case"json":return createjs.LoadQueue.JSON;case"xml":return createjs.LoadQueue.XML;case"css":return createjs.LoadQueue.CSS;case"js":return createjs.LoadQueue.JAVASCRIPT;case"svg":return createjs.LoadQueue.SVG;default:return createjs.LoadQueue.TEXT}},b._sendFileProgress=function(a,b){if(this._isCanceled())return this._cleanUp(),void 0;if(this.hasEventListener("fileprogress")){var c=new createjs.Event("fileprogress");c.progress=b,c.loaded=b,c.total=1,c.item=a,this.dispatchEvent(c)}},b._sendFileComplete=function(a,b){if(!this._isCanceled()){var c=new createjs.Event("fileload");c.loader=b,c.item=a,c.result=this._loadedResults[a.id],c.rawResult=this._loadedRawResults[a.id],a.completeHandler&&a.completeHandler(c),this.hasEventListener("fileload")&&this.dispatchEvent(c)}},b._sendFileStart=function(a){var b=new createjs.Event("filestart");b.item=a,this.hasEventListener("filestart")&&this.dispatchEvent(b)},b.toString=function(){return"[PreloadJS LoadQueue]"},createjs.LoadQueue=a;var d=function(){};d.init=function(){var a=navigator.userAgent;d.isFirefox=a.indexOf("Firefox")>-1,d.isOpera=null!=window.opera,d.isChrome=a.indexOf("Chrome")>-1,d.isIOS=a.indexOf("iPod")>-1||a.indexOf("iPhone")>-1||a.indexOf("iPad")>-1},d.init(),createjs.LoadQueue.BrowserDetect=d}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a){this.init(a)},b=a.prototype=new createjs.AbstractLoader;b._loadTimeout=null,b._tagCompleteProxy=null,b._isAudio=!1,b._tag=null,b._jsonResult=null,b.init=function(a){this._item=a,this._tag=a.tag,this._isAudio=window.HTMLAudioElement&&a.tag instanceof window.HTMLAudioElement,this._tagCompleteProxy=createjs.proxy(this._handleLoad,this)},b.getResult=function(){return this._item.type==createjs.LoadQueue.JSONP||this._item.type==createjs.LoadQueue.MANIFEST?this._jsonResult:this._tag},b.cancel=function(){this.canceled=!0,this._clean()},b.load=function(){var a=this._item,b=this._tag;clearTimeout(this._loadTimeout);var c=createjs.LoadQueue.LOAD_TIMEOUT;0==c&&(c=createjs.LoadQueue.loadTimeout),this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),c),this._isAudio&&(b.src=null,b.preload="auto"),b.onerror=createjs.proxy(this._handleError,this),this._isAudio?(b.onstalled=createjs.proxy(this._handleStalled,this),b.addEventListener("canplaythrough",this._tagCompleteProxy,!1)):(b.onload=createjs.proxy(this._handleLoad,this),b.onreadystatechange=createjs.proxy(this._handleReadyStateChange,this));var d=this.buildPath(a.src,a.values);switch(a.type){case createjs.LoadQueue.CSS:b.href=d;break;case createjs.LoadQueue.SVG:b.data=d;break;default:b.src=d}if(a.type==createjs.LoadQueue.JSONP||a.type==createjs.LoadQueue.JSON||a.type==createjs.LoadQueue.MANIFEST){if(null==a.callback)throw new Error("callback is required for loading JSONP requests.");if(null!=window[a.callback])throw new Error('JSONP callback "'+a.callback+'" already exists on window. You need to specify a different callback. Or re-name the current one.');window[a.callback]=createjs.proxy(this._handleJSONPLoad,this)}if(a.type==createjs.LoadQueue.SVG||a.type==createjs.LoadQueue.JSONP||a.type==createjs.LoadQueue.JSON||a.type==createjs.LoadQueue.MANIFEST||a.type==createjs.LoadQueue.JAVASCRIPT||a.type==createjs.LoadQueue.CSS){this._startTagVisibility=b.style.visibility,b.style.visibility="hidden";var e=document.body||document.getElementsByTagName("body")[0];if(null==e){if(a.type==createjs.LoadQueue.SVG)return this._handleSVGError(),void 0;e=document.head||document.getElementsByTagName("head")}e.appendChild(b)}null!=b.load&&b.load()},b._handleSVGError=function(){this._clean();var a=new createjs.Event("error");a.text="SVG_NO_BODY",this._sendError(a)},b._handleJSONPLoad=function(a){this._jsonResult=a},b._handleTimeout=function(){this._clean();var a=new createjs.Event("error");a.text="PRELOAD_TIMEOUT",this._sendError(a)},b._handleStalled=function(){},b._handleError=function(){this._clean();var a=new createjs.Event("error");this._sendError(a)},b._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this.getItem().tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleLoad()},b._handleLoad=function(){if(!this._isCanceled()){var a=this.getItem(),b=a.tag;if(!(this.loaded||this._isAudio&&4!==b.readyState)){switch(this.loaded=!0,a.type){case createjs.LoadQueue.SVG:case createjs.LoadQueue.JSON:case createjs.LoadQueue.JSONP:case createjs.LoadQueue.MANIFEST:case createjs.LoadQueue.CSS:b.style.visibility=this._startTagVisibility,b.parentNode&&b.parentNode.contains(b)&&b.parentNode.removeChild(b)}this._clean(),this._sendComplete()}}},b._clean=function(){clearTimeout(this._loadTimeout);var a=this.getItem(),b=a.tag;null!=b&&(b.onload=null,b.removeEventListener&&b.removeEventListener("canplaythrough",this._tagCompleteProxy,!1),b.onstalled=null,b.onprogress=null,b.onerror=null,null!=b.parentNode&&a.type==createjs.LoadQueue.SVG&&a.type==createjs.LoadQueue.JSON&&a.type==createjs.LoadQueue.MANIFEST&&a.type==createjs.LoadQueue.CSS&&a.type==createjs.LoadQueue.JSONP&&b.parentNode.removeChild(b));var a=this.getItem();(a.type==createjs.LoadQueue.JSONP||a.type==createjs.LoadQueue.MANIFEST)&&(window[a.callback]=null)},b.toString=function(){return"[PreloadJS TagLoader]"},createjs.TagLoader=a}(),this.createjs=this.createjs||{},function(){"use strict";var a=function(a,b){this.init(a,b)},b=a;b.ACTIVEX_VERSIONS=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"];var c=a.prototype=new createjs.AbstractLoader;c._request=null,c._loadTimeout=null,c._xhrLevel=1,c._response=null,c._rawResponse=null,c._crossOrigin="",c.init=function(a,b){this._item=a,this._crossOrigin=b,!this._createXHR(a)},c.getResult=function(a){return a&&this._rawResponse?this._rawResponse:this._response},c.cancel=function(){this.canceled=!0,this._clean(),this._request.abort()},c.load=function(){if(null==this._request)return this._handleError(),void 0;if(this._request.onloadstart=createjs.proxy(this._handleLoadStart,this),this._request.onprogress=createjs.proxy(this._handleProgress,this),this._request.onabort=createjs.proxy(this._handleAbort,this),this._request.onerror=createjs.proxy(this._handleError,this),this._request.ontimeout=createjs.proxy(this._handleTimeout,this),1==this._xhrLevel){var a=createjs.LoadQueue.LOAD_TIMEOUT;if(0==a)a=createjs.LoadQueue.loadTimeout;else try{console.warn("LoadQueue.LOAD_TIMEOUT has been deprecated in favor of LoadQueue.loadTimeout")}catch(b){}this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),a)}this._request.onload=createjs.proxy(this._handleLoad,this),this._request.onreadystatechange=createjs.proxy(this._handleReadyStateChange,this);try{this._item.values&&this._item.method!=createjs.LoadQueue.GET?this._item.method==createjs.LoadQueue.POST&&this._request.send(this._formatQueryString(this._item.values)):this._request.send()}catch(c){var d=new createjs.Event("error");d.error=c,this._sendError(d)}},c.getAllResponseHeaders=function(){return this._request.getAllResponseHeaders instanceof Function?this._request.getAllResponseHeaders():null},c.getResponseHeader=function(a){return this._request.getResponseHeader instanceof Function?this._request.getResponseHeader(a):null},c._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.Event("progress");b.loaded=a.loaded,b.total=a.total,this._sendProgress(b)}},c._handleLoadStart=function(){clearTimeout(this._loadTimeout),this._sendLoadStart()},c._handleAbort=function(){this._clean();var a=new createjs.Event("error");a.text="XHR_ABORTED",this._sendError(a)},c._handleError=function(){this._clean();var a=new createjs.Event("error");this._sendError(a)},c._handleReadyStateChange=function(){4==this._request.readyState&&this._handleLoad()},c._handleLoad=function(){if(!this.loaded){if(this.loaded=!0,!this._checkError())return this._handleError(),void 0;this._response=this._getResponse(),this._clean();var a=this._generateTag();a&&this._sendComplete()}},c._handleTimeout=function(a){this._clean();var b=new createjs.Event("error");b.text="PRELOAD_TIMEOUT",this._sendError(a)},c._checkError=function(){var a=parseInt(this._request.status);switch(a){case 404:case 0:return!1}return!0},c._getResponse=function(){if(null!=this._response)return this._response;if(null!=this._request.response)return this._request.response;try{if(null!=this._request.responseText)return this._request.responseText}catch(a){}try{if(null!=this._request.responseXML)return this._request.responseXML}catch(a){}return null},c._createXHR=function(a){var c=this._isCrossDomain(a),d={},e=null;if(window.XMLHttpRequest)e=new XMLHttpRequest,c&&void 0===e.withCredentials&&window.XDomainRequest&&(e=new XDomainRequest);else{for(var f=0,g=b.ACTIVEX_VERSIONS.length;g>f;f++){b.ACTIVEX_VERSIONS[f];try{e=new ActiveXObject(axVersions);break}catch(h){}}if(null==e)return!1}createjs.LoadQueue.isText(a.type)&&e.overrideMimeType&&e.overrideMimeType("text/plain; charset=utf-8"),this._xhrLevel="string"==typeof e.responseType?2:1;var i=null;if(i=a.method==createjs.LoadQueue.GET?this.buildPath(a.src,a.values):a.src,e.open(a.method||createjs.LoadQueue.GET,i,!0),c&&e instanceof XMLHttpRequest&&1==this._xhrLevel&&(d.Origin=location.origin),a.values&&a.method==createjs.LoadQueue.POST&&(d["Content-Type"]="application/x-www-form-urlencoded"),c||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest"),a.headers)for(var j in a.headers)d[j]=a.headers[j];createjs.LoadQueue.isBinary(a.type)&&(e.responseType="arraybuffer");for(j in d)e.setRequestHeader(j,d[j]);return this._request=e,!0},c._clean=function(){clearTimeout(this._loadTimeout);var a=this._request;a.onloadstart=null,a.onprogress=null,a.onabort=null,a.onerror=null,a.onload=null,a.ontimeout=null,a.onloadend=null,a.onreadystatechange=null},c._generateTag=function(){var a=this._item.type,b=this._item.tag;switch(a){case createjs.LoadQueue.IMAGE:return b.onload=createjs.proxy(this._handleTagReady,this),""!=this._crossOrigin&&(b.crossOrigin="Anonymous"),b.src=this.buildPath(this._item.src,this._item.values),this._rawResponse=this._response,this._response=b,!1;case createjs.LoadQueue.JAVASCRIPT:return b=document.createElement("script"),b.text=this._response,this._rawResponse=this._response,this._response=b,!0;case createjs.LoadQueue.CSS:var c=document.getElementsByTagName("head")[0];if(c.appendChild(b),b.styleSheet)b.styleSheet.cssText=this._response;else{var d=document.createTextNode(this._response);b.appendChild(d)}return this._rawResponse=this._response,this._response=b,!0;case createjs.LoadQueue.XML:var e=this._parseXML(this._response,"text/xml");return this._rawResponse=this._response,this._response=e,!0;case createjs.LoadQueue.SVG:var e=this._parseXML(this._response,"image/svg+xml");return this._rawResponse=this._response,null!=e.documentElement?(b.appendChild(e.documentElement),this._response=b):this._response=e,!0;case createjs.LoadQueue.JSON:case createjs.LoadQueue.MANIFEST:var f={};try{f=JSON.parse(this._response)}catch(g){f=g}return this._rawResponse=this._response,this._response=f,!0}return!0},c._parseXML=function(a,b){var c=null;try{if(window.DOMParser){var d=new DOMParser;c=d.parseFromString(a,b)}else c=new ActiveXObject("Microsoft.XMLDOM"),c.async=!1,c.loadXML(a)}catch(e){}return c},c._handleTagReady=function(){var a=this._item.tag;a&&(a.onload=null),this._sendComplete()},c.toString=function(){return"[PreloadJS XHRLoader]"},createjs.XHRLoader=a}(),"object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(a){return 10>a?"0"+a:a}function quote(a){return escapable.lastIndex=0,escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return"string"==typeof b?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function str(a,b){var c,d,e,f,g,h=gap,i=b[a];switch(i&&"object"==typeof i&&"function"==typeof i.toJSON&&(i=i.toJSON(a)),"function"==typeof rep&&(i=rep.call(b,a,i)),typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";if(gap+=indent,g=[],"[object Array]"===Object.prototype.toString.apply(i)){for(f=i.length,c=0;f>c;c+=1)g[c]=str(c,i)||"null";return e=0===g.length?"[]":gap?"[\n"+gap+g.join(",\n"+gap)+"\n"+h+"]":"["+g.join(",")+"]",gap=h,e}if(rep&&"object"==typeof rep)for(f=rep.length,c=0;f>c;c+=1)"string"==typeof rep[c]&&(d=rep[c],e=str(d,i),e&&g.push(quote(d)+(gap?": ":":")+e));else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&g.push(quote(d)+(gap?": ":":")+e));return e=0===g.length?"{}":gap?"{\n"+gap+g.join(",\n"+gap)+"\n"+h+"}":"{"+g.join(",")+"}",gap=h,e}}"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;"function"!=typeof JSON.stringify&&(JSON.stringify=function(a,b,c){var d;if(gap="",indent="","number"==typeof c)for(d=0;c>d;d+=1)indent+=" ";else"string"==typeof c&&(indent=c);if(rep=b,b&&"function"!=typeof b&&("object"!=typeof b||"number"!=typeof b.length))throw new Error("JSON.stringify");return str("",{"":a})}),"function"!=typeof JSON.parse&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&"object"==typeof e)for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),void 0!==d?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;if(text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})),/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(); \ No newline at end of file +this.createjs=this.createjs||{},function(){"use strict";var a=createjs.PreloadJS=createjs.PreloadJS||{};a.version="NEXT",a.buildDate="Thu, 14 Sep 2017 22:19:45 GMT"}(),this.createjs=this.createjs||{},createjs.extend=function(a,b){"use strict";function c(){this.constructor=a}return c.prototype=b.prototype,a.prototype=new c},this.createjs=this.createjs||{},createjs.promote=function(a,b){"use strict";var c=a.prototype,d=Object.getPrototypeOf&&Object.getPrototypeOf(c)||c.__proto__;if(d){c[(b+="_")+"constructor"]=d.constructor;for(var e in d)c.hasOwnProperty(e)&&"function"==typeof d[e]&&(c[b+e]=d[e])}return a},this.createjs=this.createjs||{},createjs.deprecate=function(a,b){"use strict";return function(){var c="Deprecated property or method '"+b+"'. See docs for info.";return console&&(console.warn?console.warn(c):console.log(c)),a&&a.apply(this,arguments)}},this.createjs=this.createjs||{},function(){"use strict";createjs.proxy=function(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){return a.apply(b,Array.prototype.slice.call(arguments,0).concat(c))}}}(),this.createjs=this.createjs||{},createjs.indexOf=function(a,b){"use strict";for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1},this.createjs=this.createjs||{},function(){"use strict";function Event(a,b,c){this.type=a,this.target=null,this.currentTarget=null,this.eventPhase=0,this.bubbles=!!b,this.cancelable=!!c,this.timeStamp=(new Date).getTime(),this.defaultPrevented=!1,this.propagationStopped=!1,this.immediatePropagationStopped=!1,this.removed=!1}var a=Event.prototype;a.preventDefault=function(){this.defaultPrevented=this.cancelable&&!0},a.stopPropagation=function(){this.propagationStopped=!0},a.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},a.remove=function(){this.removed=!0},a.clone=function(){return new Event(this.type,this.bubbles,this.cancelable)},a.set=function(a){for(var b in a)this[b]=a[b];return this},a.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=Event}(),this.createjs=this.createjs||{},function(){"use strict";function ErrorEvent(a,b,c){this.Event_constructor("error"),this.title=a,this.message=b,this.data=c}var a=createjs.extend(ErrorEvent,createjs.Event);a.clone=function(){return new createjs.ErrorEvent(this.title,this.message,this.data)},createjs.ErrorEvent=createjs.promote(ErrorEvent,"Event")}(),this.createjs=this.createjs||{},function(){"use strict";function EventDispatcher(){this._listeners=null,this._captureListeners=null}var a=EventDispatcher.prototype;EventDispatcher.initialize=function(b){b.addEventListener=a.addEventListener,b.on=a.on,b.removeEventListener=b.off=a.removeEventListener,b.removeAllEventListeners=a.removeAllEventListeners,b.hasEventListener=a.hasEventListener,b.dispatchEvent=a.dispatchEvent,b._dispatchEvent=a._dispatchEvent,b.willTrigger=a.willTrigger},a.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},a.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},a.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},a.off=a.removeEventListener,a.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},a.dispatchEvent=function(a,b,c){if("string"==typeof a){var d=this._listeners;if(!(b||d&&d[a]))return!0;a=new createjs.Event(a,b,c)}else a.target&&a.clone&&(a=a.clone());try{a.target=this}catch(e){}if(a.bubbles&&this.parent){for(var f=this,g=[f];f.parent;)g.push(f=f.parent);var h,i=g.length;for(h=i-1;h>=0&&!a.propagationStopped;h--)g[h]._dispatchEvent(a,1+(0==h));for(h=1;i>h&&!a.propagationStopped;h++)g[h]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return!a.defaultPrevented},a.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},a.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},a.toString=function(){return"[EventDispatcher]"},a._dispatchEvent=function(a,b){var c,d,e=2>=b?this._captureListeners:this._listeners;if(a&&e&&(d=e[a.type])&&(c=d.length)){try{a.currentTarget=this}catch(f){}try{a.eventPhase=0|b}catch(f){}a.removed=!1,d=d.slice();for(var g=0;c>g&&!a.immediatePropagationStopped;g++){var h=d[g];h.handleEvent?h.handleEvent(a):h(a),a.removed&&(this.off(a.type,h,1==b),a.removed=!1)}}2===b&&this._dispatchEvent(a,2.1)},createjs.EventDispatcher=EventDispatcher}(),this.createjs=this.createjs||{},function(){"use strict";function ProgressEvent(a,b){this.Event_constructor("progress"),this.loaded=a,this.total=null==b?1:b,this.progress=0==b?0:this.loaded/this.total}var a=createjs.extend(ProgressEvent,createjs.Event);a.clone=function(){return new createjs.ProgressEvent(this.loaded,this.total)},createjs.ProgressEvent=createjs.promote(ProgressEvent,"Event")}(window),function(){function a(b,d){function f(a){if(f[a]!==q)return f[a];var b;if("bug-string-char-index"==a)b="a"!="a"[0];else if("json"==a)b=f("json-stringify")&&f("json-parse");else{var c,e='{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';if("json-stringify"==a){var i=d.stringify,k="function"==typeof i&&t;if(k){(c=function(){return 1}).toJSON=c;try{k="0"===i(0)&&"0"===i(new g)&&'""'==i(new h)&&i(s)===q&&i(q)===q&&i()===q&&"1"===i(c)&&"[1]"==i([c])&&"[null]"==i([q])&&"null"==i(null)&&"[null,null,null]"==i([q,s,null])&&i({a:[c,!0,!1,null,"\x00\b\n\f\r "]})==e&&"1"===i(null,c)&&"[\n 1,\n 2\n]"==i([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==i(new j(-864e13))&&'"+275760-09-13T00:00:00.000Z"'==i(new j(864e13))&&'"-000001-01-01T00:00:00.000Z"'==i(new j(-621987552e5))&&'"1969-12-31T23:59:59.999Z"'==i(new j(-1))}catch(l){k=!1}}b=k}if("json-parse"==a){var m=d.parse;if("function"==typeof m)try{if(0===m("0")&&!m(!1)){c=m(e);var n=5==c.a.length&&1===c.a[0];if(n){try{n=!m('" "')}catch(l){}if(n)try{n=1!==m("01")}catch(l){}if(n)try{n=1!==m("1.")}catch(l){}}}}catch(l){n=!1}b=n}}return f[a]=!!b}b||(b=e.Object()),d||(d=e.Object());var g=b.Number||e.Number,h=b.String||e.String,i=b.Object||e.Object,j=b.Date||e.Date,k=b.SyntaxError||e.SyntaxError,l=b.TypeError||e.TypeError,m=b.Math||e.Math,n=b.JSON||e.JSON;"object"==typeof n&&n&&(d.stringify=n.stringify,d.parse=n.parse);var o,p,q,r=i.prototype,s=r.toString,t=new j(-0xc782b5b800cec);try{t=-109252==t.getUTCFullYear()&&0===t.getUTCMonth()&&1===t.getUTCDate()&&10==t.getUTCHours()&&37==t.getUTCMinutes()&&6==t.getUTCSeconds()&&708==t.getUTCMilliseconds()}catch(u){}if(!f("json")){var v="[object Function]",w="[object Date]",x="[object Number]",y="[object String]",z="[object Array]",A="[object Boolean]",B=f("bug-string-char-index");if(!t)var C=m.floor,D=[0,31,59,90,120,151,181,212,243,273,304,334],E=function(a,b){return D[b]+365*(a-1970)+C((a-1969+(b=+(b>1)))/4)-C((a-1901+b)/100)+C((a-1601+b)/400)};if((o=r.hasOwnProperty)||(o=function(a){var b,c={};return(c.__proto__=null,c.__proto__={toString:1},c).toString!=s?o=function(a){var b=this.__proto__,c=a in(this.__proto__=null,this);return this.__proto__=b,c}:(b=c.constructor,o=function(a){var c=(this.constructor||b).prototype;return a in this&&!(a in c&&this[a]===c[a])}),c=null,o.call(this,a)}),p=function(a,b){var d,e,f,g=0;(d=function(){this.valueOf=0}).prototype.valueOf=0,e=new d;for(f in e)o.call(e,f)&&g++;return d=e=null,g?p=2==g?function(a,b){var c,d={},e=s.call(a)==v;for(c in a)e&&"prototype"==c||o.call(d,c)||!(d[c]=1)||!o.call(a,c)||b(c)}:function(a,b){var c,d,e=s.call(a)==v;for(c in a)e&&"prototype"==c||!o.call(a,c)||(d="constructor"===c)||b(c);(d||o.call(a,c="constructor"))&&b(c)}:(e=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"],p=function(a,b){var d,f,g=s.call(a)==v,h=!g&&"function"!=typeof a.constructor&&c[typeof a.hasOwnProperty]&&a.hasOwnProperty||o;for(d in a)g&&"prototype"==d||!h.call(a,d)||b(d);for(f=e.length;d=e[--f];h.call(a,d)&&b(d));}),p(a,b)},!f("json-stringify")){var F={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"},G="000000",H=function(a,b){return(G+(b||0)).slice(-a)},I="\\u00",J=function(a){for(var b='"',c=0,d=a.length,e=!B||d>10,f=e&&(B?a.split(""):a);d>c;c++){var g=a.charCodeAt(c);switch(g){case 8:case 9:case 10:case 12:case 13:case 34:case 92:b+=F[g];break;default:if(32>g){b+=I+H(2,g.toString(16));break}b+=e?f[c]:a.charAt(c)}}return b+'"'},K=function(a,b,c,d,e,f,g){var h,i,j,k,m,n,r,t,u,v,B,D,F,G,I,L;try{h=b[a]}catch(M){}if("object"==typeof h&&h)if(i=s.call(h),i!=w||o.call(h,"toJSON"))"function"==typeof h.toJSON&&(i!=x&&i!=y&&i!=z||o.call(h,"toJSON"))&&(h=h.toJSON(a));else if(h>-1/0&&1/0>h){if(E){for(m=C(h/864e5),j=C(m/365.2425)+1970-1;E(j+1,0)<=m;j++);for(k=C((m-E(j,0))/30.42);E(j,k+1)<=m;k++);m=1+m-E(j,k),n=(h%864e5+864e5)%864e5,r=C(n/36e5)%24,t=C(n/6e4)%60,u=C(n/1e3)%60,v=n%1e3}else j=h.getUTCFullYear(),k=h.getUTCMonth(),m=h.getUTCDate(),r=h.getUTCHours(),t=h.getUTCMinutes(),u=h.getUTCSeconds(),v=h.getUTCMilliseconds();h=(0>=j||j>=1e4?(0>j?"-":"+")+H(6,0>j?-j:j):H(4,j))+"-"+H(2,k+1)+"-"+H(2,m)+"T"+H(2,r)+":"+H(2,t)+":"+H(2,u)+"."+H(3,v)+"Z"}else h=null;if(c&&(h=c.call(b,a,h)),null===h)return"null";if(i=s.call(h),i==A)return""+h;if(i==x)return h>-1/0&&1/0>h?""+h:"null";if(i==y)return J(""+h);if("object"==typeof h){for(G=g.length;G--;)if(g[G]===h)throw l();if(g.push(h),B=[],I=f,f+=e,i==z){for(F=0,G=h.length;G>F;F++)D=K(F,h,c,d,e,f,g),B.push(D===q?"null":D);L=B.length?e?"[\n"+f+B.join(",\n"+f)+"\n"+I+"]":"["+B.join(",")+"]":"[]"}else p(d||h,function(a){var b=K(a,h,c,d,e,f,g);b!==q&&B.push(J(a)+":"+(e?" ":"")+b)}),L=B.length?e?"{\n"+f+B.join(",\n"+f)+"\n"+I+"}":"{"+B.join(",")+"}":"{}";return g.pop(),L}};d.stringify=function(a,b,d){var e,f,g,h;if(c[typeof b]&&b)if((h=s.call(b))==v)f=b;else if(h==z){g={};for(var i,j=0,k=b.length;k>j;i=b[j++],h=s.call(i),(h==y||h==x)&&(g[i]=1));}if(d)if((h=s.call(d))==x){if((d-=d%1)>0)for(e="",d>10&&(d=10);e.lengthL;)switch(e=f.charCodeAt(L)){case 9:case 10:case 13:case 32:L++;break;case 123:case 125:case 91:case 93:case 58:case 44:return a=B?f.charAt(L):f[L],L++,a;case 34:for(a="@",L++;g>L;)if(e=f.charCodeAt(L),32>e)P();else if(92==e)switch(e=f.charCodeAt(++L)){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:a+=O[e],L++;break;case 117:for(b=++L,c=L+4;c>L;L++)e=f.charCodeAt(L),e>=48&&57>=e||e>=97&&102>=e||e>=65&&70>=e||P();a+=N("0x"+f.slice(b,L));break;default:P()}else{if(34==e)break;for(e=f.charCodeAt(L),b=L;e>=32&&92!=e&&34!=e;)e=f.charCodeAt(++L);a+=f.slice(b,L)}if(34==f.charCodeAt(L))return L++,a;P();default:if(b=L,45==e&&(d=!0,e=f.charCodeAt(++L)),e>=48&&57>=e){for(48==e&&(e=f.charCodeAt(L+1),e>=48&&57>=e)&&P(),d=!1;g>L&&(e=f.charCodeAt(L),e>=48&&57>=e);L++);if(46==f.charCodeAt(L)){for(c=++L;g>c&&(e=f.charCodeAt(c),e>=48&&57>=e);c++);c==L&&P(),L=c}if(e=f.charCodeAt(L),101==e||69==e){for(e=f.charCodeAt(++L),(43==e||45==e)&&L++,c=L;g>c&&(e=f.charCodeAt(c),e>=48&&57>=e);c++);c==L&&P(),L=c}return+f.slice(b,L)}if(d&&P(),"true"==f.slice(L,L+4))return L+=4,!0;if("false"==f.slice(L,L+5))return L+=5,!1;if("null"==f.slice(L,L+4))return L+=4,null;P()}return"$"},R=function(a){var b,c;if("$"==a&&P(),"string"==typeof a){if("@"==(B?a.charAt(0):a[0]))return a.slice(1);if("["==a){for(b=[];a=Q(),"]"!=a;c||(c=!0))c&&(","==a?(a=Q(),"]"==a&&P()):P()),","==a&&P(),b.push(R(a));return b}if("{"==a){for(b={};a=Q(),"}"!=a;c||(c=!0))c&&(","==a?(a=Q(),"}"==a&&P()):P()),(","==a||"string"!=typeof a||"@"!=(B?a.charAt(0):a[0])||":"!=Q())&&P(),b[a.slice(1)]=R(Q());return b}P()}return a},S=function(a,b,c){var d=T(a,b,c);d===q?delete a[b]:a[b]=d},T=function(a,b,c){var d,e=a[b];if("object"==typeof e&&e)if(s.call(e)==z)for(d=e.length;d--;)S(e,d,c);else p(e,function(a){S(e,a,c)});return c.call(a,b,e)};d.parse=function(a,b){var c,d;return L=0,M=""+a,c=R(Q()),"$"!=Q()&&P(),L=M=null,b&&s.call(b)==v?T((d={},d[""]=c,d),"",b):c}}}return d.runInContext=a,d}var b="function"==typeof define&&define.amd,c={"function":!0,object:!0},d=c[typeof exports]&&exports&&!exports.nodeType&&exports,e=c[typeof window]&&window||this,f=d&&c[typeof module]&&module&&!module.nodeType&&"object"==typeof global&&global;if(!f||f.global!==f&&f.window!==f&&f.self!==f||(e=f),d&&!b)a(e,d);else{var g=e.JSON,h=e.JSON3,i=!1,j=a(e,e.JSON3={noConflict:function(){return i||(i=!0,e.JSON=g,e.JSON3=h,g=h=null),j}});e.JSON={parse:j.parse,stringify:j.stringify}}b&&define(function(){return j})}.call(this),function(){var a={};a.a=function(){return a.el("a")},a.svg=function(){return a.el("svg")},a.object=function(){return a.el("object")},a.image=function(){return a.el("image")},a.img=function(){return a.el("img")},a.style=function(){return a.el("style")},a.link=function(){return a.el("link")},a.script=function(){return a.el("script")},a.audio=function(){return a.el("audio")},a.video=function(){return a.el("video")},a.text=function(a){return document.createTextNode(a)},a.el=function(a){return document.createElement(a)},createjs.Elements=a}(),function(){var a={};a.ABSOLUTE_PATT=/^(?:\w+:)?\/{2}/i,a.RELATIVE_PATT=/^[.\/]*?\//i,a.EXTENSION_PATT=/\/?[^\/]+\.(\w{1,5})$/i,a.parseURI=function(b){var c={absolute:!1,relative:!1,protocol:null,hostname:null,port:null,pathname:null,search:null,hash:null,host:null};if(null==b)return c;var d=createjs.Elements.a();d.href=b;for(var e in c)e in d&&(c[e]=d[e]);var f=b.indexOf("?");f>-1&&(b=b.substr(0,f));var g;return a.ABSOLUTE_PATT.test(b)?c.absolute=!0:a.RELATIVE_PATT.test(b)&&(c.relative=!0),(g=b.match(a.EXTENSION_PATT))&&(c.extension=g[1].toLowerCase()),c},a.formatQueryString=function(a,b){if(null==a)throw new Error("You must specify data.");var c=[];for(var d in a)c.push(d+"="+escape(a[d]));return b&&(c=c.concat(b)),c.join("&")},a.buildURI=function(a,b){if(null==b)return a;var c=[],d=a.indexOf("?");if(-1!=d){var e=a.slice(d+1);c=c.concat(e.split("&"))}return-1!=d?a.slice(0,d)+"?"+this.formatQueryString(b,c):a+"?"+this.formatQueryString(b,c)},a.isCrossDomain=function(a){var b=createjs.Elements.a();b.href=a.src;var c=createjs.Elements.a();c.href=location.href;var d=""!=b.hostname&&(b.port!=c.port||b.protocol!=c.protocol||b.hostname!=c.hostname);return d},a.isLocal=function(a){var b=createjs.Elements.a();return b.href=a.src,""==b.hostname&&"file:"==b.protocol},createjs.URLUtils=a}(),function(){var a={container:null};a.appendToHead=function(b){a.getHead().appendChild(b)},a.appendToBody=function(b){if(null==a.container){a.container=document.createElement("div"),a.container.id="preloadjs-container";var c=a.container.style;c.visibility="hidden",c.position="absolute",c.width=a.container.style.height="10px",c.overflow="hidden",c.transform=c.msTransform=c.webkitTransform=c.oTransform="translate(-10px, -10px)",a.getBody().appendChild(a.container)}a.container.appendChild(b)},a.getHead=function(){return document.head||document.getElementsByTagName("head")[0]},a.getBody=function(){return document.body||document.getElementsByTagName("body")[0]},a.removeChild=function(a){a.parent&&a.parent.removeChild(a)},a.isImageTag=function(a){return a instanceof HTMLImageElement},a.isAudioTag=function(a){return window.HTMLAudioElement?a instanceof HTMLAudioElement:!1},a.isVideoTag=function(a){return window.HTMLVideoElement?a instanceof HTMLVideoElement:!1},createjs.DomUtils=a}(),function(){var a={};a.parseXML=function(a){var b=null;try{if(window.DOMParser){var c=new DOMParser;b=c.parseFromString(a,"text/xml")}}catch(d){}if(!b)try{b=new ActiveXObject("Microsoft.XMLDOM"),b.async=!1,b.loadXML(a)}catch(d){b=null}return b},a.parseJSON=function(a){if(null==a)return null;try{return JSON.parse(a)}catch(b){throw b}},createjs.DataUtils=a}(),this.createjs=this.createjs||{},function(){var a={};a.BINARY="binary",a.CSS="css",a.FONT="font",a.FONTCSS="fontcss",a.IMAGE="image",a.JAVASCRIPT="javascript",a.JSON="json",a.JSONP="jsonp",a.MANIFEST="manifest",a.SOUND="sound",a.VIDEO="video",a.SPRITESHEET="spritesheet",a.SVG="svg",a.TEXT="text",a.XML="xml",createjs.Types=a}(),this.createjs=this.createjs||{},function(){var a={};a.POST="POST",a.GET="GET",createjs.Methods=a}(),this.createjs=this.createjs||{},function(){"use strict";function LoadItem(){this.src=null,this.type=null,this.id=null,this.maintainOrder=!1,this.callback=null,this.data=null,this.method=createjs.Methods.GET,this.values=null,this.headers=null,this.withCredentials=!1,this.mimeType=null,this.crossOrigin=null,this.loadTimeout=b.LOAD_TIMEOUT_DEFAULT}var a=LoadItem.prototype={},b=LoadItem;b.LOAD_TIMEOUT_DEFAULT=8e3,b.create=function(a){if("string"==typeof a){var c=new LoadItem;return c.src=a,c}if(a instanceof b)return a;if(a instanceof Object&&a.src)return null==a.loadTimeout&&(a.loadTimeout=b.LOAD_TIMEOUT_DEFAULT),a;throw new Error("Type not recognized.")},a.set=function(a){for(var b in a)this[b]=a[b];return this},createjs.LoadItem=b}(),function(){var a={};a.isBinary=function(a){switch(a){case createjs.Types.IMAGE:case createjs.Types.BINARY:return!0;default:return!1}},a.isText=function(a){switch(a){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!0;default:return!1}},a.getTypeByExtension=function(a){if(null==a)return createjs.Types.TEXT;switch(a.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=a}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractLoader(a,b,c){this.EventDispatcher_constructor(),this.loaded=!1,this.canceled=!1,this.progress=0,this.type=c,this.resultFormatter=null,this._item=a?createjs.LoadItem.create(a):null,this._preferXHR=b,this._result=null,this._rawResult=null,this._loadedItems=null,this._tagSrcAttribute=null,this._tag=null}var a=createjs.extend(AbstractLoader,createjs.EventDispatcher),b=AbstractLoader;try{Object.defineProperties(b,{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(c){}a.getItem=function(){return this._item},a.getResult=function(a){return a?this._rawResult:this._result},a.getTag=function(){return this._tag},a.setTag=function(a){this._tag=a},a.load=function(){this._createRequest(),this._request.on("complete",this,this),this._request.on("progress",this,this),this._request.on("loadStart",this,this),this._request.on("abort",this,this),this._request.on("timeout",this,this),this._request.on("error",this,this);var a=new createjs.Event("initialize");a.loader=this._request,this.dispatchEvent(a),this._request.load()},a.cancel=function(){this.canceled=!0,this.destroy()},a.destroy=function(){this._request&&(this._request.removeAllEventListeners(),this._request.destroy()),this._request=null,this._item=null,this._rawResult=null,this._result=null,this._loadItems=null,this.removeAllEventListeners()},a.getLoadedItems=function(){return this._loadedItems},a._createRequest=function(){this._request=this._preferXHR?new createjs.XHRRequest(this._item):new createjs.TagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},a._createTag=function(){return null},a._sendLoadStart=function(){this._isCanceled()||this.dispatchEvent("loadstart")},a._sendProgress=function(a){if(!this._isCanceled()){var b=null;"number"==typeof a?(this.progress=a,b=new createjs.ProgressEvent(this.progress)):(b=a,this.progress=a.loaded/a.total,b.progress=this.progress,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0)),this.hasEventListener("progress")&&this.dispatchEvent(b)}},a._sendComplete=function(){if(!this._isCanceled()){this.loaded=!0;var a=new createjs.Event("complete");a.rawResult=this._rawResult,null!=this._result&&(a.result=this._result),this.dispatchEvent(a)}},a._sendError=function(a){!this._isCanceled()&&this.hasEventListener("error")&&(null==a&&(a=new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY")),this.dispatchEvent(a))},a._isCanceled=function(){return null==window.createjs||this.canceled?!0:!1},a.resultFormatter=null,a.handleEvent=function(a){switch(a.type){case"complete":this._rawResult=a.target._response;var b=this.resultFormatter&&this.resultFormatter(this);b instanceof Function?b.call(this,createjs.proxy(this._resultFormatSuccess,this),createjs.proxy(this._resultFormatFailed,this)):(this._result=b||this._rawResult,this._sendComplete());break;case"progress":this._sendProgress(a);break;case"error":this._sendError(a);break;case"loadstart":this._sendLoadStart();break;case"abort":case"timeout":this._isCanceled()||this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_"+a.type.toUpperCase()+"_ERROR"))}},a._resultFormatSuccess=function(a){this._result=a,this._sendComplete()},a._resultFormatFailed=function(a){this._sendError(a)},a.toString=function(){return"[PreloadJS AbstractLoader]"},createjs.AbstractLoader=createjs.promote(AbstractLoader,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractMediaLoader(a,b,c){this.AbstractLoader_constructor(a,b,c),this.resultFormatter=this._formatResult,this._tagSrcAttribute="src",this.on("initialize",this._updateXHR,this)}var a=createjs.extend(AbstractMediaLoader,createjs.AbstractLoader);a.load=function(){this._tag||(this._tag=this._createTag(this._item.src)),this._tag.preload="auto",this._tag.load(),this.AbstractLoader_load()},a._createTag=function(){},a._createRequest=function(){this._request=this._preferXHR?new createjs.XHRRequest(this._item):new createjs.MediaTagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},a._updateXHR=function(a){a.loader.setResponseType&&a.loader.setResponseType("blob")},a._formatResult=function(a){if(this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.onstalled=null,this._preferXHR){var b=window.URL||window.webkitURL,c=a.getResult(!0);a.getTag().src=b.createObjectURL(c)}return a.getTag()},createjs.AbstractMediaLoader=createjs.promote(AbstractMediaLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";var AbstractRequest=function(a){this._item=a},a=createjs.extend(AbstractRequest,createjs.EventDispatcher);a.load=function(){},a.destroy=function(){},a.cancel=function(){},createjs.AbstractRequest=createjs.promote(AbstractRequest,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function TagRequest(a,b,c){this.AbstractRequest_constructor(a),this._tag=b,this._tagSrcAttribute=c,this._loadedHandler=createjs.proxy(this._handleTagComplete,this),this._addedToDOM=!1}var a=createjs.extend(TagRequest,createjs.AbstractRequest);a.load=function(){this._tag.onload=createjs.proxy(this._handleTagComplete,this),this._tag.onreadystatechange=createjs.proxy(this._handleReadyStateChange,this),this._tag.onerror=createjs.proxy(this._handleError,this);var a=new createjs.Event("initialize");a.loader=this._tag,this.dispatchEvent(a),this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout),this._tag[this._tagSrcAttribute]=this._item.src,null==this._tag.parentNode&&(createjs.DomUtils.appendToBody(this._tag),this._addedToDOM=!0)},a.destroy=function(){this._clean(),this._tag=null,this.AbstractRequest_destroy()},a._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},a._handleError=function(){this._clean(),this.dispatchEvent("error")},a._handleTagComplete=function(){this._rawResult=this._tag,this._result=this.resultFormatter&&this.resultFormatter(this)||this._rawResult,this._clean(),this.dispatchEvent("complete")},a._handleTimeout=function(){this._clean(),this.dispatchEvent(new createjs.Event("timeout"))},a._clean=function(){this._tag.onload=null,this._tag.onreadystatechange=null,this._tag.onerror=null,this._addedToDOM&&null!=this._tag.parentNode&&this._tag.parentNode.removeChild(this._tag),clearTimeout(this._loadTimeout)},a._handleStalled=function(){},createjs.TagRequest=createjs.promote(TagRequest,"AbstractRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function MediaTagRequest(a,b,c){this.AbstractRequest_constructor(a),this._tag=b,this._tagSrcAttribute=c,this._loadedHandler=createjs.proxy(this._handleTagComplete,this)}var a=createjs.extend(MediaTagRequest,createjs.TagRequest);a.load=function(){var a=createjs.proxy(this._handleStalled,this);this._stalledCallback=a;var b=createjs.proxy(this._handleProgress,this);this._handleProgress=b,this._tag.addEventListener("stalled",a),this._tag.addEventListener("progress",b),this._tag.addEventListener&&this._tag.addEventListener("canplaythrough",this._loadedHandler,!1),this.TagRequest_load()},a._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},a._handleStalled=function(){},a._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.ProgressEvent(a.loaded,a.total);this.dispatchEvent(b)}},a._clean=function(){this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.removeEventListener("stalled",this._stalledCallback),this._tag.removeEventListener("progress",this._progressCallback),this.TagRequest__clean()},createjs.MediaTagRequest=createjs.promote(MediaTagRequest,"TagRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function XHRRequest(a){this.AbstractRequest_constructor(a),this._request=null,this._loadTimeout=null,this._xhrLevel=1,this._response=null,this._rawResponse=null,this._canceled=!1,this._handleLoadStartProxy=createjs.proxy(this._handleLoadStart,this),this._handleProgressProxy=createjs.proxy(this._handleProgress,this),this._handleAbortProxy=createjs.proxy(this._handleAbort,this),this._handleErrorProxy=createjs.proxy(this._handleError,this),this._handleTimeoutProxy=createjs.proxy(this._handleTimeout,this),this._handleLoadProxy=createjs.proxy(this._handleLoad,this),this._handleReadyStateChangeProxy=createjs.proxy(this._handleReadyStateChange,this),!this._createXHR(a)}var a=createjs.extend(XHRRequest,createjs.AbstractRequest);XHRRequest.ACTIVEX_VERSIONS=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],a.getResult=function(a){return a&&this._rawResponse?this._rawResponse:this._response},a.cancel=function(){this.canceled=!0,this._clean(),this._request.abort()},a.load=function(){if(null==this._request)return void this._handleError();null!=this._request.addEventListener?(this._request.addEventListener("loadstart",this._handleLoadStartProxy,!1),this._request.addEventListener("progress",this._handleProgressProxy,!1),this._request.addEventListener("abort",this._handleAbortProxy,!1),this._request.addEventListener("error",this._handleErrorProxy,!1),this._request.addEventListener("timeout",this._handleTimeoutProxy,!1),this._request.addEventListener("load",this._handleLoadProxy,!1),this._request.addEventListener("readystatechange",this._handleReadyStateChangeProxy,!1)):(this._request.onloadstart=this._handleLoadStartProxy,this._request.onprogress=this._handleProgressProxy,this._request.onabort=this._handleAbortProxy,this._request.onerror=this._handleErrorProxy,this._request.ontimeout=this._handleTimeoutProxy,this._request.onload=this._handleLoadProxy,this._request.onreadystatechange=this._handleReadyStateChangeProxy),1==this._xhrLevel&&(this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout));try{this._item.values?this._request.send(createjs.URLUtils.formatQueryString(this._item.values)):this._request.send()}catch(a){this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND",null,a))}},a.setResponseType=function(a){"blob"===a&&(a=window.URL?"blob":"arraybuffer",this._responseType=a),this._request.responseType=a},a.getAllResponseHeaders=function(){return this._request.getAllResponseHeaders instanceof Function?this._request.getAllResponseHeaders():null},a.getResponseHeader=function(a){return this._request.getResponseHeader instanceof Function?this._request.getResponseHeader(a):null},a._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.ProgressEvent(a.loaded,a.total);this.dispatchEvent(b)}},a._handleLoadStart=function(){clearTimeout(this._loadTimeout),this.dispatchEvent("loadstart")},a._handleAbort=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED",null,a))},a._handleError=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent(a.message))},a._handleReadyStateChange=function(){4==this._request.readyState&&this._handleLoad()},a._handleLoad=function(){if(!this.loaded){this.loaded=!0;var a=this._checkError();if(a)return void this._handleError(a);if(this._response=this._getResponse(),"arraybuffer"===this._responseType)try{this._response=new Blob([this._response])}catch(b){if(window.BlobBuilder=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,"TypeError"===b.name&&window.BlobBuilder){var c=new BlobBuilder;c.append(this._response),this._response=c.getBlob()}}this._clean(),this.dispatchEvent(new createjs.Event("complete"))}},a._handleTimeout=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT",null,a))},a._checkError=function(){var a=parseInt(this._request.status);return a>=400&&599>=a?new Error(a):0==a&&/^https?:/.test(location.protocol)?new Error(0):null},a._getResponse=function(){if(null!=this._response)return this._response; +if(null!=this._request.response)return this._request.response;try{if(null!=this._request.responseText)return this._request.responseText}catch(a){}try{if(null!=this._request.responseXML)return this._request.responseXML}catch(a){}return null},a._createXHR=function(a){var b=createjs.URLUtils.isCrossDomain(a),c={},d=null;if(window.XMLHttpRequest)d=new XMLHttpRequest,b&&void 0===d.withCredentials&&window.XDomainRequest&&(d=new XDomainRequest);else{for(var e=0,f=s.ACTIVEX_VERSIONS.length;f>e;e++){var g=s.ACTIVEX_VERSIONS[e];try{d=new ActiveXObject(g);break}catch(h){}}if(null==d)return!1}null==a.mimeType&&createjs.RequestUtils.isText(a.type)&&(a.mimeType="text/plain; charset=utf-8"),a.mimeType&&d.overrideMimeType&&d.overrideMimeType(a.mimeType),this._xhrLevel="string"==typeof d.responseType?2:1;var i=null;if(i=a.method==createjs.Methods.GET?createjs.URLUtils.buildURI(a.src,a.values):a.src,d.open(a.method||createjs.Methods.GET,i,!0),b&&d instanceof XMLHttpRequest&&1==this._xhrLevel&&(c.Origin=location.origin),a.values&&a.method==createjs.Methods.POST&&(c["Content-Type"]="application/x-www-form-urlencoded"),b||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest"),a.headers)for(var j in a.headers)c[j]=a.headers[j];for(j in c)d.setRequestHeader(j,c[j]);return d instanceof XMLHttpRequest&&void 0!==a.withCredentials&&(d.withCredentials=a.withCredentials),this._request=d,!0},a._clean=function(){clearTimeout(this._loadTimeout),null!=this._request.removeEventListener?(this._request.removeEventListener("loadstart",this._handleLoadStartProxy),this._request.removeEventListener("progress",this._handleProgressProxy),this._request.removeEventListener("abort",this._handleAbortProxy),this._request.removeEventListener("error",this._handleErrorProxy),this._request.removeEventListener("timeout",this._handleTimeoutProxy),this._request.removeEventListener("load",this._handleLoadProxy),this._request.removeEventListener("readystatechange",this._handleReadyStateChangeProxy)):(this._request.onloadstart=null,this._request.onprogress=null,this._request.onabort=null,this._request.onerror=null,this._request.ontimeout=null,this._request.onload=null,this._request.onreadystatechange=null)},a.toString=function(){return"[PreloadJS XHRRequest]"},createjs.XHRRequest=createjs.promote(XHRRequest,"AbstractRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function LoadQueue(a,b,c){this.AbstractLoader_constructor(),this._plugins=[],this._typeCallbacks={},this._extensionCallbacks={},this.next=null,this.maintainScriptOrder=!0,this.stopOnError=!1,this._maxConnections=1,this._availableLoaders=[createjs.FontLoader,createjs.ImageLoader,createjs.JavaScriptLoader,createjs.CSSLoader,createjs.JSONLoader,createjs.JSONPLoader,createjs.SoundLoader,createjs.ManifestLoader,createjs.SpriteSheetLoader,createjs.XMLLoader,createjs.SVGLoader,createjs.BinaryLoader,createjs.VideoLoader,createjs.TextLoader],this._defaultLoaderLength=this._availableLoaders.length,this.init(a,b,c)}var a=createjs.extend(LoadQueue,createjs.AbstractLoader),b=LoadQueue;try{Object.defineProperties(b,{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(c){}a.init=function(a,b,c){this.preferXHR=!0,this._preferXHR=!0,this.setPreferXHR(a),this._paused=!1,this._basePath=b,this._crossOrigin=c,this._loadStartWasDispatched=!1,this._currentlyLoadingScript=null,this._currentLoads=[],this._loadQueue=[],this._loadQueueBackup=[],this._loadItemsById={},this._loadItemsBySrc={},this._loadedResults={},this._loadedRawResults={},this._numItems=0,this._numItemsLoaded=0,this._scriptOrder=[],this._loadedScripts=[],this._lastProgress=0/0},a.registerLoader=function(a){if(!a||!a.canLoadItem)throw new Error("loader is of an incorrect type.");if(-1!=this._availableLoaders.indexOf(a))throw new Error("loader already exists.");this._availableLoaders.unshift(a)},a.unregisterLoader=function(a){var b=this._availableLoaders.indexOf(a);-1!=b&&b0)return;var c=!1;if(b){for(;b.length;){var d=b.pop(),e=this.getResult(d);for(f=this._loadQueue.length-1;f>=0;f--)if(g=this._loadQueue[f].getItem(),g.id==d||g.src==d){this._loadQueue.splice(f,1)[0].cancel();break}for(f=this._loadQueueBackup.length-1;f>=0;f--)if(g=this._loadQueueBackup[f].getItem(),g.id==d||g.src==d){this._loadQueueBackup.splice(f,1)[0].cancel();break}if(e)this._disposeItem(this.getItem(d));else for(var f=this._currentLoads.length-1;f>=0;f--){var g=this._currentLoads[f].getItem();if(g.id==d||g.src==d){this._currentLoads.splice(f,1)[0].cancel(),c=!0;break}}}c&&this._loadNext()}else{this.close();for(var h in this._loadItemsById)this._disposeItem(this._loadItemsById[h]);this.init(this.preferXHR,this._basePath)}},a.reset=function(){this.close();for(var a in this._loadItemsById)this._disposeItem(this._loadItemsById[a]);for(var b=[],c=0,d=this._loadQueueBackup.length;d>c;c++)b.push(this._loadQueueBackup[c].getItem());this.loadManifest(b,!1)},a.installPlugin=function(a){if(null!=a&&null!=a.getPreloadHandlers){this._plugins.push(a);var b=a.getPreloadHandlers();if(b.scope=a,null!=b.types)for(var c=0,d=b.types.length;d>c;c++)this._typeCallbacks[b.types[c]]=b;if(null!=b.extensions)for(c=0,d=b.extensions.length;d>c;c++)this._extensionCallbacks[b.extensions[c]]=b}},a.setMaxConnections=function(a){this._maxConnections=a,!this._paused&&this._loadQueue.length>0&&this._loadNext()},a.loadFile=function(a,b,c){if(null==a){var d=new createjs.ErrorEvent("PRELOAD_NO_FILE");return void this._sendError(d)}this._addItem(a,null,c),this.setPaused(b!==!1?!1:!0)},a.loadManifest=function(a,c,d){var e=null,f=null;if(Array.isArray(a)){if(0==a.length){var g=new createjs.ErrorEvent("PRELOAD_MANIFEST_EMPTY");return void this._sendError(g)}e=a}else if("string"==typeof a)e=[{src:a,type:b.MANIFEST}];else{if("object"!=typeof a){var g=new createjs.ErrorEvent("PRELOAD_MANIFEST_NULL");return void this._sendError(g)}if(void 0!==a.src){if(null==a.type)a.type=b.MANIFEST;else if(a.type!=b.MANIFEST){var g=new createjs.ErrorEvent("PRELOAD_MANIFEST_TYPE");this._sendError(g)}e=[a]}else void 0!==a.manifest&&(e=a.manifest,f=a.path)}for(var h=0,i=e.length;i>h;h++)this._addItem(e[h],f,d);this.setPaused(c!==!1?!1:!0)},a.load=function(){this.setPaused(!1)},a.getItem=function(a){return this._loadItemsById[a]||this._loadItemsBySrc[a]},a.getResult=function(a,b){var c=this._loadItemsById[a]||this._loadItemsBySrc[a];if(null==c)return null;var d=c.id;return b&&this._loadedRawResults[d]?this._loadedRawResults[d]:this._loadedResults[d]},a.getItems=function(a){var b=[];for(var c in this._loadItemsById){var d=this._loadItemsById[c],e=this.getResult(c);(a!==!0||null!=e)&&b.push({item:d,result:e,rawResult:this.getResult(c,!0)})}return b},a.setPaused=function(a){this._paused=a,this._paused||this._loadNext()},a.close=function(){for(;this._currentLoads.length;)this._currentLoads.pop().cancel();this._scriptOrder.length=0,this._loadedScripts.length=0,this.loadStartWasDispatched=!1,this._itemCount=0,this._lastProgress=0/0},a._addItem=function(a,b,c){var d=this._createLoadItem(a,b,c);if(null!=d){var e=this._createLoader(d);null!=e&&("plugins"in e&&(e.plugins=this._plugins),d._loader=e,this._loadQueue.push(e),this._loadQueueBackup.push(e),this._numItems++,this._updateProgress(),(this.maintainScriptOrder&&d.type==createjs.Types.JAVASCRIPT||d.maintainOrder===!0)&&(this._scriptOrder.push(d),this._loadedScripts.push(null)))}},a._createLoadItem=function(a,b,c){var d=createjs.LoadItem.create(a);if(null==d)return null;var e="",f=c||this._basePath;if(d.src instanceof Object){if(!d.type)return null;if(b){e=b;var g=createjs.URLUtils.parseURI(b);null==f||g.absolute||g.relative||(e=f+e)}else null!=f&&(e=f)}else{var h=createjs.URLUtils.parseURI(d.src);h.extension&&(d.ext=h.extension),null==d.type&&(d.type=createjs.RequestUtils.getTypeByExtension(d.ext));var i=d.src;if(!h.absolute&&!h.relative)if(b){e=b;var g=createjs.URLUtils.parseURI(b);i=b+i,null==f||g.absolute||g.relative||(e=f+e)}else null!=f&&(e=f);d.src=e+d.src}d.path=e,(void 0===d.id||null===d.id||""===d.id)&&(d.id=i);var j=this._typeCallbacks[d.type]||this._extensionCallbacks[d.ext];if(j){var k=j.callback.call(j.scope,d,this);if(k===!1)return null;k===!0||null!=k&&(d._loader=k),h=createjs.URLUtils.parseURI(d.src),null!=h.extension&&(d.ext=h.extension)}return this._loadItemsById[d.id]=d,this._loadItemsBySrc[d.src]=d,null==d.crossOrigin&&(d.crossOrigin=this._crossOrigin),d},a._createLoader=function(a){if(null!=a._loader)return a._loader;for(var b=this.preferXHR,c=0;c=this._maxConnections);a++){var b=this._loadQueue[a];this._canStartLoad(b)&&(this._loadQueue.splice(a,1),a--,this._loadItem(b))}}},a._loadItem=function(a){a.on("fileload",this._handleFileLoad,this),a.on("progress",this._handleProgress,this),a.on("complete",this._handleFileComplete,this),a.on("error",this._handleError,this),a.on("fileerror",this._handleFileError,this),this._currentLoads.push(a),this._sendFileStart(a.getItem()),a.load()},a._handleFileLoad=function(a){a.target=null,this.dispatchEvent(a)},a._handleFileError=function(a){var b=new createjs.ErrorEvent("FILE_LOAD_ERROR",null,a.item);this._sendError(b)},a._handleError=function(a){var b=a.target;this._numItemsLoaded++,this._finishOrderedItem(b,!0),this._updateProgress();var c=new createjs.ErrorEvent("FILE_LOAD_ERROR",null,b.getItem());this._sendError(c),this.stopOnError?this.setPaused(!0):(this._removeLoadItem(b),this._cleanLoadItem(b),this._loadNext())},a._handleFileComplete=function(a){var b=a.target,c=b.getItem(),d=b.getResult();this._loadedResults[c.id]=d;var e=b.getResult(!0);null!=e&&e!==d&&(this._loadedRawResults[c.id]=e),this._saveLoadedItems(b),this._removeLoadItem(b),this._finishOrderedItem(b)||this._processFinishedLoad(c,b),this._cleanLoadItem(b)},a._saveLoadedItems=function(a){var b=a.getLoadedItems();if(null!==b)for(var c=0;cb;b++){var c=this._loadedScripts[b];if(null===c)break;if(c!==!0){var d=this._loadedResults[c.id];c.type==createjs.Types.JAVASCRIPT&&createjs.DomUtils.appendToHead(d);var e=c._loader;this._processFinishedLoad(c,e),this._loadedScripts[b]=!0}}},a._processFinishedLoad=function(a,b){if(this._numItemsLoaded++,!this.maintainScriptOrder&&a.type==createjs.Types.JAVASCRIPT){var c=b.getTag();createjs.DomUtils.appendToHead(c)}this._updateProgress(),this._sendFileComplete(a,b),this._loadNext()},a._canStartLoad=function(a){if(!this.maintainScriptOrder||a.preferXHR)return!0;var b=a.getItem();if(b.type!=createjs.Types.JAVASCRIPT)return!0;if(this._currentlyLoadingScript)return!1;for(var c=this._scriptOrder.indexOf(b),d=0;c>d;){var e=this._loadedScripts[d];if(null==e)return!1;d++}return this._currentlyLoadingScript=!0,!0},a._removeLoadItem=function(a){for(var b=this._currentLoads.length,c=0;b>c;c++)if(this._currentLoads[c]==a){this._currentLoads.splice(c,1);break}},a._cleanLoadItem=function(a){var b=a.getItem();b&&delete b._loader},a._handleProgress=function(a){var b=a.target;this._sendFileProgress(b.getItem(),b.progress),this._updateProgress()},a._updateProgress=function(){var a=this._numItemsLoaded/this._numItems,b=this._numItems-this._numItemsLoaded;if(b>0){for(var c=0,d=0,e=this._currentLoads.length;e>d;d++)c+=this._currentLoads[d].progress;a+=c/b*(b/this._numItems)}this._lastProgress!=a&&(this._sendProgress(a),this._lastProgress=a)},a._disposeItem=function(a){delete this._loadedResults[a.id],delete this._loadedRawResults[a.id],delete this._loadItemsById[a.id],delete this._loadItemsBySrc[a.src]},a._sendFileProgress=function(a,b){if(!this._isCanceled()&&!this._paused&&this.hasEventListener("fileprogress")){var c=new createjs.Event("fileprogress");c.progress=b,c.loaded=b,c.total=1,c.item=a,this.dispatchEvent(c)}},a._sendFileComplete=function(a,b){if(!this._isCanceled()&&!this._paused){var c=new createjs.Event("fileload");c.loader=b,c.item=a,c.result=this._loadedResults[a.id],c.rawResult=this._loadedRawResults[a.id],a.completeHandler&&a.completeHandler(c),this.hasEventListener("fileload")&&this.dispatchEvent(c)}},a._sendFileStart=function(a){var b=new createjs.Event("filestart");b.item=a,this.hasEventListener("filestart")&&this.dispatchEvent(b)},a.toString=function(){return"[PreloadJS LoadQueue]"},createjs.LoadQueue=createjs.promote(LoadQueue,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function TextLoader(a){this.AbstractLoader_constructor(a,!0,createjs.Types.TEXT)}var a=(createjs.extend(TextLoader,createjs.AbstractLoader),TextLoader);a.canLoadItem=function(a){return a.type==createjs.Types.TEXT},createjs.TextLoader=createjs.promote(TextLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function BinaryLoader(a){this.AbstractLoader_constructor(a,!0,createjs.Types.BINARY),this.on("initialize",this._updateXHR,this)}var a=createjs.extend(BinaryLoader,createjs.AbstractLoader),b=BinaryLoader;b.canLoadItem=function(a){return a.type==createjs.Types.BINARY},a._updateXHR=function(a){a.loader.setResponseType("arraybuffer")},createjs.BinaryLoader=createjs.promote(BinaryLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function CSSLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.Types.CSS),this.resultFormatter=this._formatResult,this._tagSrcAttribute="href",this._tag=b?createjs.Elements.style():createjs.Elements.link(),this._tag.rel="stylesheet",this._tag.type="text/css"}var a=createjs.extend(CSSLoader,createjs.AbstractLoader),b=CSSLoader;b.canLoadItem=function(a){return a.type==createjs.Types.CSS},a._formatResult=function(a){if(this._preferXHR){var b=a.getTag();if(b.styleSheet)b.styleSheet.cssText=a.getResult(!0);else{var c=createjs.Elements.text(a.getResult(!0));b.appendChild(c)}}else b=this._tag;return createjs.DomUtils.appendToHead(b),b},createjs.CSSLoader=createjs.promote(CSSLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function FontLoader(a,b){this.AbstractLoader_constructor(a,b,a.type),this._faces={},this._watched=[],this._count=0,this._watchInterval=null,this._loadTimeout=null,this._injectCSS=void 0===a.injectCSS?!0:a.injectCSS,this.dispatchEvent("initialize")}var a=createjs.extend(FontLoader,createjs.AbstractLoader);FontLoader.canLoadItem=function(a){return a.type==createjs.Types.FONT||a.type==createjs.Types.FONTCSS},FontLoader.sampleText="abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ",FontLoader._ctx=document.createElement("canvas").getContext("2d"),FontLoader._referenceFonts=["serif","monospace"],FontLoader.WEIGHT_REGEX=/[- ._]*(thin|normal|book|regular|medium|black|heavy|[1-9]00|(?:extra|ultra|semi|demi)?[- ._]*(?:light|bold))[- ._]*/gi,FontLoader.STYLE_REGEX=/[- ._]*(italic|oblique)[- ._]*/gi,FontLoader.FONT_FORMAT={woff2:"woff2",woff:"woff",ttf:"truetype",otf:"truetype"},FontLoader.FONT_WEIGHT={thin:100,extralight:200,ultralight:200,light:300,semilight:300,demilight:300,book:"normal",regular:"normal",semibold:600,demibold:600,extrabold:800,ultrabold:800,black:900,heavy:900},FontLoader.WATCH_DURATION=10,a.load=function(){if(this.type==createjs.Types.FONTCSS){var a=this._watchCSS();if(!a)return void this.AbstractLoader_load()}else if(this._item.src instanceof Array)this._watchFontArray();else{var b=this._defFromSrc(this._item.src);this._watchFont(b),this._injectStyleTag(this._cssFromDef(b))}this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout),this.dispatchEvent("loadstart")},a._handleTimeout=function(){this._stopWatching(),this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT"))},a._createRequest=function(){return this._request},a.handleEvent=function(a){switch(a.type){case"complete":this._rawResult=a.target._response,this._result=!0,this._parseCSS(this._rawResult);break;case"error":this._stopWatching(),this.AbstractLoader_handleEvent(a)}},a._watchCSS=function(){var a=this._item.src;return a instanceof HTMLStyleElement&&(this._injectCSS&&!a.parentNode&&(document.head||document.getElementsByTagName("head")[0]).appendChild(a),this._injectCSS=!1,a="\n"+a.textContent),-1!==a.search(/\n|\r|@font-face/i)?(this._parseCSS(a),!0):(this._request=new createjs.XHRRequest(this._item),!1)},a._parseCSS=function(a){for(var b=/@font-face\s*\{([^}]+)}/g;;){var c=b.exec(a);if(!c)break;this._watchFont(this._parseFontFace(c[1]))}this._injectStyleTag(a)},a._watchFontArray=function(){for(var a,b=this._item.src,c="",d=b.length-1;d>=0;d--){var e=b[d];a="string"==typeof e?this._defFromSrc(e):this._defFromObj(e),this._watchFont(a),c+=this._cssFromDef(a)+"\n"}this._injectStyleTag(c)},a._injectStyleTag=function(a){if(this._injectCSS){var b=document.head||document.getElementsByTagName("head")[0],c=document.createElement("style");c.type="text/css",c.styleSheet?c.styleSheet.cssText=a:c.appendChild(document.createTextNode(a)),b.appendChild(c)}},a._parseFontFace=function(a){var b=this._getCSSValue(a,"font-family"),c=this._getCSSValue(a,"src");return b&&c?this._defFromObj({family:b,src:c,style:this._getCSSValue(a,"font-style"),weight:this._getCSSValue(a,"font-weight")}):null},a._watchFont=function(a){a&&!this._faces[a.id]&&(this._faces[a.id]=a,this._watched.push(a),this._count++,this._calculateReferenceSizes(a),this._startWatching())},a._startWatching=function(){null==this._watchInterval&&(this._watchInterval=setInterval(createjs.proxy(this._watch,this),FontLoader.WATCH_DURATION))},a._stopWatching=function(){clearInterval(this._watchInterval),clearTimeout(this._loadTimeout),this._watchInterval=null},a._watch=function(){for(var a=this._watched,b=FontLoader._referenceFonts,c=a.length,d=c-1;d>=0;d--)for(var e=a[d],f=e.refs,g=f.length-1;g>=0;g--){var h=this._getTextWidth(e.family+","+b[g],e.weight,e.style);if(h!=f[g]){var i=new createjs.Event("fileload");e.type="font-family",i.item=e,this.dispatchEvent(i),a.splice(d,1);break}}if(c!==a.length){var i=new createjs.ProgressEvent(this._count-a.length,this._count);this.dispatchEvent(i)}0===c&&(this._stopWatching(),this._sendComplete())},a._calculateReferenceSizes=function(a){for(var b=FontLoader._referenceFonts,c=a.refs=[],d=0;dc;c++)b.installPlugin(this.plugins[c]);b.loadManifest(a)}else this._sendComplete()},a._handleManifestFileLoad=function(a){a.target=null,this.dispatchEvent(a)},a._handleManifestComplete=function(){this._loadedItems=this._manifestQueue.getItems(!0),this._sendComplete()},a._handleManifestProgress=function(a){this.progress=a.progress*(1-b.MANIFEST_PROGRESS)+b.MANIFEST_PROGRESS,this._sendProgress(this.progress)},a._handleManifestError=function(a){var b=new createjs.Event("fileerror");b.item=a.data,this.dispatchEvent(b)},createjs.ManifestLoader=createjs.promote(ManifestLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function SoundLoader(a,b){this.AbstractMediaLoader_constructor(a,b,createjs.Types.SOUND),createjs.DomUtils.isAudioTag(a)?this._tag=a:createjs.DomUtils.isAudioTag(a.src)?this._tag=a:createjs.DomUtils.isAudioTag(a.tag)&&(this._tag=createjs.DomUtils.isAudioTag(a)?a:a.src),null!=this._tag&&(this._preferXHR=!1)}var a=createjs.extend(SoundLoader,createjs.AbstractMediaLoader),b=SoundLoader;b.canLoadItem=function(a){return a.type==createjs.Types.SOUND},a._createTag=function(a){var b=createjs.Elements.audio();return b.autoplay=!1,b.preload="none",b.src=a,b},createjs.SoundLoader=createjs.promote(SoundLoader,"AbstractMediaLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function VideoLoader(a,b){this.AbstractMediaLoader_constructor(a,b,createjs.Types.VIDEO),createjs.DomUtils.isVideoTag(a)||createjs.DomUtils.isVideoTag(a.src)?(this.setTag(createjs.DomUtils.isVideoTag(a)?a:a.src),this._preferXHR=!1):this.setTag(this._createTag())}var a=createjs.extend(VideoLoader,createjs.AbstractMediaLoader),b=VideoLoader;a._createTag=function(){return createjs.Elements.video()},b.canLoadItem=function(a){return a.type==createjs.Types.VIDEO},createjs.VideoLoader=createjs.promote(VideoLoader,"AbstractMediaLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function SpriteSheetLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.Types.SPRITESHEET),this._manifestQueue=null}var a=createjs.extend(SpriteSheetLoader,createjs.AbstractLoader),b=SpriteSheetLoader;b.SPRITESHEET_PROGRESS=.25,b.canLoadItem=function(a){return a.type==createjs.Types.SPRITESHEET},a.destroy=function(){this.AbstractLoader_destroy(),this._manifestQueue.close()},a._createRequest=function(){var a=this._item.callback;this._request=null!=a?new createjs.JSONPLoader(this._item):new createjs.JSONLoader(this._item)},a.handleEvent=function(a){switch(a.type){case"complete":return this._rawResult=a.target.getResult(!0),this._result=a.target.getResult(),this._sendProgress(b.SPRITESHEET_PROGRESS),void this._loadManifest(this._result);case"progress":return a.loaded*=b.SPRITESHEET_PROGRESS,this.progress=a.loaded/a.total,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0),void this._sendProgress(a)}this.AbstractLoader_handleEvent(a)},a._loadManifest=function(a){if(a&&a.images){var b=this._manifestQueue=new createjs.LoadQueue(this._preferXHR,this._item.path,this._item.crossOrigin);b.on("complete",this._handleManifestComplete,this,!0),b.on("fileload",this._handleManifestFileLoad,this),b.on("progress",this._handleManifestProgress,this),b.on("error",this._handleManifestError,this,!0),b.loadManifest(a.images)}},a._handleManifestFileLoad=function(a){var b=a.result;if(null!=b){var c=this.getResult().images,d=c.indexOf(a.item.src);c[d]=b}},a._handleManifestComplete=function(){this._result=new createjs.SpriteSheet(this._result),this._loadedItems=this._manifestQueue.getItems(!0),this._sendComplete()},a._handleManifestProgress=function(a){this.progress=a.progress*(1-b.SPRITESHEET_PROGRESS)+b.SPRITESHEET_PROGRESS,this._sendProgress(this.progress)},a._handleManifestError=function(a){var b=new createjs.Event("fileerror");b.item=a.data,this.dispatchEvent(b)},createjs.SpriteSheetLoader=createjs.promote(SpriteSheetLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function SVGLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.Types.SVG),this.resultFormatter=this._formatResult,this._tagSrcAttribute="data",b?this.setTag(createjs.Elements.svg()):(this.setTag(createjs.Elements.object()),this.getTag().type="image/svg+xml") +}var a=createjs.extend(SVGLoader,createjs.AbstractLoader),b=SVGLoader;b.canLoadItem=function(a){return a.type==createjs.Types.SVG},a._formatResult=function(a){var b=createjs.DataUtils.parseXML(a.getResult(!0)),c=a.getTag();if(!this._preferXHR&&document.body.contains(c)&&document.body.removeChild(c),null!=b.documentElement){var d=b.documentElement;return document.importNode&&(d=document.importNode(d,!0)),c.appendChild(d),c}return b},createjs.SVGLoader=createjs.promote(SVGLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function XMLLoader(a){this.AbstractLoader_constructor(a,!0,createjs.Types.XML),this.resultFormatter=this._formatResult}var a=createjs.extend(XMLLoader,createjs.AbstractLoader),b=XMLLoader;b.canLoadItem=function(a){return a.type==createjs.Types.XML},a._formatResult=function(a){return createjs.DataUtils.parseXML(a.getResult(!0))},createjs.XMLLoader=createjs.promote(XMLLoader,"AbstractLoader")}(); \ No newline at end of file diff --git a/lib/preloadjs.js b/lib/preloadjs.js new file mode 100644 index 00000000..c13ea8a6 --- /dev/null +++ b/lib/preloadjs.js @@ -0,0 +1,7894 @@ +/*! +* PreloadJS +* 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. +*/ + + +//############################################################################## +// version.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + /** + * Static class holding library specific information such as the version and buildDate of the library. + * @class PreloadJS + **/ + var s = createjs.PreloadJS = createjs.PreloadJS || {}; + + /** + * The version string for this release. + * @property version + * @type {String} + * @static + **/ + s.version = /*=version*/"1.0.0"; // injected by build process + + /** + * The build date for this release in UTC format. + * @property buildDate + * @type {String} + * @static + **/ + s.buildDate = /*=date*/"Thu, 14 Sep 2017 19:47:47 GMT"; // injected by build process + +})(); + +//############################################################################## +// extend.js +//############################################################################## + +this.createjs = this.createjs||{}; + +/** + * @class Utility Methods + */ + +/** + * Sets up the prototype chain and constructor property for a new class. + * + * This should be called right after creating the class constructor. + * + * function MySubClass() {} + * createjs.extend(MySubClass, MySuperClass); + * 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 +//############################################################################## + +this.createjs = this.createjs||{}; + +/** + * @class Utility Methods + */ + +/** + * Promotes any methods on the super class that were overridden, by creating an alias in the format `prefix_methodName`. + * It is recommended to use the super class's name as the prefix. + * An alias to the super class's constructor is always added in the format `prefix_constructor`. + * This allows the subclass to call super class methods without using `function.call`, providing better performance. + * + * For example, if `MySubClass` extends `MySuperClass`, and both define a `draw` method, then calling `promote(MySubClass, "MySuperClass")` + * would add a `MySuperClass_constructor` method to MySubClass and promote the `draw` method on `MySuperClass` to the + * prototype of `MySubClass` as `MySuperClass_draw`. + * + * This should be called after the class's prototype is fully defined. + * + * function ClassA(name) { + * this.name = name; + * } + * ClassA.prototype.greet = function() { + * return "Hello "+this.name; + * } + * + * function ClassB(name, punctuation) { + * this.ClassA_constructor(name); + * this.punctuation = punctuation; + * } + * createjs.extend(ClassB, ClassA); + * ClassB.prototype.greet = function() { + * return this.ClassA_greet()+this.punctuation; + * } + * createjs.promote(ClassB, "ClassA"); + * + * var foo = new ClassB("World", "!?!"); + * console.log(foo.greet()); // Hello World!?! + * + * @method promote + * @param {Function} subclass The class to promote super class methods on. + * @param {String} prefix The prefix to add to the promoted method names. Usually the name of the superclass. + * @return {Function} Returns the subclass. + */ +createjs.promote = function(subclass, prefix) { + "use strict"; + + var subP = subclass.prototype, supP = (Object.getPrototypeOf&&Object.getPrototypeOf(subP))||subP.__proto__; + if (supP) { + subP[(prefix+="_") + "constructor"] = supP.constructor; // constructor is not always innumerable + for (var n in supP) { + if (subP.hasOwnProperty(n) && (typeof supP[n] == "function")) { subP[prefix + n] = supP[n]; } + } + } + return subclass; +}; + +//############################################################################## +// deprecate.js +//############################################################################## + +this.createjs = this.createjs||{}; + +/** + * @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); + } +}; + +//############################################################################## +// proxy.js +//############################################################################## + +this.createjs = this.createjs||{}; + +/** + * 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)); + }; + } + +}()); + +//############################################################################## +// indexOf.js +//############################################################################## + +this.createjs = this.createjs||{}; + +/** + * @class Utility Methods + */ + +/** + * Finds the first occurrence of a specified value searchElement in the passed in array, and returns the index of + * that value. Returns -1 if value is not found. + * + * var i = createjs.indexOf(myArray, myElementToFind); + * + * @method indexOf + * @param {Array} array Array to search for searchElement + * @param searchElement Element to find in array. + * @return {Number} The first index of searchElement in array. + */ +createjs.indexOf = function (array, searchElement){ + "use strict"; + + for (var i = 0,l=array.length; i < l; i++) { + if (searchElement === array[i]) { + return i; + } + } + return -1; +}; + +//############################################################################## +// Event.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + +// constructor: + /** + * Contains properties and methods shared by all events for use with + * {{#crossLink "EventDispatcher"}}{{/crossLink}}. + * + * Note that Event objects are often reused, so you should never + * rely on an event object's state outside of the call stack it was received in. + * @class Event + * @param {String} type The event type. + * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. + * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. + * @constructor + **/ + function Event(type, bubbles, cancelable) { + + + // public properties: + /** + * The type of event. + * @property type + * @type String + **/ + this.type = type; + + /** + * The object that generated an event. + * @property target + * @type Object + * @default null + * @readonly + */ + this.target = null; + + /** + * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will + * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event + * is generated from childObj, then a listener on parentObj would receive the event with + * target=childObj (the original target) and currentTarget=parentObj (where the listener was added). + * @property currentTarget + * @type Object + * @default null + * @readonly + */ + this.currentTarget = null; + + /** + * For bubbling events, this indicates the current event phase:
      + *
    1. capture phase: starting from the top parent to the target
    2. + *
    3. at target phase: currently being dispatched from the target
    4. + *
    5. bubbling phase: from the target to the top parent
    6. + *
    + * @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 +//############################################################################## + +this.createjs = this.createjs||{}; + +(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"); + +}()); + +//############################################################################## +// EventDispatcher.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(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= 10.53. + isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 && + // Safari < 2.0.2 stores the internal millisecond time value correctly, + // but clips the values returned by the date methods to the range of + // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]). + isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708; + } catch (exception) {} + + // Internal: Determines whether the native `JSON.stringify` and `parse` + // implementations are spec-compliant. Based on work by Ken Snyder. + function has(name) { + if (has[name] !== undef) { + // Return cached feature test result. + return has[name]; + } + var isSupported; + if (name == "bug-string-char-index") { + // IE <= 7 doesn't support accessing string characters using square + // bracket notation. IE 8 only supports this for primitives. + isSupported = "a"[0] != "a"; + } else if (name == "json") { + // Indicates whether both `JSON.stringify` and `JSON.parse` are + // supported. + isSupported = has("json-stringify") && has("json-parse"); + } else { + var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'; + // Test `JSON.stringify`. + if (name == "json-stringify") { + var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended; + if (stringifySupported) { + // A test function object with a custom `toJSON` method. + (value = function () { + return 1; + }).toJSON = value; + try { + stringifySupported = + // Firefox 3.1b1 and b2 serialize string, number, and boolean + // primitives as object literals. + stringify(0) === "0" && + // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object + // literals. + stringify(new Number()) === "0" && + stringify(new String()) == '""' && + // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or + // does not define a canonical JSON representation (this applies to + // objects with `toJSON` properties as well, *unless* they are nested + // within an object or array). + stringify(getClass) === undef && + // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and + // FF 3.1b3 pass this test. + stringify(undef) === undef && + // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s, + // respectively, if the value is omitted entirely. + stringify() === undef && + // FF 3.1b1, 2 throw an error if the given value is not a number, + // string, array, object, Boolean, or `null` literal. This applies to + // objects with custom `toJSON` methods as well, unless they are nested + // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON` + // methods entirely. + stringify(value) === "1" && + stringify([value]) == "[1]" && + // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of + // `"[null]"`. + stringify([undef]) == "[null]" && + // YUI 3.0.0b1 fails to serialize `null` literals. + stringify(null) == "null" && + // FF 3.1b1, 2 halts serialization if an array contains a function: + // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3 + // elides non-JSON values from objects and arrays, unless they + // define custom `toJSON` methods. + stringify([undef, getClass, null]) == "[null,null,null]" && + // Simple serialization test. FF 3.1b1 uses Unicode escape sequences + // where character escape codes are expected (e.g., `\b` => `\u0008`). + stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized && + // FF 3.1b1 and b2 ignore the `filter` and `width` arguments. + stringify(null, value) === "1" && + stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" && + // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly + // serialize extended years. + stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' && + // The milliseconds are optional in ES 5, but required in 5.1. + stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' && + // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative + // four-digit years instead of six-digit years. Credits: @Yaffle. + stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' && + // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond + // values less than 1000. Credits: @Yaffle. + stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"'; + } catch (exception) { + stringifySupported = false; + } + } + isSupported = stringifySupported; + } + // Test `JSON.parse`. + if (name == "json-parse") { + var parse = exports.parse; + if (typeof parse == "function") { + try { + // FF 3.1b1, b2 will throw an exception if a bare literal is provided. + // Conforming implementations should also coerce the initial argument to + // a string prior to parsing. + if (parse("0") === 0 && !parse(false)) { + // Simple parsing test. + value = parse(serialized); + var parseSupported = value["a"].length == 5 && value["a"][0] === 1; + if (parseSupported) { + try { + // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings. + parseSupported = !parse('"\t"'); + } catch (exception) {} + if (parseSupported) { + try { + // FF 4.0 and 4.0.1 allow leading `+` signs and leading + // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow + // certain octal literals. + parseSupported = parse("01") !== 1; + } catch (exception) {} + } + if (parseSupported) { + try { + // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal + // points. These environments, along with FF 3.1b1 and 2, + // also allow trailing commas in JSON objects and arrays. + parseSupported = parse("1.") !== 1; + } catch (exception) {} + } + } + } + } catch (exception) { + parseSupported = false; + } + } + isSupported = parseSupported; + } + } + return has[name] = !!isSupported; + } + + if (!has("json")) { + // Common `[[Class]]` name aliases. + var functionClass = "[object Function]", + dateClass = "[object Date]", + numberClass = "[object Number]", + stringClass = "[object String]", + arrayClass = "[object Array]", + booleanClass = "[object Boolean]"; + + // Detect incomplete support for accessing string characters by index. + var charIndexBuggy = has("bug-string-char-index"); + + // Define additional utility methods if the `Date` methods are buggy. + if (!isExtended) { + var floor = Math.floor; + // A mapping between the months of the year and the number of days between + // January 1st and the first of the respective month. + var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; + // Internal: Calculates the number of days between the Unix epoch and the + // first day of the given month. + var getDay = function (year, month) { + return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400); + }; + } + + // Internal: Determines if a property is a direct property of the given + // object. Delegates to the native `Object#hasOwnProperty` method. + if (!(isProperty = objectProto.hasOwnProperty)) { + isProperty = function (property) { + var members = {}, constructor; + if ((members.__proto__ = null, members.__proto__ = { + // The *proto* property cannot be set multiple times in recent + // versions of Firefox and SeaMonkey. + "toString": 1 + }, members).toString != getClass) { + // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but + // supports the mutable *proto* property. + isProperty = function (property) { + // Capture and break the object's prototype chain (see section 8.6.2 + // of the ES 5.1 spec). The parenthesized expression prevents an + // unsafe transformation by the Closure Compiler. + var original = this.__proto__, result = property in (this.__proto__ = null, this); + // Restore the original prototype chain. + this.__proto__ = original; + return result; + }; + } else { + // Capture a reference to the top-level `Object` constructor. + constructor = members.constructor; + // Use the `constructor` property to simulate `Object#hasOwnProperty` in + // other environments. + isProperty = function (property) { + var parent = (this.constructor || constructor).prototype; + return property in this && !(property in parent && this[property] === parent[property]); + }; + } + members = null; + return isProperty.call(this, property); + }; + } + + // Internal: Normalizes the `for...in` iteration algorithm across + // environments. Each enumerated key is yielded to a `callback` function. + forEach = function (object, callback) { + var size = 0, Properties, members, property; + + // Tests for bugs in the current environment's `for...in` algorithm. The + // `valueOf` property inherits the non-enumerable flag from + // `Object.prototype` in older versions of IE, Netscape, and Mozilla. + (Properties = function () { + this.valueOf = 0; + }).prototype.valueOf = 0; + + // Iterate over a new instance of the `Properties` class. + members = new Properties(); + for (property in members) { + // Ignore all properties inherited from `Object.prototype`. + if (isProperty.call(members, property)) { + size++; + } + } + Properties = members = null; + + // Normalize the iteration algorithm. + if (!size) { + // A list of non-enumerable properties inherited from `Object.prototype`. + members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"]; + // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable + // properties. + forEach = function (object, callback) { + var isFunction = getClass.call(object) == functionClass, property, length; + var hasProperty = !isFunction && typeof object.constructor != "function" && objectTypes[typeof object.hasOwnProperty] && object.hasOwnProperty || isProperty; + for (property in object) { + // Gecko <= 1.0 enumerates the `prototype` property of functions under + // certain conditions; IE does not. + if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) { + callback(property); + } + } + // Manually invoke the callback for each non-enumerable property. + for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property)); + }; + } else if (size == 2) { + // Safari <= 2.0.4 enumerates shadowed properties twice. + forEach = function (object, callback) { + // Create a set of iterated properties. + var members = {}, isFunction = getClass.call(object) == functionClass, property; + for (property in object) { + // Store each property name to prevent double enumeration. The + // `prototype` property of functions is not enumerated due to cross- + // environment inconsistencies. + if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) { + callback(property); + } + } + }; + } else { + // No bugs detected; use the standard `for...in` algorithm. + forEach = function (object, callback) { + var isFunction = getClass.call(object) == functionClass, property, isConstructor; + for (property in object) { + if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) { + callback(property); + } + } + // Manually invoke the callback for the `constructor` property due to + // cross-environment inconsistencies. + if (isConstructor || isProperty.call(object, (property = "constructor"))) { + callback(property); + } + }; + } + return forEach(object, callback); + }; + + // Public: Serializes a JavaScript `value` as a JSON string. The optional + // `filter` argument may specify either a function that alters how object and + // array members are serialized, or an array of strings and numbers that + // indicates which properties should be serialized. The optional `width` + // argument may be either a string or number that specifies the indentation + // level of the output. + if (!has("json-stringify")) { + // Internal: A map of control characters and their escaped equivalents. + var Escapes = { + 92: "\\\\", + 34: '\\"', + 8: "\\b", + 12: "\\f", + 10: "\\n", + 13: "\\r", + 9: "\\t" + }; + + // Internal: Converts `value` into a zero-padded string such that its + // length is at least equal to `width`. The `width` must be <= 6. + var leadingZeroes = "000000"; + var toPaddedString = function (width, value) { + // The `|| 0` expression is necessary to work around a bug in + // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`. + return (leadingZeroes + (value || 0)).slice(-width); + }; + + // Internal: Double-quotes a string `value`, replacing all ASCII control + // characters (characters with code unit values between 0 and 31) with + // their escaped equivalents. This is an implementation of the + // `Quote(value)` operation defined in ES 5.1 section 15.12.3. + var unicodePrefix = "\\u00"; + var quote = function (value) { + var result = '"', index = 0, length = value.length, useCharIndex = !charIndexBuggy || length > 10; + var symbols = useCharIndex && (charIndexBuggy ? value.split("") : value); + for (; index < length; index++) { + var charCode = value.charCodeAt(index); + // If the character is a control character, append its Unicode or + // shorthand escape sequence; otherwise, append the character as-is. + switch (charCode) { + case 8: case 9: case 10: case 12: case 13: case 34: case 92: + result += Escapes[charCode]; + break; + default: + if (charCode < 32) { + result += unicodePrefix + toPaddedString(2, charCode.toString(16)); + break; + } + result += useCharIndex ? symbols[index] : value.charAt(index); + } + } + return result + '"'; + }; + + // Internal: Recursively serializes an object. Implements the + // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations. + var serialize = function (property, object, callback, properties, whitespace, indentation, stack) { + var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result; + try { + // Necessary for host object support. + value = object[property]; + } catch (exception) {} + if (typeof value == "object" && value) { + className = getClass.call(value); + if (className == dateClass && !isProperty.call(value, "toJSON")) { + if (value > -1 / 0 && value < 1 / 0) { + // Dates are serialized according to the `Date#toJSON` method + // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15 + // for the ISO 8601 date time string format. + if (getDay) { + // Manually compute the year, month, date, hours, minutes, + // seconds, and milliseconds if the `getUTC*` methods are + // buggy. Adapted from @Yaffle's `date-shim` project. + date = floor(value / 864e5); + for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++); + for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++); + date = 1 + date - getDay(year, month); + // The `time` value specifies the time within the day (see ES + // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used + // to compute `A modulo B`, as the `%` operator does not + // correspond to the `modulo` operation for negative numbers. + time = (value % 864e5 + 864e5) % 864e5; + // The hours, minutes, seconds, and milliseconds are obtained by + // decomposing the time within the day. See section 15.9.1.10. + hours = floor(time / 36e5) % 24; + minutes = floor(time / 6e4) % 60; + seconds = floor(time / 1e3) % 60; + milliseconds = time % 1e3; + } else { + year = value.getUTCFullYear(); + month = value.getUTCMonth(); + date = value.getUTCDate(); + hours = value.getUTCHours(); + minutes = value.getUTCMinutes(); + seconds = value.getUTCSeconds(); + milliseconds = value.getUTCMilliseconds(); + } + // Serialize extended years correctly. + value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) + + "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) + + // Months, dates, hours, minutes, and seconds should have two + // digits; milliseconds should have three. + "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) + + // Milliseconds are optional in ES 5.0, but required in 5.1. + "." + toPaddedString(3, milliseconds) + "Z"; + } else { + value = null; + } + } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) { + // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the + // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3 + // ignores all `toJSON` methods on these objects unless they are + // defined directly on an instance. + value = value.toJSON(property); + } + } + if (callback) { + // If a replacement function was provided, call it to obtain the value + // for serialization. + value = callback.call(object, property, value); + } + if (value === null) { + return "null"; + } + className = getClass.call(value); + if (className == booleanClass) { + // Booleans are represented literally. + return "" + value; + } else if (className == numberClass) { + // JSON numbers must be finite. `Infinity` and `NaN` are serialized as + // `"null"`. + return value > -1 / 0 && value < 1 / 0 ? "" + value : "null"; + } else if (className == stringClass) { + // Strings are double-quoted and escaped. + return quote("" + value); + } + // Recursively serialize objects and arrays. + if (typeof value == "object") { + // Check for cyclic structures. This is a linear search; performance + // is inversely proportional to the number of unique nested objects. + for (length = stack.length; length--;) { + if (stack[length] === value) { + // Cyclic structures cannot be serialized by `JSON.stringify`. + throw TypeError(); + } + } + // Add the object to the stack of traversed objects. + stack.push(value); + results = []; + // Save the current indentation level and indent one additional level. + prefix = indentation; + indentation += whitespace; + if (className == arrayClass) { + // Recursively serialize array elements. + for (index = 0, length = value.length; index < length; index++) { + element = serialize(index, value, callback, properties, whitespace, indentation, stack); + results.push(element === undef ? "null" : element); + } + result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]"; + } else { + // Recursively serialize object members. Members are selected from + // either a user-specified list of property names, or the object + // itself. + forEach(properties || value, function (property) { + var element = serialize(property, value, callback, properties, whitespace, indentation, stack); + if (element !== undef) { + // According to ES 5.1 section 15.12.3: "If `gap` {whitespace} + // is not the empty string, let `member` {quote(property) + ":"} + // be the concatenation of `member` and the `space` character." + // The "`space` character" refers to the literal space + // character, not the `space` {width} argument provided to + // `JSON.stringify`. + results.push(quote(property) + ":" + (whitespace ? " " : "") + element); + } + }); + result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}"; + } + // Remove the object from the traversed object stack. + stack.pop(); + return result; + } + }; + + // Public: `JSON.stringify`. See ES 5.1 section 15.12.3. + exports.stringify = function (source, filter, width) { + var whitespace, callback, properties, className; + if (objectTypes[typeof filter] && filter) { + if ((className = getClass.call(filter)) == functionClass) { + callback = filter; + } else if (className == arrayClass) { + // Convert the property names array into a makeshift set. + properties = {}; + for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1)); + } + } + if (width) { + if ((className = getClass.call(width)) == numberClass) { + // Convert the `width` to an integer and create a string containing + // `width` number of space characters. + if ((width -= width % 1) > 0) { + for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " "); + } + } else if (className == stringClass) { + whitespace = width.length <= 10 ? width : width.slice(0, 10); + } + } + // Opera <= 7.54u2 discards the values associated with empty string keys + // (`""`) only if they are used directly within an object member list + // (e.g., `!("" in { "": 1})`). + return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []); + }; + } + + // Public: Parses a JSON source string. + if (!has("json-parse")) { + var fromCharCode = String.fromCharCode; + + // Internal: A map of escaped control characters and their unescaped + // equivalents. + var Unescapes = { + 92: "\\", + 34: '"', + 47: "/", + 98: "\b", + 116: "\t", + 110: "\n", + 102: "\f", + 114: "\r" + }; + + // Internal: Stores the parser state. + var Index, Source; + + // Internal: Resets the parser state and throws a `SyntaxError`. + var abort = function () { + Index = Source = null; + throw SyntaxError(); + }; + + // Internal: Returns the next token, or `"$"` if the parser has reached + // the end of the source string. A token may be a string, number, `null` + // literal, or Boolean literal. + var lex = function () { + var source = Source, length = source.length, value, begin, position, isSigned, charCode; + while (Index < length) { + charCode = source.charCodeAt(Index); + switch (charCode) { + case 9: case 10: case 13: case 32: + // Skip whitespace tokens, including tabs, carriage returns, line + // feeds, and space characters. + Index++; + break; + case 123: case 125: case 91: case 93: case 58: case 44: + // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at + // the current position. + value = charIndexBuggy ? source.charAt(Index) : source[Index]; + Index++; + return value; + case 34: + // `"` delimits a JSON string; advance to the next character and + // begin parsing the string. String tokens are prefixed with the + // sentinel `@` character to distinguish them from punctuators and + // end-of-string tokens. + for (value = "@", Index++; Index < length;) { + charCode = source.charCodeAt(Index); + if (charCode < 32) { + // Unescaped ASCII control characters (those with a code unit + // less than the space character) are not permitted. + abort(); + } else if (charCode == 92) { + // A reverse solidus (`\`) marks the beginning of an escaped + // control character (including `"`, `\`, and `/`) or Unicode + // escape sequence. + charCode = source.charCodeAt(++Index); + switch (charCode) { + case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114: + // Revive escaped control characters. + value += Unescapes[charCode]; + Index++; + break; + case 117: + // `\u` marks the beginning of a Unicode escape sequence. + // Advance to the first character and validate the + // four-digit code point. + begin = ++Index; + for (position = Index + 4; Index < position; Index++) { + charCode = source.charCodeAt(Index); + // A valid sequence comprises four hexdigits (case- + // insensitive) that form a single hexadecimal value. + if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) { + // Invalid Unicode escape sequence. + abort(); + } + } + // Revive the escaped character. + value += fromCharCode("0x" + source.slice(begin, Index)); + break; + default: + // Invalid escape sequence. + abort(); + } + } else { + if (charCode == 34) { + // An unescaped double-quote character marks the end of the + // string. + break; + } + charCode = source.charCodeAt(Index); + begin = Index; + // Optimize for the common case where a string is valid. + while (charCode >= 32 && charCode != 92 && charCode != 34) { + charCode = source.charCodeAt(++Index); + } + // Append the string as-is. + value += source.slice(begin, Index); + } + } + if (source.charCodeAt(Index) == 34) { + // Advance to the next character and return the revived string. + Index++; + return value; + } + // Unterminated string. + abort(); + default: + // Parse numbers and literals. + begin = Index; + // Advance past the negative sign, if one is specified. + if (charCode == 45) { + isSigned = true; + charCode = source.charCodeAt(++Index); + } + // Parse an integer or floating-point value. + if (charCode >= 48 && charCode <= 57) { + // Leading zeroes are interpreted as octal literals. + if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) { + // Illegal octal literal. + abort(); + } + isSigned = false; + // Parse the integer component. + for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++); + // Floats cannot contain a leading decimal point; however, this + // case is already accounted for by the parser. + if (source.charCodeAt(Index) == 46) { + position = ++Index; + // Parse the decimal component. + for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); + if (position == Index) { + // Illegal trailing decimal. + abort(); + } + Index = position; + } + // Parse exponents. The `e` denoting the exponent is + // case-insensitive. + charCode = source.charCodeAt(Index); + if (charCode == 101 || charCode == 69) { + charCode = source.charCodeAt(++Index); + // Skip past the sign following the exponent, if one is + // specified. + if (charCode == 43 || charCode == 45) { + Index++; + } + // Parse the exponential component. + for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); + if (position == Index) { + // Illegal empty exponent. + abort(); + } + Index = position; + } + // Coerce the parsed value to a JavaScript number. + return +source.slice(begin, Index); + } + // A negative sign may only precede numbers. + if (isSigned) { + abort(); + } + // `true`, `false`, and `null` literals. + if (source.slice(Index, Index + 4) == "true") { + Index += 4; + return true; + } else if (source.slice(Index, Index + 5) == "false") { + Index += 5; + return false; + } else if (source.slice(Index, Index + 4) == "null") { + Index += 4; + return null; + } + // Unrecognized token. + abort(); + } + } + // Return the sentinel `$` character if the parser has reached the end + // of the source string. + return "$"; + }; + + // Internal: Parses a JSON `value` token. + var get = function (value) { + var results, hasMembers; + if (value == "$") { + // Unexpected end of input. + abort(); + } + if (typeof value == "string") { + if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") { + // Remove the sentinel `@` character. + return value.slice(1); + } + // Parse object and array literals. + if (value == "[") { + // Parses a JSON array, returning a new JavaScript array. + results = []; + for (;; hasMembers || (hasMembers = true)) { + value = lex(); + // A closing square bracket marks the end of the array literal. + if (value == "]") { + break; + } + // If the array literal contains elements, the current token + // should be a comma separating the previous element from the + // next. + if (hasMembers) { + if (value == ",") { + value = lex(); + if (value == "]") { + // Unexpected trailing `,` in array literal. + abort(); + } + } else { + // A `,` must separate each array element. + abort(); + } + } + // Elisions and leading commas are not permitted. + if (value == ",") { + abort(); + } + results.push(get(value)); + } + return results; + } else if (value == "{") { + // Parses a JSON object, returning a new JavaScript object. + results = {}; + for (;; hasMembers || (hasMembers = true)) { + value = lex(); + // A closing curly brace marks the end of the object literal. + if (value == "}") { + break; + } + // If the object literal contains members, the current token + // should be a comma separator. + if (hasMembers) { + if (value == ",") { + value = lex(); + if (value == "}") { + // Unexpected trailing `,` in object literal. + abort(); + } + } else { + // A `,` must separate each object member. + abort(); + } + } + // Leading commas are not permitted, object property names must be + // double-quoted strings, and a `:` must separate each property + // name and value. + if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") { + abort(); + } + results[value.slice(1)] = get(lex()); + } + return results; + } + // Unexpected token encountered. + abort(); + } + return value; + }; + + // Internal: Updates a traversed object member. + var update = function (source, property, callback) { + var element = walk(source, property, callback); + if (element === undef) { + delete source[property]; + } else { + source[property] = element; + } + }; + + // Internal: Recursively traverses a parsed JSON object, invoking the + // `callback` function for each value. This is an implementation of the + // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2. + var walk = function (source, property, callback) { + var value = source[property], length; + if (typeof value == "object" && value) { + // `forEach` can't be used to traverse an array in Opera <= 8.54 + // because its `Object#hasOwnProperty` implementation returns `false` + // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`). + if (getClass.call(value) == arrayClass) { + for (length = value.length; length--;) { + update(value, length, callback); + } + } else { + forEach(value, function (property) { + update(value, property, callback); + }); + } + } + return callback.call(source, property, value); + }; + + // Public: `JSON.parse`. See ES 5.1 section 15.12.2. + exports.parse = function (source, callback) { + var result, value; + Index = 0; + Source = "" + source; + result = get(lex()); + // If a JSON string contains multiple tokens, it is invalid. + if (lex() != "$") { + abort(); + } + // Reset the parser state. + Index = Source = null; + return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result; + }; + } + } + + exports["runInContext"] = runInContext; + return exports; + } + + if (freeExports && !isLoader) { + // Export for CommonJS environments. + runInContext(root, freeExports); + } else { + // Export for web browsers and JavaScript engines. + var nativeJSON = root.JSON, + previousJSON = root["JSON3"], + isRestored = false; + + var JSON3 = runInContext(root, (root["JSON3"] = { + // Public: Restores the original value of the global `JSON` object and + // returns a reference to the `JSON3` object. + "noConflict": function () { + if (!isRestored) { + isRestored = true; + root.JSON = nativeJSON; + root["JSON3"] = previousJSON; + nativeJSON = previousJSON = null; + } + return JSON3; + } + })); + + root.JSON = { + "parse": JSON3.parse, + "stringify": JSON3.stringify + }; + } + + // Export for asynchronous module loaders. + if (isLoader) { + define(function () { + return JSON3; + }); + } +}).call(this); + +//############################################################################## +// 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; + +}()); + +//############################################################################## +// 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: + *
      + *
    • If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or + * `//networkPath`)
    • + *
    • If the path is relative. Relative paths start with `../` or `/path` (or similar)
    • + *
    • The file extension. This is determined by the filename with an extension. Query strings are dropped, and + * the file path is expected to follow the format `name.ext`.
    • + *
    + * + * @method parseURI + * @param {String} path + * @returns {Object} An Object with an `absolute` and `relative` Boolean values, + * 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; + +}()); + +//############################################################################## +// 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; + +}()); + +//############################################################################## +// DataUtils.js +//############################################################################## + +(function () { + + /** + * A few data utilities for formatting different data types. + * @class DataUtils + */ + var s = {}; + + // static methods + /** + * Parse XML using the DOM. This is required when preloading XML or SVG. + * @method parseXML + * @param {String} text The raw text or XML that is loaded by XHR. + * @return {XML} An XML document + * @static + */ + s.parseXML = function (text) { + var xml = null; + // CocoonJS does not support XML parsing with either method. + + // Most browsers will use DOMParser + // IE fails on certain SVG files, so we have a fallback below. + try { + if (window.DOMParser) { + var parser = new DOMParser(); + xml = parser.parseFromString(text, "text/xml"); + } + } catch (e) { + } + + // Fallback for IE support. + if (!xml) { + try { + xml = new ActiveXObject("Microsoft.XMLDOM"); + xml.async = false; + xml.loadXML(text); + } catch (e) { + xml = null; + } + } + + return xml; + }; + + /** + * Parse a string into an Object. + * @method parseJSON + * @param {String} value The loaded JSON string + * @returns {Object} A JavaScript object. + */ + s.parseJSON = function (value) { + if (value == null) { + return null; + } + + try { + return JSON.parse(value); + } catch (e) { + // TODO; Handle this with a custom error? + throw e; + } + }; + + createjs.DataUtils = s; + +}()); + +//############################################################################## +// Types.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(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; +}()); + +//############################################################################## +// Methods.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(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; +}()); + +//############################################################################## +// LoadItem.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + /** + * All loaders accept an item containing the properties defined in this class. If a raw object is passed instead, + * it will not be affected, but it must contain at least a {{#crossLink "src:property"}}{{/crossLink}} property. A + * string path or HTML tag is also acceptable, but it will be automatically converted to a LoadItem using the + * {{#crossLink "create"}}{{/crossLink}} method by {{#crossLink "AbstractLoader"}}{{/crossLink}} + * @class LoadItem + * @constructor + * @since 0.6.0 + */ + function LoadItem() { + /** + * The source of the file that is being loaded. This property is required. The source can either be a + * string (recommended), or an HTML tag. + * This can also be an object, but in that case it has to include a type and be handled by a plugin. + * @property src + * @type {String} + * @default null + */ + this.src = null; + + /** + * 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. + *
      + *
    • String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
    • + *
    • LoadItem instances are returned as-is
    • + *
    • Objects are returned with any needed properties added
    • + *
    + * @method create + * @param {LoadItem|String|Object} value The load item value + * @returns {LoadItem|Object} + * @static + */ + s.create = function (value) { + if (typeof value == "string") { + var item = new LoadItem(); + item.src = value; + return item; + } else if (value instanceof s) { + return value; + } else if (value instanceof Object && value.src) { + if (value.loadTimeout == null) { + value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT; + } + return value; + } else { + throw new Error("Type not recognized."); + } + }; + + /** + * Provides a chainable shortcut method for setting a number of properties on the instance. + * + *

    Example

    + * + * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true}); + * + * @method set + * @param {Object} props A generic object containing properties to copy to the LoadItem instance. + * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.) + */ + p.set = function(props) { + for (var n in props) { this[n] = props[n]; } + return this; + }; + + createjs.LoadItem = s; + +}()); + +//############################################################################## +// 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; + +}()); + +//############################################################################## +// AbstractLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(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 +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * The AbstractMediaLoader is a base class that handles some of the shared methods and properties of loaders that + * handle HTML media elements, such as Video and Audio. + * @class AbstractMediaLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @param {String} type The type of media to load. Usually "video" or "audio". + * @extends AbstractLoader + * @constructor + */ + function AbstractMediaLoader(loadItem, preferXHR, type) { + this.AbstractLoader_constructor(loadItem, preferXHR, type); + + // public properties + this.resultFormatter = this._formatResult; + + // protected properties + this._tagSrcAttribute = "src"; + + this.on("initialize", this._updateXHR, this); + }; + + var p = createjs.extend(AbstractMediaLoader, createjs.AbstractLoader); + + // static properties + // public methods + p.load = function () { + // TagRequest will handle most of this, but Sound / Video need a few custom properties, so just handle them here. + if (!this._tag) { + this._tag = this._createTag(this._item.src); + } + + this._tag.preload = "auto"; + this._tag.load(); + + this.AbstractLoader_load(); + }; + + // protected methods + /** + * Creates a new tag for loading if it doesn't exist yet. + * @method _createTag + * @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 +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + /** + * A base class for actual data requests, such as {{#crossLink "XHRRequest"}}{{/crossLink}}, {{#crossLink "TagRequest"}}{{/crossLink}}, + * and {{#crossLink "MediaRequest"}}{{/crossLink}}. PreloadJS loaders will typically use a data loader under the + * hood to get data. + * @class AbstractRequest + * @param {LoadItem} item + * @constructor + */ + var AbstractRequest = function (item) { + this._item = item; + }; + + 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 +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * An {{#crossLink "AbstractRequest"}}{{/crossLink}} that loads HTML tags, such as images and scripts. + * @class TagRequest + * @param {LoadItem} loadItem + * @param {HTMLElement} tag + * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc. + */ + function TagRequest(loadItem, tag, srcAttribute) { + this.AbstractRequest_constructor(loadItem); + + // protected properties + /** + * The HTML tag instance that is used to load. + * @property _tag + * @type {HTMLElement} + * @protected + */ + this._tag = tag; + + /** + * The tag attribute that specifies the source, such as "src", "href", etc. + * @property _tagSrcAttribute + * @type {String} + * @protected + */ + this._tagSrcAttribute = srcAttribute; + + /** + * A method closure used for handling the tag load event. + * @property _loadedHandler + * @type {Function} + * @private + */ + this._loadedHandler = createjs.proxy(this._handleTagComplete, this); + + /** + * Determines if the element was added to the DOM automatically by PreloadJS, so it can be cleaned up after. + * @property _addedToDOM + * @type {Boolean} + * @private + */ + this._addedToDOM = false; + + }; + + 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 +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * An {{#crossLink "TagRequest"}}{{/crossLink}} that loads HTML tags for video and audio. + * @class MediaTagRequest + * @param {LoadItem} loadItem + * @param {HTMLAudioElement|HTMLVideoElement} tag + * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc. + * @constructor + */ + function MediaTagRequest(loadItem, tag, srcAttribute) { + this.AbstractRequest_constructor(loadItem); + + // protected properties + this._tag = tag; + this._tagSrcAttribute = srcAttribute; + this._loadedHandler = createjs.proxy(this._handleTagComplete, this); + }; + + var p = createjs.extend(MediaTagRequest, createjs.TagRequest); + var s = MediaTagRequest; + + // public methods + p.load = function () { + var sc = createjs.proxy(this._handleStalled, this); + this._stalledCallback = sc; + + var pc = createjs.proxy(this._handleProgress, this); + this._handleProgress = pc; + + this._tag.addEventListener("stalled", sc); + this._tag.addEventListener("progress", pc); + + // This will tell us when audio is buffered enough to play through, but not when its loaded. + // The tag doesn't keep loading in Chrome once enough has buffered, and we have decided that behaviour is sufficient. + this._tag.addEventListener && this._tag.addEventListener("canplaythrough", this._loadedHandler, false); // canplaythrough callback doesn't work in Chrome, so we use an event. + + this.TagRequest_load(); + }; + + // private methods + p._handleReadyStateChange = function () { + clearTimeout(this._loadTimeout); + // This is strictly for tags in browsers that do not support onload. + var tag = this._tag; + + // Complete is for old IE support. + if (tag.readyState == "loaded" || tag.readyState == "complete") { + this._handleTagComplete(); + } + }; + + p._handleStalled = function () { + //Ignore, let the timeout take care of it. Sometimes its not really stopped. + }; + + /** + * An XHR request has reported progress. + * @method _handleProgress + * @param {Object} event The XHR progress event. + * @private + */ + p._handleProgress = function (event) { + if (!event || event.loaded > 0 && event.total == 0) { + return; // Sometimes we get no "total", so just ignore the progress event. + } + + var newEvent = new createjs.ProgressEvent(event.loaded, event.total); + this.dispatchEvent(newEvent); + }; + + // protected methods + p._clean = function () { + this._tag.removeEventListener && this._tag.removeEventListener("canplaythrough", this._loadedHandler); + this._tag.removeEventListener("stalled", this._stalledCallback); + this._tag.removeEventListener("progress", this._progressCallback); + + this.TagRequest__clean(); + }; + + createjs.MediaTagRequest = createjs.promote(MediaTagRequest, "TagRequest"); + +}()); + +//############################################################################## +// XHRRequest.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + +// constructor + /** + * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used + * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary. + * XHR requests load the content as text or binary data, provide progress and consistent completion events, and + * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for + * cross-domain loading. + * @class XHRRequest + * @constructor + * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} + * for an overview of supported file properties. + * @extends AbstractLoader + */ + function XHRRequest (item) { + this.AbstractRequest_constructor(item); + + // protected properties + /** + * A reference to the XHR request used to load the content. + * @property _request + * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP} + * @private + */ + this._request = null; + + /** + * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1, + * typically IE9). + * @property _loadTimeout + * @type {Number} + * @private + */ + this._loadTimeout = null; + + /** + * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect + * the version, so we use capabilities to make a best guess. + * @property _xhrLevel + * @type {Number} + * @default 1 + * @private + */ + this._xhrLevel = 1; + + /** + * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be + * null until the file is loaded. + * @property _response + * @type {mixed} + * @private + */ + this._response = null; + + /** + * The response of the loaded file before it is modified. In most cases, content is converted from raw text to + * an HTML tag or a formatted object which is set to the result property, but the developer may still + * want to access the raw content as it was loaded. + * @property _rawResponse + * @type {String|Object} + * @private + */ + this._rawResponse = null; + + this._canceled = false; + + // Setup our event handlers now. + this._handleLoadStartProxy = createjs.proxy(this._handleLoadStart, this); + this._handleProgressProxy = createjs.proxy(this._handleProgress, this); + this._handleAbortProxy = createjs.proxy(this._handleAbort, this); + this._handleErrorProxy = createjs.proxy(this._handleError, this); + this._handleTimeoutProxy = createjs.proxy(this._handleTimeout, this); + this._handleLoadProxy = createjs.proxy(this._handleLoad, this); + this._handleReadyStateChangeProxy = createjs.proxy(this._handleReadyStateChange, this); + + if (!this._createXHR(item)) { + //TODO: Throw error? + } + }; + + var p = createjs.extend(XHRRequest, createjs.AbstractRequest); + +// static properties + /** + * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE. + * @property ACTIVEX_VERSIONS + * @type {Array} + * @since 0.4.2 + * @private + */ + XHRRequest.ACTIVEX_VERSIONS = [ + "Msxml2.XMLHTTP.6.0", + "Msxml2.XMLHTTP.5.0", + "Msxml2.XMLHTTP.4.0", + "MSXML2.XMLHTTP.3.0", + "MSXML2.XMLHTTP", + "Microsoft.XMLHTTP" + ]; + +// Public methods + /** + * Look up the loaded result. + * @method getResult + * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content + * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be + * returned instead. + * @return {Object} A result object containing the content that was loaded, such as: + *
      + *
    • An image tag (<image />) for images
    • + *
    • A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the + * HTML head.
    • + *
    • A style tag for CSS (<style />)
    • + *
    • Raw text for TEXT
    • + *
    • A formatted JavaScript object defined by JSON
    • + *
    • An XML document
    • + *
    • An binary arraybuffer loaded by XHR
    • + *
    + * Note that if a raw result is requested, but not found, the result will be returned instead. + */ + p.getResult = function (raw) { + if (raw && this._rawResponse) { + return this._rawResponse; + } + return this._response; + }; + + // Overrides abstract method in AbstractRequest + p.cancel = function () { + this.canceled = true; + this._clean(); + this._request.abort(); + }; + + // Overrides abstract method in AbstractLoader + p.load = function () { + if (this._request == null) { + this._handleError(); + return; + } + + //Events + if (this._request.addEventListener != null) { + this._request.addEventListener("loadstart", this._handleLoadStartProxy, false); + this._request.addEventListener("progress", this._handleProgressProxy, false); + this._request.addEventListener("abort", this._handleAbortProxy, false); + this._request.addEventListener("error", this._handleErrorProxy, false); + this._request.addEventListener("timeout", this._handleTimeoutProxy, false); + + // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. + this._request.addEventListener("load", this._handleLoadProxy, false); + this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false); + } else { + // IE9 support + this._request.onloadstart = this._handleLoadStartProxy; + this._request.onprogress = this._handleProgressProxy; + this._request.onabort = this._handleAbortProxy; + this._request.onerror = this._handleErrorProxy; + this._request.ontimeout = this._handleTimeoutProxy; + + // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. + this._request.onload = this._handleLoadProxy; + this._request.onreadystatechange = this._handleReadyStateChangeProxy; + } + + // Set up a timeout if we don't have XHR2 + if (this._xhrLevel == 1) { + this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); + } + + // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome + try { + if (!this._item.values) { + this._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: + *
      + *
    • Status codes between 400 and 599 (HTTP error range)
    • + *
    • A status of 0, but *only when the application is running on a server*. If the application is running + * on `file:`, then it may incorrectly treat an error on local (or embedded applications) as a successful + * load.
    • + *
    + * @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"); + +}()); + +//############################################################################## +// LoadQueue.js +//############################################################################## + +this.createjs = this.createjs || {}; + +/* + TODO: WINDOWS ISSUES + * No error for HTML audio in IE 678 + * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR + * No script complete handler in IE 67 TAGS (XHR is fine) + * No XML/JSON in IE6 TAGS + * Need to hide loading SVG in Opera TAGS + * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking) + * SVG no load or failure in Opera XHR + * Reported issues with IE7/8 + */ + +(function () { + "use strict"; + +// constructor + /** + * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either + * a single file, or queue of files. + * + * Creating a Queue
    + * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the preferXHR + * argument to false. + * + * var queue = new createjs.LoadQueue(true); + * + * Listening for Events
    + * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}} + * lets you add as many listeners as you want for events. You can subscribe to the following events:
      + *
    • {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all + * files
    • + *
    • {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with + * any file.
    • + *
    • {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has + * changed.
    • + *
    • {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.
    • + *
    • {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note + * that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.
    • + *
    + * + * queue.on("fileload", handleFileLoad, this); + * queue.on("complete", handleComplete, this); + * + * Adding files and manifests
    + * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a + * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are + * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you + * like. + * + * queue.loadFile("filePath/file.jpg"); + * queue.loadFile({id:"image", src:"filePath/file.jpg"}); + * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]); + * + * // Use an external manifest + * queue.loadManifest("path/to/manifest.json"); + * queue.loadManifest({src:"manifest.json", type:"manifest"}); + * + * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not + * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin + * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a + * `loadNow` argument of `true`. + * + * queue.load(); + * + * File Types
    + * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS + * should handle the majority of standard file and url formats, and works with common file extensions. If you have + * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a + * type property with any manifest item. + * + * queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.Types.SOUND}); + * + * // Note that PreloadJS will not read a file extension from the query string + * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:createjs.Types.IMAGE}); + * + * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include: + *
      + *
    • {{#crossLink "Types/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
    • + *
    • {{#crossLink "Types/CSS:property"}}{{/crossLink}}: CSS files
    • + *
    • {{#crossLink "Types/IMAGE:property"}}{{/crossLink}}: Common image formats
    • + *
    • {{#crossLink "Types/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
    • + *
    • {{#crossLink "Types/JSON:property"}}{{/crossLink}}: JSON data
    • + *
    • {{#crossLink "Types/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
    • + *
    • {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see + * {{#crossLink "AbstractLoader/loadManifest"}}{{/crossLink}}
    • + *
    • {{#crossLink "Types/SOUND:property"}}{{/crossLink}}: Audio file formats
    • + *
    • {{#crossLink "Types/SPRITESHEET:property"}}{{/crossLink}}: JSON SpriteSheet definitions. This + * will also load sub-images, and provide a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance.
    • + *
    • {{#crossLink "Types/SVG:property"}}{{/crossLink}}: SVG files
    • + *
    • {{#crossLink "Types/TEXT:property"}}{{/crossLink}}: Text files - XHR only
    • + *
    • {{#crossLink "Types/VIDEO:property"}}{{/crossLink}}: Video objects
    • + *
    • {{#crossLink "Types/XML:property"}}{{/crossLink}}: XML data
    • + *
    + * + * Note: Loader types used to be defined on LoadQueue, but have been moved to the Types class + * + * Handling Results
    + * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is + * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a + * formatted object that can be used immediately, including: + *
      + *
    • Binary: The binary loaded result
    • + *
    • CSS: A <link /> tag
    • + *
    • Image: An <img /> tag
    • + *
    • JavaScript: A <script /> tag
    • + *
    • JSON/JSONP: A formatted JavaScript Object
    • + *
    • Manifest: A JavaScript object. + *
    • Sound: An <audio /> tag + *
    • SpriteSheet: A {{#crossLink "SpriteSheet"}}{{/crossLink}} instance, containing loaded images. + *
    • SVG: An <object /> tag
    • + *
    • Text: Raw text
    • + *
    • Video: A Video DOM node
    • + *
    • XML: An XML DOM node
    • + *
    + * + * function handleFileLoad(event) { + * var item = event.item; // A reference to the item that was passed in to the LoadQueue + * var type = item.type; + * + * // Add any images to the page body. + * if (type == createjs.Types.IMAGE) { + * document.body.appendChild(event.result); + * } + * } + * + * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up + * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the + * "src" or file path can be used instead, including the `path` defined by a manifest, but not including + * a base path defined on the LoadQueue. It is recommended to always pass an id if you want to look up content. + * + * var image = queue.getResult("image"); + * document.body.appendChild(image); + * + * Raw loaded content can be accessed using the rawResult property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} + * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd + * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript, + * CSS, XML, SVG, and JSON objects, or anything loaded with XHR. + * + * var image = queue.getResult("image", true); // load the binary image data loaded with XHR. + * + * Plugins
    + * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio, + * make sure to install the SoundJS Sound class, which will help load HTML audio, + * Flash audio, and WebAudio files. This should be installed before loading any audio files. + * + * queue.installPlugin(createjs.Sound); + * + *

    Known Browser Issues

    + *
      + *
    • Browsers without audio support can not load audio files.
    • + *
    • Safari on Mac OS X can only play HTML audio if QuickTime is installed
    • + *
    • HTML Audio tags will only download until their canPlayThrough event is fired. Browsers other + * than Chrome will continue to download in the background.
    • + *
    • When loading scripts using tags, they are automatically added to the document.
    • + *
    • Scripts loaded via XHR may not be properly inspectable with browser tools.
    • + *
    • IE6 and IE7 (and some other browsers) may not be able to load XML, Text, or JSON, since they require + * XHR to work.
    • + *
    • Content loaded via tags will not show progress, and will continue to download in the background when + * canceled, although no events will be dispatched.
    • + *
    + * + * @class LoadQueue + * @param {Boolean} [preferXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP + * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR + * when necessary. + * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue + * before they are loaded. Sources beginning with a protocol such as `http://` or a relative path such as `../` + * will not receive a base path. + * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To + * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any + * string value will be passed through, but only "" and "Anonymous" are recommended. Note: The crossOrigin + * parameter is deprecated. Use LoadItem.crossOrigin instead + * + * @constructor + * @extends AbstractLoader + */ + function LoadQueue (preferXHR, basePath, crossOrigin) { + this.AbstractLoader_constructor(); + + /** + * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}. + * @property _plugins + * @type {Array} + * @private + * @since 0.6.1 + */ + this._plugins = []; + + /** + * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the + * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} + * method for more information. + * @property _typeCallbacks + * @type {Object} + * @private + */ + this._typeCallbacks = {}; + + /** + * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the + * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} + * method for more information. + * @property _extensionCallbacks + * @type {null} + * @private + */ + this._extensionCallbacks = {}; + + /** + * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and + * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed. + * @property next + * @type {LoadQueue} + * @default null + */ + this.next = null; + + /** + * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head + * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas + * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order + * specified. + * + * Any items can be set to load in order by setting the {{#crossLink "maintainOrder:property"}}{{/crossLink}} + * property on the load item, or by ensuring that only one connection can be open at a time using + * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Note that when the `maintainScriptOrder` property + * is set to `true`, scripts items are automatically set to `maintainOrder=true`, and changing the + * `maintainScriptOrder` to `false` during a load will not change items already in a queue. + * + *

    Example

    + * + * var queue = new createjs.LoadQueue(); + * queue.setMaxConnections(3); // Set a higher number to load multiple items at once + * queue.maintainScriptOrder = true; // Ensure scripts are loaded in order + * queue.loadManifest([ + * "script1.js", + * "script2.js", + * "image.png", // Load any time + * {src: "image2.png", maintainOrder: true} // Will wait for script2.js + * "image3.png", + * "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR) + * ]); + * + * @property maintainScriptOrder + * @type {Boolean} + * @default true + */ + this.maintainScriptOrder = true; + + /** + * Determines if the LoadQueue will stop processing the current queue when an error is encountered. + * @property stopOnError + * @type {Boolean} + * @default false + */ + this.stopOnError = false; + + /** + * The number of maximum open connections that a loadQueue tries to maintain. Please see + * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information. + * @property _maxConnections + * @type {Number} + * @default 1 + * @private + */ + this._maxConnections = 1; + + /** + * An internal list of all the default Loaders that are included with PreloadJS. Before an item is loaded, the + * available loader list is iterated, in the order they are included, and as soon as a loader indicates it can + * handle the content, it will be selected. The default loader, ({{#crossLink "TextLoader"}}{{/crossLink}} is + * last in the list, so it will be used if no other match is found. Typically, loaders will match based on the + * {{#crossLink "LoadItem/type"}}{{/crossLink}}, which is automatically determined using the file extension of + * the {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. + * + * Loaders can be removed from PreloadJS by simply not including them. + * + * Custom loaders installed using {{#crossLink "registerLoader"}}{{/crossLink}} will be prepended to this list + * so that they are checked first. + * @property _availableLoaders + * @type {Array} + * @private + * @since 0.6.0 + */ + this._availableLoaders = [ + createjs.FontLoader, + createjs.ImageLoader, + createjs.JavaScriptLoader, + createjs.CSSLoader, + createjs.JSONLoader, + createjs.JSONPLoader, + createjs.SoundLoader, + createjs.ManifestLoader, + createjs.SpriteSheetLoader, + createjs.XMLLoader, + createjs.SVGLoader, + createjs.BinaryLoader, + createjs.VideoLoader, + createjs.TextLoader + ]; + + /** + * The number of built in loaders, so they can't be removed by {{#crossLink "unregisterLoader"}}{{/crossLink}. + * @property _defaultLoaderLength + * @type {Number} + * @private + * @since 0.6.0 + */ + this._defaultLoaderLength = this._availableLoaders.length; + + this.init(preferXHR, basePath, crossOrigin); + } + + var p = createjs.extend(LoadQueue, createjs.AbstractLoader); + var s = LoadQueue; + + // 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) {} + + /** + * An internal initialization method, which is used for initial set up, but also to reset the LoadQueue. + * @method init + * @param preferXHR + * @param basePath + * @param crossOrigin + * @private + */ + p.init = function (preferXHR, basePath, crossOrigin) { + + // public properties + + /** + * Try and use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR + * loading depending on the requirements for a media type. For example, HTML audio can not be loaded with XHR, + * and plain text can not be loaded with tags, so it will default the the correct type instead of using the + * user-defined type. + * @type {Boolean} + * @default true + * @since 0.6.0 + */ + this.preferXHR = true; //TODO: Get/Set + this._preferXHR = true; + this.setPreferXHR(preferXHR); + + // protected properties + /** + * Whether the queue is currently paused or not. + * @property _paused + * @type {boolean} + * @private + */ + this._paused = false; + + /** + * A path that will be prepended on to the item's {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. The + * `_basePath` property will only be used if an item's source is relative, and does not include a protocol such + * as `http://`, or a relative path such as `../`. + * @property _basePath + * @type {String} + * @private + * @since 0.3.1 + */ + this._basePath = basePath; + + /** + * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded + * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by + * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues, + * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are "" + * and "Anonymous". + * @property _crossOrigin + * @type {String} + * @default "" + * @private + * @since 0.4.1 + */ + this._crossOrigin = crossOrigin; + + /** + * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first + * file is requested. + * @property _loadStartWasDispatched + * @type {Boolean} + * @default false + * @private + */ + this._loadStartWasDispatched = false; + + /** + * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when + * using a script tag to do preloading. + * @property _currentlyLoadingScript + * @type {Boolean} + * @private + */ + this._currentlyLoadingScript = null; + + /** + * An array containing the currently downloading files. + * @property _currentLoads + * @type {Array} + * @private + */ + this._currentLoads = []; + + /** + * An array containing the queued items that have not yet started downloading. + * @property _loadQueue + * @type {Array} + * @private + */ + this._loadQueue = []; + + /** + * An array containing downloads that have not completed, so that the LoadQueue can be properly reset. + * @property _loadQueueBackup + * @type {Array} + * @private + */ + this._loadQueueBackup = []; + + /** + * An object hash of items that have finished downloading, indexed by the {{#crossLink "LoadItem"}}{{/crossLink}} + * id. + * @property _loadItemsById + * @type {Object} + * @private + */ + this._loadItemsById = {}; + + /** + * An object hash of items that have finished downloading, indexed by {{#crossLink "LoadItem"}}{{/crossLink}} + * source. + * @property _loadItemsBySrc + * @type {Object} + * @private + */ + this._loadItemsBySrc = {}; + + /** + * An object hash of loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}. + * @property _loadedResults + * @type {Object} + * @private + */ + this._loadedResults = {}; + + /** + * An object hash of un-parsed loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}. + * @property _loadedRawResults + * @type {Object} + * @private + */ + this._loadedRawResults = {}; + + /** + * The number of items that have been requested. This helps manage an overall progress without knowing how large + * the files are before they are downloaded. This does not include items inside of loaders such as the + * {{#crossLink "ManifestLoader"}}{{/crossLink}}. + * @property _numItems + * @type {Number} + * @default 0 + * @private + */ + this._numItems = 0; + + /** + * The number of items that have completed loaded. This helps manage an overall progress without knowing how large + * the files are before they are downloaded. + * @property _numItemsLoaded + * @type {Number} + * @default 0 + * @private + */ + this._numItemsLoaded = 0; + + /** + * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right + * order. + * @property _scriptOrder + * @type {Array} + * @private + */ + this._scriptOrder = []; + + /** + * A list of scripts that have been loaded. Items are added to this list as null when they are + * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true + * once they are complete and have been dispatched. + * @property _loadedScripts + * @type {Array} + * @private + */ + this._loadedScripts = []; + + /** + * The last progress amount. This is used to suppress duplicate progress events. + * @property _lastProgress + * @type {Number} + * @private + * @since 0.6.0 + */ + this._lastProgress = NaN; + + }; + +// static properties + +// events + /** + * This event is fired when an individual file has loaded, and been processed. + * @event fileload + * @param {Object} target The object that dispatched the event. + * @param {String} type The event type. + * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} + * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the + * object will contain that value as a `src` property. + * @param {Object} result The HTML tag or parsed result of the loaded item. + * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted + * to a usable object. + * @since 0.3.0 + */ + + /** + * This {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when an an individual file's progress changes. + * @event fileprogress + * @since 0.3.0 + */ + + /** + * This event is fired when an individual file starts to load. + * @event filestart + * @param {Object} target The object that dispatched the event. + * @param {String} type The event type. + * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} + * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the + * object will contain that value as a property. + */ + + /** + * Although it extends {{#crossLink "AbstractLoader"}}{{/crossLink}}, the `initialize` event is never fired from + * a LoadQueue instance. + * @event initialize + * @private + */ + +// public methods + /** + * Register a custom loaders class. New loaders are given precedence over loaders added earlier and default loaders. + * It is recommended that loaders extend {{#crossLink "AbstractLoader"}}{{/crossLink}}. Loaders can only be added + * once, and will be prepended to the list of available loaders. + * @method registerLoader + * @param {Function|AbstractLoader} loader The AbstractLoader class to add. + * @since 0.6.0 + */ + p.registerLoader = function (loader) { + if (!loader || !loader.canLoadItem) { + throw new Error("loader is of an incorrect type."); + } else if (this._availableLoaders.indexOf(loader) != -1) { + throw new Error("loader already exists."); //LM: Maybe just silently fail here + } + + this._availableLoaders.unshift(loader); + }; + + /** + * Remove a custom loader added using {{#crossLink "registerLoader"}}{{/crossLink}}. Only custom loaders can be + * unregistered, the default loaders will always be available. + * @method unregisterLoader + * @param {Function|AbstractLoader} loader The AbstractLoader class to remove + */ + p.unregisterLoader = function (loader) { + var idx = this._availableLoaders.indexOf(loader); + if (idx != -1 && idx < this._defaultLoaderLength - 1) { + this._availableLoaders.splice(idx, 1); + } + }; + + /** + * Change the {{#crossLink "preferXHR:property"}}{{/crossLink}} value. Note that if this is set to `true`, it may + * fail, or be ignored depending on the browser's capabilities and the load type. + * @method setPreferXHR + * @param {Boolean} value + * @returns {Boolean} The value of {{#crossLink "preferXHR"}}{{/crossLink}} that was successfully set. + * @since 0.6.0 + */ + p.setPreferXHR = function (value) { + // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it. + //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR. + this.preferXHR = (value != false && window.XMLHttpRequest != null); + return this.preferXHR; + }; + + /** + * Stops all queued and loading items, and clears the queue. This also removes all internal references to loaded + * content, and allows the queue to be used again. + * @method removeAll + * @since 0.3.0 + */ + p.removeAll = function () { + this.remove(); + }; + + /** + * Stops an item from being loaded, and removes it from the queue. If nothing is passed, all items are removed. + * This also removes internal references to loaded item(s). + * + *

    Example

    + * + * queue.loadManifest([ + * {src:"test.png", id:"png"}, + * {src:"test.jpg", id:"jpg"}, + * {src:"test.mp3", id:"mp3"} + * ]); + * queue.remove("png"); // Single item by ID + * queue.remove("png", "test.jpg"); // Items as arguments. Mixed id and src. + * queue.remove(["test.png", "jpg"]); // Items in an Array. Mixed id and src. + * + * @method remove + * @param {String | Array} idsOrUrls* The id or ids to remove from this queue. You can pass an item, an array of + * items, or multiple items as arguments. + * @since 0.3.0 + */ + p.remove = function (idsOrUrls) { + var args = null; + + if (idsOrUrls && !Array.isArray(idsOrUrls)) { + args = [idsOrUrls]; + } else if (idsOrUrls) { + args = idsOrUrls; + } else if (arguments.length > 0) { + return; + } + + var itemsWereRemoved = false; + + // Destroy everything + if (!args) { + this.close(); + for (var n in this._loadItemsById) { + this._disposeItem(this._loadItemsById[n]); + } + this.init(this.preferXHR, this._basePath); + + // Remove specific items + } else { + while (args.length) { + var item = args.pop(); + var r = this.getResult(item); + + //Remove from the main load Queue + for (i = this._loadQueue.length - 1; i >= 0; i--) { + loadItem = this._loadQueue[i].getItem(); + if (loadItem.id == item || loadItem.src == item) { + this._loadQueue.splice(i, 1)[0].cancel(); + break; + } + } + + //Remove from the backup queue + for (i = this._loadQueueBackup.length - 1; i >= 0; i--) { + loadItem = this._loadQueueBackup[i].getItem(); + if (loadItem.id == item || loadItem.src == item) { + this._loadQueueBackup.splice(i, 1)[0].cancel(); + break; + } + } + + if (r) { + this._disposeItem(this.getItem(item)); + } else { + for (var i = this._currentLoads.length - 1; i >= 0; i--) { + var loadItem = this._currentLoads[i].getItem(); + if (loadItem.id == item || loadItem.src == item) { + this._currentLoads.splice(i, 1)[0].cancel(); + itemsWereRemoved = true; + break; + } + } + } + } + + // If this was called during a load, try to load the next item. + if (itemsWereRemoved) { + this._loadNext(); + } + } + }; + + /** + * Stops all open loads, destroys any loaded items, and resets the queue, so all items can + * be reloaded again by calling {{#crossLink "AbstractLoader/load"}}{{/crossLink}}. Items are not removed from the + * queue. To remove items use the {{#crossLink "LoadQueue/remove"}}{{/crossLink}} or + * {{#crossLink "LoadQueue/removeAll"}}{{/crossLink}} method. + * @method reset + * @since 0.3.0 + */ + p.reset = function () { + this.close(); + for (var n in this._loadItemsById) { + this._disposeItem(this._loadItemsById[n]); + } + + //Reset the queue to its start state + var a = []; + for (var i = 0, l = this._loadQueueBackup.length; i < l; i++) { + a.push(this._loadQueueBackup[i].getItem()); + } + + this.loadManifest(a, false); + }; + + /** + * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc). + * Currently, only one plugin can exist per type/extension. + * + * When a plugin is installed, a getPreloadHandlers() method will be called on it. For more information + * on this method, check out the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method in the + * {{#crossLink "SamplePlugin"}}{{/crossLink}} class. + * + * Before a file is loaded, a matching plugin has an opportunity to modify the load. If a `callback` is returned + * from the {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method, it will be invoked first, and its + * result may cancel or modify the item. The callback method can also return a `completeHandler` to be fired when + * the file is loaded, or a `tag` object, which will manage the actual download. For more information on these + * methods, check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} and {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}} + * methods on the {{#crossLink "SamplePlugin"}}{{/crossLink}}. + * + * @method installPlugin + * @param {Function} plugin The plugin class to install. + */ + p.installPlugin = function (plugin) { + if (plugin == null) { + return; + } + + if (plugin.getPreloadHandlers != null) { + this._plugins.push(plugin); + var map = plugin.getPreloadHandlers(); + map.scope = plugin; + + if (map.types != null) { + for (var i = 0, l = map.types.length; i < l; i++) { + this._typeCallbacks[map.types[i]] = map; + } + } + + if (map.extensions != null) { + for (i = 0, l = map.extensions.length; i < l; i++) { + this._extensionCallbacks[map.extensions[i]] = map; + } + } + } + }; + + /** + * Set the maximum number of concurrent connections. Note that browsers and servers may have a built-in maximum + * number of open connections, so any additional connections may remain in a pending state until the browser + * opens the connection. When loading scripts using tags, and when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}} + * is `true`, only one script is loaded at a time due to browser limitations. + * + *

    Example

    + * + * var queue = new createjs.LoadQueue(); + * queue.setMaxConnections(10); // Allow 10 concurrent loads + * + * @method setMaxConnections + * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue + * is open at any time. + */ + p.setMaxConnections = function (value) { + this._maxConnections = value; + if (!this._paused && this._loadQueue.length > 0) { + this._loadNext(); + } + }; + + /** + * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} + * method. + * + * Files are always appended to the current queue, so this method can be used multiple times to add files. + * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method. + * @method loadFile + * @param {LoadItem|Object|String} file The file object or path to load. A file can be either + *
      + *
    • A {{#crossLink "LoadItem"}}{{/crossLink}} instance
    • + *
    • An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
    • + *
    • OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}} + * in the background.
    • + *
    + * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default + * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is + * `true`, the queue will resume automatically. + * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the + * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}}, + * its files will NOT use the basePath parameter. The basePath parameter is deprecated. + * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue + * constructor, or a `path` property in a manifest definition. + */ + p.loadFile = function (file, loadNow, basePath) { + if (file == null) { + var event = new createjs.ErrorEvent("PRELOAD_NO_FILE"); + this._sendError(event); + return; + } + this._addItem(file, null, basePath); + + if (loadNow !== false) { + this.setPaused(false); + } else { + this.setPaused(true); + } + }; + + /** + * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method. + * The files in the manifest are requested in the same order, but may complete in a different order if the max + * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load + * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is + * default). + * + * Files are always appended to the current queue, so this method can be used multiple times to add files. + * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method. + * @method loadManifest + * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of + * manifests: + *
      + *
    1. A string path, which points to a manifest file, which is a JSON file that contains a "manifest" property, + * which defines the list of files to load, and can optionally contain a "path" property, which will be + * prepended to each file in the list.
    2. + *
    3. An object which defines a "src", which is a JSON or JSONP file. A "callback" can be defined for JSONP + * file. The JSON/JSONP file should contain a "manifest" property, which defines the list of files to load, + * and can optionally contain a "path" property, which will be prepended to each file in the list.
    4. + *
    5. An object which contains a "manifest" property, which defines the list of files to load, and can + * optionally contain a "path" property, which will be prepended to each file in the list.
    6. + *
    7. An Array of files to load.
    8. + *
    + * + * Each "file" in a manifest can be either: + *
      + *
    • A {{#crossLink "LoadItem"}}{{/crossLink}} instance
    • + *
    • An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
    • + *
    • OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}} + * in the background.
    • + *
    + * + * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default + * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is + * `true`, the queue will resume automatically. + * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the + * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}}, + * its files will NOT use the basePath parameter. The basePath parameter is deprecated. + * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue + * constructor, or a `path` property in a manifest definition. + */ + p.loadManifest = function (manifest, loadNow, basePath) { + var fileList = null; + var path = null; + + // Array-based list of items + if (Array.isArray(manifest)) { + if (manifest.length == 0) { + var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_EMPTY"); + this._sendError(event); + return; + } + fileList = manifest; + + // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded. + } else if (typeof(manifest) === "string") { + fileList = [ + { + src: manifest, + type: s.MANIFEST + } + ]; + + } else if (typeof(manifest) == "object") { + + // An object that defines a manifest path + if (manifest.src !== undefined) { + if (manifest.type == null) { + manifest.type = s.MANIFEST; + } else if (manifest.type != s.MANIFEST) { + var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_TYPE"); + this._sendError(event); + } + fileList = [manifest]; + + // An object that defines a manifest + } else if (manifest.manifest !== undefined) { + fileList = manifest.manifest; + path = manifest.path; + } + + // Unsupported. This will throw an error. + } else { + var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_NULL"); + this._sendError(event); + return; + } + + for (var i = 0, l = fileList.length; i < l; i++) { + this._addItem(fileList[i], path, basePath); + } + + if (loadNow !== false) { + this.setPaused(false); + } else { + this.setPaused(true); + } + + }; + + /** + * Start a LoadQueue that was created, but not automatically started. + * @method load + */ + p.load = function () { + this.setPaused(false); + }; + + /** + * Look up a {{#crossLink "LoadItem"}}{{/crossLink}} using either the "id" or "src" that was specified when loading it. Note that if no "id" was + * supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The + * `basePath` will not be part of the ID. + * @method getItem + * @param {String} value The id or src of the load item. + * @return {Object} The load item that was initially requested using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} + * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} + * event as the `item` parameter. + */ + p.getItem = function (value) { + return this._loadItemsById[value] || this._loadItemsBySrc[value]; + }; + + /** + * Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id" + * was supplied with the load item, the ID will be the "src", including a `path` property defined by a manifest. The + * `basePath` will not be part of the ID. + * @method getResult + * @param {String} value The id or src of the load item. + * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content + * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be + * returned instead. + * @return {Object} A result object containing the content that was loaded, such as: + *
      + *
    • An image tag (<image />) for images
    • + *
    • A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML + * DOM.
    • + *
    • A style tag for CSS (<style /> or <link >)
    • + *
    • Raw text for TEXT
    • + *
    • A formatted JavaScript object defined by JSON
    • + *
    • An XML document
    • + *
    • A binary arraybuffer loaded by XHR
    • + *
    • An audio tag (<audio >) for HTML audio. Note that it is recommended to use SoundJS APIs to play + * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method + * which can not be used to play audio back.
    • + *
    + * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item` + * parameter. Note that if a raw result is requested, but not found, the result will be returned instead. + */ + p.getResult = function (value, rawResult) { + var item = this._loadItemsById[value] || this._loadItemsBySrc[value]; + if (item == null) { + return null; + } + var id = item.id; + if (rawResult && this._loadedRawResults[id]) { + return this._loadedRawResults[id]; + } + return this._loadedResults[id]; + }; + + /** + * Generate an list of items loaded by this queue. + * @method getItems + * @param {Boolean} loaded Determines if only items that have been loaded should be returned. If false, in-progress + * and failed load items will also be included. + * @returns {Array} A list of objects that have been loaded. Each item includes the {{#crossLink "LoadItem"}}{{/crossLink}}, + * result, and rawResult. + * @since 0.6.0 + */ + p.getItems = function (loaded) { + var arr = []; + for (var n in this._loadItemsById) { + var item = this._loadItemsById[n]; + var result = this.getResult(n); + if (loaded === true && result == null) { + continue; + } + arr.push({ + item: item, + result: result, + rawResult: this.getResult(n, true) + }); + } + return arr; + }; + + /** + * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not + * be processed when active loads complete. LoadQueues are not paused by default. + * + * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or + * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, a paused queue will be resumed, unless the `loadNow` + * argument is `false`. + * @method setPaused + * @param {Boolean} value Whether the queue should be paused or not. + */ + p.setPaused = function (value) { + this._paused = value; + if (!this._paused) { + this._loadNext(); + } + }; + + /** + * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from + * starting to download. Note that currently any active loads will remain open, and events may be processed. + * + * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead. + * @method close + */ + p.close = function () { + while (this._currentLoads.length) { + this._currentLoads.pop().cancel(); + } + this._scriptOrder.length = 0; + this._loadedScripts.length = 0; + this.loadStartWasDispatched = false; + this._itemCount = 0; + this._lastProgress = NaN; + }; + +// protected methods + /** + * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to + * load the content. The load queue is populated with the loader instance that handles preloading, and not the load + * item that was passed in by the user. To look up the load item by id or src, use the {{#crossLink "LoadQueue.getItem"}}{{/crossLink}} + * method. + * @method _addItem + * @param {String|Object} value The item to add to the queue. + * @param {String} [path] An optional path prepended to the `src`. The path will only be prepended if the src is + * relative, and does not start with a protocol such as `http://`, or a path like `../`. If the LoadQueue was + * provided a {{#crossLink "_basePath"}}{{/crossLink}}, then it will optionally be prepended after. + * @param {String} [basePath] DeprecatedAn optional basePath passed into a {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} + * or {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} call. This parameter will be removed in a future tagged + * version. + * @private + */ + p._addItem = function (value, path, basePath) { + var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src. + if (item == null) { + return; + } // Sometimes plugins or types should be skipped. + var loader = this._createLoader(item); + if (loader != null) { + if ("plugins" in loader) { + loader.plugins = this._plugins; + } + item._loader = loader; + this._loadQueue.push(loader); + this._loadQueueBackup.push(loader); + + this._numItems++; + this._updateProgress(); + + // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time. + if ((this.maintainScriptOrder + && item.type == createjs.Types.JAVASCRIPT + //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way + ) + || item.maintainOrder === true) { + this._scriptOrder.push(item); + this._loadedScripts.push(null); + } + } + }; + + /** + * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of + * item is determined by browser support, requirements based on the file type, and developer settings. For example, + * XHR is only used for file types that support it in new browsers. + * + * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may + * alter the load item. + * @method _createLoadItem + * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded. + * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will + * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}} + * when it is added. + * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to + * the path argument. + * @return {Object} The loader instance that will be used. + * @private + */ + p._createLoadItem = function (value, path, basePath) { + var item = createjs.LoadItem.create(value); + if (item == null) { + return null; + } + + var bp = ""; // Store the generated basePath + var useBasePath = basePath || this._basePath; + + if (item.src instanceof Object) { + if (!item.type) { + return null; + } // the the src is an object, type is required to pass off to plugin + if (path) { + bp = path; + var pathMatch = createjs.URLUtils.parseURI(path); + // Also append basePath + if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) { + bp = useBasePath + bp; + } + } else if (useBasePath != null) { + bp = useBasePath; + } + } else { + // Determine Extension, etc. + var match = createjs.URLUtils.parseURI(item.src); + if (match.extension) { + item.ext = match.extension; + } + if (item.type == null) { + item.type = createjs.RequestUtils.getTypeByExtension(item.ext); + } + + // Inject path & basePath + var autoId = item.src; + if (!match.absolute && !match.relative) { + if (path) { + bp = path; + var pathMatch = createjs.URLUtils.parseURI(path); + autoId = path + autoId; + // Also append basePath + if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) { + bp = useBasePath + bp; + } + } else if (useBasePath != null) { + bp = useBasePath; + } + } + item.src = bp + item.src; + } + item.path = bp; + + // If there's no id, set one now. + if (item.id === undefined || item.id === null || item.id === "") { + item.id = autoId; + } + + // Give plugins a chance to modify the loadItem: + var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext]; + if (customHandler) { + // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately) + var result = customHandler.callback.call(customHandler.scope, item, this); + + // The plugin will handle the load, or has canceled it. Ignore it. + if (result === false) { + return null; + + // Load as normal: + } else if (result === true) { + // Do Nothing + + // Result is a loader class: + } else if (result != null) { + item._loader = result; + } + + // Update the extension in case the type changed: + match = createjs.URLUtils.parseURI(item.src); + if (match.extension != null) { + item.ext = match.extension; + } + } + + // Store the item for lookup. This also helps clean-up later. + this._loadItemsById[item.id] = item; + this._loadItemsBySrc[item.src] = item; + + if (item.crossOrigin == null) { + item.crossOrigin = this._crossOrigin; + } + + return item; + }; + + /** + * Create a loader for a load item. + * @method _createLoader + * @param {Object} item A formatted load item that can be used to generate a loader. + * @return {AbstractLoader} A loader that can be used to load content. + * @private + */ + p._createLoader = function (item) { + if (item._loader != null) { // A plugin already specified a loader + return item._loader; + } + + // Initially, try and use the provided/supported XHR mode: + var preferXHR = this.preferXHR; + + for (var i = 0; i < this._availableLoaders.length; i++) { + var loader = this._availableLoaders[i]; + if (loader && loader.canLoadItem(item)) { + return new loader(item, preferXHR); + } + } + + // TODO: Log error (requires createjs.log) + return null; + }; + + /** + * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event + * is processed. The queue will "fill up" any empty slots, up to the max connection specified using + * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded + * using tags, which have to be loaded one at a time to maintain load order. + * @method _loadNext + * @private + */ + p._loadNext = function () { + if (this._paused) { + return; + } + + // Only dispatch loadstart event when the first file is loaded. + if (!this._loadStartWasDispatched) { + this._sendLoadStart(); + this._loadStartWasDispatched = true; + } + + // The queue has completed. + if (this._numItems == this._numItemsLoaded) { + this.loaded = true; + this._sendComplete(); + + // Load the next queue, if it has been defined. + if (this.next && this.next.load) { + this.next.load(); + } + } else { + this.loaded = false; + } + + // Must iterate forwards to load in the right order. + for (var i = 0; i < this._loadQueue.length; i++) { + if (this._currentLoads.length >= this._maxConnections) { + break; + } + var loader = this._loadQueue[i]; + + // Determine if we should be only loading one tag-script at a time: + // Note: maintainOrder items don't do anything here because we can hold onto their loaded value + if (!this._canStartLoad(loader)) { + continue; + } + this._loadQueue.splice(i, 1); + i--; + this._loadItem(loader); + } + }; + + /** + * Begin loading an item. Event listeners are not added to the loaders until the load starts. + * @method _loadItem + * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader. + * @private + */ + p._loadItem = function (loader) { + loader.on("fileload", this._handleFileLoad, this); + loader.on("progress", this._handleProgress, this); + loader.on("complete", this._handleFileComplete, this); + loader.on("error", this._handleError, this); + loader.on("fileerror", this._handleFileError, this); + this._currentLoads.push(loader); + this._sendFileStart(loader.getItem()); + loader.load(); + }; + + /** + * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}} + * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}} + * events. + * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader. + * @private + * @since 0.6.0 + */ + p._handleFileLoad = function (event) { + event.target = null; + this.dispatchEvent(event); + }; + + /** + * The callback that is fired when a loader encounters an error from an internal file load operation. This enables + * loaders like M + * @param event + * @private + */ + p._handleFileError = function (event) { + var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, event.item); + this._sendError(newEvent); + }; + + /** + * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} + * is set to `true`. + * @method _handleError + * @param {ErrorEvent} event The error event, containing relevant error information. + * @private + */ + p._handleError = function (event) { + var loader = event.target; + this._numItemsLoaded++; + + this._finishOrderedItem(loader, true); + this._updateProgress(); + + var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem()); + // TODO: Propagate actual error message. + + this._sendError(newEvent); + + if (!this.stopOnError) { + this._removeLoadItem(loader); + this._cleanLoadItem(loader); + this._loadNext(); + } else { + this.setPaused(true); + } + }; + + /** + * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and + * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML, + * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. + * @method _handleFileComplete + * @param {Event} event The event object from the loader. + * @private + */ + p._handleFileComplete = function (event) { + var loader = event.target; + var item = loader.getItem(); + + var result = loader.getResult(); + this._loadedResults[item.id] = result; + var rawResult = loader.getResult(true); + if (rawResult != null && rawResult !== result) { + this._loadedRawResults[item.id] = rawResult; + } + + this._saveLoadedItems(loader); + + // Remove the load item + this._removeLoadItem(loader); + + if (!this._finishOrderedItem(loader)) { + // The item was NOT managed, so process it now + this._processFinishedLoad(item, loader); + } + + // Clean up the load item + this._cleanLoadItem(loader); + }; + + /** + * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}). + * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the + * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}} + * methods. + * @method _saveLoadedItems + * @param {AbstractLoader} loader + * @protected + * @since 0.6.0 + */ + p._saveLoadedItems = function (loader) { + // TODO: Not sure how to handle this. Would be nice to expose the items. + // Loaders may load sub-items. This adds them to this queue + var list = loader.getLoadedItems(); + if (list === null) { + return; + } + + for (var i = 0; i < list.length; i++) { + var item = list[i].item; + + // Store item lookups + this._loadItemsBySrc[item.src] = item; + this._loadItemsById[item.id] = item; + + // Store loaded content + this._loadedResults[item.id] = list[i].result; + this._loadedRawResults[item.id] = list[i].rawResult; + } + }; + + /** + * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if + * so, trigger prior items to trigger as well. + * @method _finishOrderedItem + * @param {AbstractLoader} loader + * @param {Boolean} loadFailed + * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate + * behaviour if it is. + * @private + */ + p._finishOrderedItem = function (loader, loadFailed) { + var item = loader.getItem(); + + if ((this.maintainScriptOrder && item.type == createjs.Types.JAVASCRIPT) + || item.maintainOrder) { + + //TODO: Evaluate removal of the _currentlyLoadingScript + if (loader instanceof createjs.JavaScriptLoader) { + this._currentlyLoadingScript = false; + } + + var index = createjs.indexOf(this._scriptOrder, item); + if (index == -1) { + return false; + } // This loader no longer exists + this._loadedScripts[index] = (loadFailed === true) ? true : item; + + this._checkScriptLoadOrder(); + return true; + } + + return false; + }; + + /** + * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the + * order they were added, but with a "null" value. When they are completed, the value is set to the load item, + * and then when they are processed and dispatched, the value is set to `true`. This method simply + * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are + * dispatched. + * @method _checkScriptLoadOrder + * @private + */ + p._checkScriptLoadOrder = function () { + var l = this._loadedScripts.length; + + for (var i = 0; i < l; i++) { + var item = this._loadedScripts[i]; + if (item === null) { + break; + } // This is still loading. Do not process further. + if (item === true) { + continue; + } // This has completed, and been processed. Move on. + + var loadItem = this._loadedResults[item.id]; + if (item.type == createjs.Types.JAVASCRIPT) { + // Append script tags to the head automatically. + createjs.DomUtils.appendToHead(loadItem); + } + + var loader = item._loader; + this._processFinishedLoad(item, loader); + this._loadedScripts[i] = true; + } + }; + + /** + * A file has completed loading, and the LoadQueue can move on. This triggers the complete event, and kick-starts + * the next item. + * @method _processFinishedLoad + * @param {LoadItem|Object} item + * @param {AbstractLoader} loader + * @protected + */ + p._processFinishedLoad = function (item, loader) { + this._numItemsLoaded++; + + // Since LoadQueue needs maintain order, we can't append scripts in the loader. + // So we do it here instead. Or in _checkScriptLoadOrder(); + if (!this.maintainScriptOrder && item.type == createjs.Types.JAVASCRIPT) { + var tag = loader.getTag(); + createjs.DomUtils.appendToHead(tag); + } + + this._updateProgress(); + this._sendFileComplete(item, loader); + this._loadNext(); + }; + + /** + * Ensure items with `maintainOrder=true` that are before the specified item have loaded. This only applies to + * JavaScript items that are being loaded with a TagLoader, since they have to be loaded and completed before + * the script can even be started, since it exist in the DOM while loading. + * @method _canStartLoad + * @param {AbstractLoader} loader The loader for the item + * @return {Boolean} Whether the item can start a load or not. + * @private + */ + p._canStartLoad = function (loader) { + if (!this.maintainScriptOrder || loader.preferXHR) { + return true; + } + var item = loader.getItem(); + if (item.type != createjs.Types.JAVASCRIPT) { + return true; + } + if (this._currentlyLoadingScript) { + return false; + } + + var index = this._scriptOrder.indexOf(item); + var i = 0; + while (i < index) { + var checkItem = this._loadedScripts[i]; + if (checkItem == null) { + return false; + } + i++; + } + this._currentlyLoadingScript = true; + return true; + }; + + /** + * A load item is completed or was canceled, and needs to be removed from the LoadQueue. + * @method _removeLoadItem + * @param {AbstractLoader} loader A loader instance to remove. + * @private + */ + p._removeLoadItem = function (loader) { + var l = this._currentLoads.length; + for (var i = 0; i < l; i++) { + if (this._currentLoads[i] == loader) { + this._currentLoads.splice(i, 1); + break; + } + } + }; + + /** + * Remove unneeded references from a loader. + * + * @param loader + * @private + */ + p._cleanLoadItem = function(loader) { + var item = loader.getItem(); + if (item) { + delete item._loader; + } + } + + /** + * An item has dispatched progress. Propagate that progress, and update the LoadQueue's overall progress. + * @method _handleProgress + * @param {ProgressEvent} event The progress event from the item. + * @private + */ + p._handleProgress = function (event) { + var loader = event.target; + this._sendFileProgress(loader.getItem(), loader.progress); + this._updateProgress(); + }; + + /** + * Overall progress has changed, so determine the new progress amount and dispatch it. This changes any time an + * item dispatches progress or completes. Note that since we don't always know the actual filesize of items before + * they are loaded. In this case, we define a "slot" for each item (1 item in 10 would get 10%), and then append + * loaded progress on top of the already-loaded items. + * + * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be: + *
      + *
    • 5/10 of the items in the queue (50%)
    • + *
    • plus 20% of item 6's slot (2%)
    • + *
    • equals 52%
    • + *
    + * @method _updateProgress + * @private + */ + p._updateProgress = function () { + var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress + var remaining = this._numItems - this._numItemsLoaded; + if (remaining > 0) { + var chunk = 0; + for (var i = 0, l = this._currentLoads.length; i < l; i++) { + chunk += this._currentLoads[i].progress; + } + loaded += (chunk / remaining) * (remaining / this._numItems); + } + + if (this._lastProgress != loaded) { + this._sendProgress(loaded); + this._lastProgress = loaded; + } + }; + + /** + * Clean out item results, to free them from memory. Mainly, the loaded item and results are cleared from internal + * hashes. + * @method _disposeItem + * @param {LoadItem|Object} item The item that was passed in for preloading. + * @private + */ + p._disposeItem = function (item) { + delete this._loadedResults[item.id]; + delete this._loadedRawResults[item.id]; + delete this._loadItemsById[item.id]; + delete this._loadItemsBySrc[item.src]; + }; + + /** + * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}} + * event for details on the event payload. + * @method _sendFileProgress + * @param {LoadItem|Object} item The item that is being loaded. + * @param {Number} progress The amount the item has been loaded (between 0 and 1). + * @protected + */ + p._sendFileProgress = function (item, progress) { + if (this._isCanceled() || this._paused) { + return; + } + if (!this.hasEventListener("fileprogress")) { + return; + } + + //LM: Rework ProgressEvent to support this? + var event = new createjs.Event("fileprogress"); + event.progress = progress; + event.loaded = progress; + event.total = 1; + event.item = item; + + this.dispatchEvent(event); + }; + + /** + * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for + * details on the event payload. + * @method _sendFileComplete + * @param {LoadItemObject} item The item that is being loaded. + * @param {AbstractLoader} loader + * @protected + */ + p._sendFileComplete = function (item, loader) { + if (this._isCanceled() || this._paused) { + return; + } + + var event = new createjs.Event("fileload"); + event.loader = loader; + event.item = item; + event.result = this._loadedResults[item.id]; + event.rawResult = this._loadedRawResults[item.id]; + + // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this. + if (item.completeHandler) { + item.completeHandler(event); + } + + this.hasEventListener("fileload") && this.dispatchEvent(event); + }; + + /** + * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see + * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload. + * @method _sendFileStart + * @param {LoadItem|Object} item The item that is being loaded. + * @protected + */ + p._sendFileStart = function (item) { + var event = new createjs.Event("filestart"); + event.item = item; + this.hasEventListener("filestart") && this.dispatchEvent(event); + }; + + p.toString = function () { + return "[PreloadJS LoadQueue]"; + }; + + createjs.LoadQueue = createjs.promote(LoadQueue, "AbstractLoader"); +}()); + +//############################################################################## +// TextLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for Text files. + * @class TextLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function TextLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, true, createjs.Types.TEXT); + }; + + var p = createjs.extend(TextLoader, createjs.AbstractLoader); + var s = TextLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader loads items that are of type {{#crossLink "Types/TEXT:property"}}{{/crossLink}}, + * but is also the default loader if a file type can not be determined. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.TEXT; + }; + + createjs.TextLoader = createjs.promote(TextLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// BinaryLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for binary files. This is useful for loading web audio, or content that requires an ArrayBuffer. + * @class BinaryLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function BinaryLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, true, createjs.Types.BINARY); + this.on("initialize", this._updateXHR, this); + }; + + var p = createjs.extend(BinaryLoader, createjs.AbstractLoader); + var s = BinaryLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/BINARY:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.BINARY; + }; + + // private methods + /** + * Before the item loads, set the response type to "arraybuffer" + * @property _updateXHR + * @param {Event} event + * @private + */ + p._updateXHR = function (event) { + event.loader.setResponseType("arraybuffer"); + }; + + createjs.BinaryLoader = createjs.promote(BinaryLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// CSSLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for CSS files. + * @class CSSLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @extends AbstractLoader + * @constructor + */ + function CSSLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.CSS); + + // public properties + this.resultFormatter = this._formatResult; + + // protected properties + this._tagSrcAttribute = "href"; + + if (preferXHR) { + this._tag = createjs.Elements.style(); + } else { + this._tag = createjs.Elements.link(); + } + + this._tag.rel = "stylesheet"; + this._tag.type = "text/css"; + }; + + var p = createjs.extend(CSSLoader, createjs.AbstractLoader); + var s = CSSLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/CSS:property"}}{{/crossLink}}. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.CSS; + }; + + // protected methods + /** + * The result formatter for CSS files. + * @method _formatResult + * @param {AbstractLoader} loader + * @returns {HTMLLinkElement|HTMLStyleElement} + * @private + */ + p._formatResult = function (loader) { + if (this._preferXHR) { + var tag = loader.getTag(); + + if (tag.styleSheet) { // IE + tag.styleSheet.cssText = loader.getResult(true); + } else { + var textNode = createjs.Elements.text(loader.getResult(true)); + tag.appendChild(textNode); + } + } else { + tag = this._tag; + } + + createjs.DomUtils.appendToHead(tag); + + return tag; + }; + + createjs.CSSLoader = createjs.promote(CSSLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// FontLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + +// constructor: + /** + * A loader that handles font files, CSS definitions, and CSS paths. FontLoader doesn't actually preload fonts + * themselves, but rather generates CSS definitions, and then tests the size changes on an HTML5 Canvas element. + * + * Note that FontLoader does not support tag-based loading due to the requirement that CSS be read to determine the + * font definitions to test for. + * @class FontLoader + * @param {LoadItem|object|string} loadItem The item to be loaded. + * @extends AbstractLoader + * @constructor + **/ + function FontLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, loadItem.type); + + // private properties: + /** + * A lookup of font faces to load. + * @property _faces + * @protected + * @type Object + **/ + this._faces = {}; + + /** + * A list of font faces currently being "watched". Watched fonts will be tested on a regular interval, and be + * removed from this list when they are complete. + * @oroperty _watched + * @type {Array} + * @protected + */ + this._watched = []; + + /** + * A count of the total font faces to load. + * @property _count + * @type {number} + * @protected + * @default 0 + */ + this._count = 0; + + /** + * The interval for checking if fonts have been loaded. + * @property _watchInterval + * @type {Number} + * @protected + */ + this._watchInterval = null; + + /** + * The timeout for determining if a font can't be loaded. Uses the LoadItem {{#crossLink "LoadImte/timeout:property"}}{{/crossLink}} + * value. + * @property _loadTimeout + * @type {Number} + * @protected + */ + this._loadTimeout = null; + /** + * Determines if generated CSS should be injected into the document. + * @property _injectCSS + * @type {boolean} + * @protected + */ + this._injectCSS = (loadItem.injectCSS === undefined) ? true : loadItem.injectCSS; + + this.dispatchEvent("initialize"); + } + var p = createjs.extend(FontLoader, createjs.AbstractLoader); + + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/FONT: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 + */ + FontLoader.canLoadItem = function (item) { + return item.type == createjs.Types.FONT || item.type == createjs.Types.FONTCSS; + }; + +// static properties: + /** + * Sample text used by the FontLoader to determine if the font has been loaded. The sample text size is compared + * to the loaded font size, and a change indicates that the font has completed. + * @property sampleText + * @type {String} + * @default abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ + * @static + * @private + */ + FontLoader.sampleText = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + /** + * The canvas context used to test the font size. Note that this currently requires an HTML DOM. + * @property _ctx + * @type {CanvasRenderingContext2D} + * @static + * @private + */ + FontLoader._ctx = document.createElement("canvas").getContext("2d"); // TODO: Consider a method to do this like EaselJS Stage has. + + /** + * A list of reference fonts to test. Multiple faces are tested to address the rare case of a loaded font being the + * exact same dimensions as the test font. + * @property _referenceFonts + * @type {Array} + * @default ["serif", "monospace"] + * @private + */ + FontLoader._referenceFonts = ["serif","monospace"]; + + /** + * A regular expression that pulls out possible style values from the font name. + *
      + *
    • This includes font names that include thin, normal, book, regular, medium, black, and heavy (such as + * "Arial Black")
    • + *
    • Weight modifiers including extra, ultra, semi, demi, light, and bold (such as "WorkSans SemiBold")
    • + *
    + * + * Weight descriptions map to font weight values by default using the following (from + * http://www.w3.org/TR/css3-fonts/#font-weight-numeric-values): + *
      + *
    • 100 - Thin
    • + *
    • 200 - Extra Light, Ultra Light
    • + *
    • 300 - Light, Semi Light, Demi Light
    • + *
    • 400 - Normal, Book, Regular
    • + *
    • 500 - Medium
    • + *
    • 600 - Semi Bold, Demi Bold
    • + *
    • 700 - Bold
    • + *
    • 800 - Extra Bold, Ultra Bold
    • + *
    • 900 - Black, Heavy
    • + *
    + * @property WEIGHT_REGEX + * @type {RegExp} + * @static + */ + FontLoader.WEIGHT_REGEX = /[- ._]*(thin|normal|book|regular|medium|black|heavy|[1-9]00|(?:extra|ultra|semi|demi)?[- ._]*(?:light|bold))[- ._]*/ig; + + /** + * A regular expression that pulls out possible style values from the font name. These include "italic" + * and "oblique". + * @property STYLE_REGEX + * @type {RegExp} + * @static + */ + FontLoader.STYLE_REGEX = /[- ._]*(italic|oblique)[- ._]*/ig; + + /** + * A lookup of font types for generating a CSS definition. For example, TTF fonts requires a "truetype" type. + * @property FONT_FORMAT + * @type {Object} + * @static + */ + FontLoader.FONT_FORMAT = {woff2:"woff2", woff:"woff", ttf:"truetype", otf:"truetype"}; + + /** + * A lookup of font weights based on a name. These values are from http://www.w3.org/TR/css3-fonts/#font-weight-numeric-values. + * @property FONT_WEIGHT + * @type {Object} + * @static + */ + FontLoader.FONT_WEIGHT = {thin:100, extralight:200, ultralight:200, light:300, semilight:300, demilight:300, book:"normal", regular:"normal", semibold:600, demibold:600, extrabold:800, ultrabold:800, black:900, heavy:900}; + + /** + * The frequency in milliseconds to check for loaded fonts. + * @property WATCH_DURATION + * @type {number} + * @default 10 + * @static + */ + FontLoader.WATCH_DURATION = 10; +// public methods: + p.load = function() { + if (this.type == createjs.Types.FONTCSS) { + var loaded = this._watchCSS(); + + // If the CSS is not ready, it will create a request, which AbstractLoader can handle. + if (!loaded) { + this.AbstractLoader_load(); + return; + } + + } else if (this._item.src instanceof Array) { + this._watchFontArray(); + } else { + var def = this._defFromSrc(this._item.src); + this._watchFont(def); + this._injectStyleTag(this._cssFromDef(def)); + } + + this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); + + this.dispatchEvent("loadstart"); + }; + + /** + * The font load has timed out. This is called via a setTimeout. + * callback. + * @method _handleTimeout + * @protected + */ + p._handleTimeout = function () { + this._stopWatching(); + this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT")); + }; + + // WatchCSS does the work for us, and provides a modified src. + p._createRequest = function() { + return this._request; + }; + + // Events come from the internal XHR loader. + p.handleEvent = function (event) { + switch (event.type) { + case "complete": + this._rawResult = event.target._response; + this._result = true; + this._parseCSS(this._rawResult); + break; + + case "error": + this._stopWatching(); + this.AbstractLoader_handleEvent(event); + break; + } + }; + +// private methods: + /** + * Determine if the provided CSS is a string definition, CSS HTML element, or a CSS file URI. Depending on the + * format, the CSS will be parsed, or loaded. + * @method _watchCSS + * @returns {boolean} Whether or not the CSS is ready + * @protected + */ + p._watchCSS = function() { + var src = this._item.src; + + // An HTMLElement was passed in. Just use it. + if (src instanceof HTMLStyleElement) { + if (this._injectCSS && !src.parentNode) { (document.head || document.getElementsByTagName('head')[0]).appendChild(src); } + this._injectCSS = false; + src = "\n"+src.textContent; + } + + // A CSS string was passed in. Parse and use it + if (src.search(/\n|\r|@font-face/i) !== -1) { // css string. + this._parseCSS(src); + return true; + } + + // Load a CSS Path. Note that we CAN NOT load it without XHR because we need to read the CSS definition + this._request = new createjs.XHRRequest(this._item); + return false; + }; + + /** + * Parse a CSS string to determine the fonts to load. + * @method _parseCSS + * @param {String} css The CSS string to parse + * @protected + */ + p._parseCSS = function(css) { + var regex = /@font-face\s*\{([^}]+)}/g + while (true) { + var result = regex.exec(css); + if (!result) { break; } + this._watchFont(this._parseFontFace(result[1])); + } + this._injectStyleTag(css); + }; + + /** + * The provided fonts were an array of object or string definitions. Parse them, and inject any that are ready. + * @method _watchFontArray + * @protected + */ + p._watchFontArray = function() { + var arr = this._item.src, css = "", def; + for (var i=arr.length-1; i>=0; i--) { + var o = arr[i]; + if (typeof o === "string") { def = this._defFromSrc(o) } + else { def = this._defFromObj(o); } + this._watchFont(def); + css += this._cssFromDef(def)+"\n"; + } + this._injectStyleTag(css); + }; + + /** + * Inject any style definitions into the document head. This is necessary when the definition is just a string or + * object definition in order for the styles to be applied to the document. If the loaded fonts are already HTML CSS + * elements, they don't need to be appended again. + * @method _injectStyleTag + * @param {String} css The CSS string content to be appended to the + * @protected + */ + p._injectStyleTag = function(css) { + if (!this._injectCSS) { return; } + var head = document.head || document.getElementsByTagName('head')[0]; + var styleTag = document.createElement("style"); + styleTag.type = "text/css"; + if (styleTag.styleSheet){ + styleTag.styleSheet.cssText = css; + } else { + styleTag.appendChild(document.createTextNode(css)); + } + head.appendChild(styleTag); + }; + + /** + * Determine the font face from a CSS definition. + * @method _parseFontFace + * @param {String} str The CSS string definition + * @protected + * @return {String} A modified CSS object containing family name, src, style, and weight + */ + p._parseFontFace = function(str) { + var family = this._getCSSValue(str, "font-family"), src = this._getCSSValue(str, "src"); + if (!family || !src) { return null; } + return this._defFromObj({ + family: family, + src: src, + style: this._getCSSValue(str, "font-style"), + weight: this._getCSSValue(str, "font-weight") + }); + }; + + /** + * Add a font to the list of fonts currently being watched. If the font is already watched or loaded, it won't be + * added again. + * @method _watchFont + * @param {Object} def The font definition + * @protected + */ + p._watchFont = function(def) { + if (!def || this._faces[def.id]) { return; } + this._faces[def.id] = def; + this._watched.push(def); + this._count++; + + this._calculateReferenceSizes(def); + this._startWatching(); + }; + + /** + * Create a interval to check for loaded fonts. Only one interval is used for all fonts. The fonts are checked based + * on the {{#crossLink "FontLoader/WATCH_DURATION:property"}}{{/crossLink}}. + * @method _startWatching + * @protected + */ + p._startWatching = function() { + if (this._watchInterval != null) { return; } + this._watchInterval = setInterval(createjs.proxy(this._watch, this), FontLoader.WATCH_DURATION); + }; + + /** + * Clear the interval used to check fonts. This happens when all fonts are loaded, or an error occurs, such as a + * CSS file error, or a load timeout. + * @method _stopWatching + * @protected + */ + p._stopWatching = function() { + clearInterval(this._watchInterval); + clearTimeout(this._loadTimeout); + this._watchInterval = null; + }; + + /** + * Check all the fonts that have not been loaded. The fonts are drawn to a canvas in memory, and if their font size + * varies from the default text size, then the font is considered loaded. + * + * A {{#crossLink "AbstractLoader/fileload"}}{{/crossLink}} event will be dispatched when each file is loaded, along + * with the font family name as the `item` value. A {{#crossLink "ProgressEvent"}}{{/crossLink}} is dispatched a + * maximum of one time per check when any fonts are loaded, with the {{#crossLink "ProgressEvent/progress:property"}}{{/crossLink}} + * value showing the percentage of fonts that have loaded. + * @method _watch + * @protected + */ + p._watch = function() { + var defs = this._watched, refFonts = FontLoader._referenceFonts, l = defs.length; + for (var i = l - 1; i >= 0; i--) { + var def = defs[i], refs = def.refs; + for (var j = refs.length - 1; j >= 0; j--) { + var w = this._getTextWidth(def.family + "," + refFonts[j], def.weight, def.style); + if (w != refs[j]) { + var event = new createjs.Event("fileload"); + def.type = "font-family"; + event.item = def; + this.dispatchEvent(event); + defs.splice(i, 1); + break; + } + } + } + if (l !== defs.length) { + var event = new createjs.ProgressEvent(this._count-defs.length, this._count); + this.dispatchEvent(event); + } + if (l === 0) { + this._stopWatching(); + this._sendComplete(); + } + }; + + /** + * Determine the default size of the reference fonts used to compare against loaded fonts. + * @method _calculateReferenceSizes + * @param {Object} def The font definition to get the size of. + * @protected + */ + p._calculateReferenceSizes = function(def) { + var refFonts = FontLoader._referenceFonts; + var refs = def.refs = []; + for (var i=0; iwithout requiring CORS. + * JSONP files are loaded as JavaScript, and the "callback" is executed once they are loaded. The callback in the + * JSONP must match the callback passed to the loadItem. + * + *

    Example JSONP

    + * + * callbackName({ + * "name": "value", + * "num": 3, + * "obj": { "bool":true } + * }); + * + *

    Example

    + * + * var loadItem = {id:"json", type:"jsonp", src:"http://server.com/text.json", callback:"callbackName"} + * var queue = new createjs.LoadQueue(); + * queue.on("complete", handleComplete); + * queue.loadItem(loadItem); + * + * function handleComplete(event) } + * var json = queue.getResult("json"); + * console.log(json.obj.bool); // true + * } + * + * JSONP files loaded concurrently require a unique callback. To ensure JSONP files are loaded in order, + * either use the {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} method (set to 1), or set + * {{#crossLink "LoadItem/maintainOrder:property"}}{{/crossLink}} on items with the same callback. + * + * Important note: Some browsers will prevent JSONP from firing the callback if the file was loaded as JSON, and not + * JavaScript. You may have to have your server give you a JavaScript mime-type for this to work. + * + * @class JSONPLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function JSONPLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, false, createjs.Types.JSONP); + this.setTag(createjs.Elements.script()); + this.getTag().type = "text/javascript"; + }; + + var p = createjs.extend(JSONPLoader, createjs.AbstractLoader); + var s = JSONPLoader; + + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/JSONP:property"}}{{/crossLink}}. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.JSONP; + }; + + // public methods + p.cancel = function () { + this.AbstractLoader_cancel(); + this._dispose(); + }; + + /** + * Loads the JSONp file. Because of the unique loading needs of JSONp + * we don't use the AbstractLoader.load() method. + * + * @method load + * + */ + p.load = function () { + if (this._item.callback == null) { + throw new Error('callback is required for loading JSONP requests.'); + } + + // TODO: Look into creating our own iFrame to handle the load + // In the first attempt, FF did not get the result + // result instanceof Object did not work either + // so we would need to clone the result. + if (window[this._item.callback] != null) { + throw new Error( + "JSONP callback '" + + this._item.callback + + "' already exists on window. You need to specify a different callback or re-name the current one."); + } + + window[this._item.callback] = createjs.proxy(this._handleLoad, this); + createjs.DomUtils.appendToBody(this._tag); + + this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); + + // Load the tag + this._tag.src = this._item.src; + }; + + // private methods + /** + * Handle the JSONP callback, which is a public method defined on `window`. + * @method _handleLoad + * @param {Object} data The formatted JSON data. + * @private + */ + p._handleLoad = function (data) { + this._result = this._rawResult = data; + this._sendComplete(); + + this._dispose(); + }; + + /** + * The tag request has not loaded within the time specfied in loadTimeout. + * @method _handleError + * @param {Object} event The XHR error event. + * @private + */ + p._handleTimeout = function () { + this._dispose(); + this.dispatchEvent(new createjs.ErrorEvent("timeout")); + }; + + /** + * Clean up the JSONP load. This clears out the callback and script tag that this loader creates. + * @method _dispose + * @private + */ + p._dispose = function () { + createjs.DomUtils.removeChild(this._tag); + delete window[this._item.callback]; + + clearTimeout(this._loadTimeout); + }; + + createjs.JSONPLoader = createjs.promote(JSONPLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// ManifestLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for JSON manifests. Items inside the manifest are loaded before the loader completes. To load manifests + * using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} as part of the + * {{#crossLink "LoadItem"}}{{/crossLink}}. + * + * The list of files in the manifest must be defined on the top-level JSON object in a `manifest` property. This + * example shows a sample manifest definition, as well as how to to include a sub-manifest. + * + * { + * "path": "assets/", + * "manifest": [ + * "image.png", + * {"src": "image2.png", "id":"image2"}, + * {"src": "sub-manifest.json", "type":"manifest", "callback":"jsonCallback"} + * ] + * } + * + * When a ManifestLoader has completed loading, the parent loader (usually a {{#crossLink "LoadQueue"}}{{/crossLink}}, + * but could also be another ManifestLoader) will inherit all the loaded items, so you can access them directly. + * + * Note that the {{#crossLink "JSONLoader"}}{{/crossLink}} and {{#crossLink "JSONPLoader"}}{{/crossLink}} are + * higher priority loaders, so manifests must set the {{#crossLink "LoadItem"}}{{/crossLink}} + * {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property to {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}}. + * + * Additionally, some browsers require the server to serve a JavaScript mime-type for JSONP, so it may not work in + * some conditions. + * @class ManifestLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function ManifestLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.MANIFEST); + + // Public Properties + /** + * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}, + * used to pass plugins to new LoadQueues that may be created. + * @property _plugins + * @type {Array} + * @private + * @since 0.6.1 + */ + this.plugins = null; + + + // Protected Properties + /** + * An internal {{#crossLink "LoadQueue"}}{{/crossLink}} that loads the contents of the manifest. + * @property _manifestQueue + * @type {LoadQueue} + * @private + */ + this._manifestQueue = null; + }; + + var p = createjs.extend(ManifestLoader, createjs.AbstractLoader); + var s = ManifestLoader; + + // static properties + /** + * The amount of progress that the manifest itself takes up. + * @property MANIFEST_PROGRESS + * @type {number} + * @default 0.25 (25%) + * @private + * @static + */ + s.MANIFEST_PROGRESS = 0.25; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.MANIFEST; + }; + + // public methods + p.load = function () { + this.AbstractLoader_load(); + }; + + // protected methods + p._createRequest = function() { + var callback = this._item.callback; + if (callback != null) { + this._request = new createjs.JSONPLoader(this._item); + } else { + this._request = new createjs.JSONLoader(this._item); + } + }; + + p.handleEvent = function (event) { + switch (event.type) { + case "complete": + this._rawResult = event.target.getResult(true); + this._result = event.target.getResult(); + this._sendProgress(s.MANIFEST_PROGRESS); + this._loadManifest(this._result); + return; + case "progress": + event.loaded *= s.MANIFEST_PROGRESS; + this.progress = event.loaded / event.total; + if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } + this._sendProgress(event); + return; + } + this.AbstractLoader_handleEvent(event); + }; + + p.destroy = function() { + this.AbstractLoader_destroy(); + this._manifestQueue.close(); + }; + + /** + * Create and load the manifest items once the actual manifest has been loaded. + * @method _loadManifest + * @param {Object} json + * @private + */ + p._loadManifest = function (json) { + if (json && json.manifest) { + var queue = this._manifestQueue = new createjs.LoadQueue(this._preferXHR); + queue.on("fileload", this._handleManifestFileLoad, this); + queue.on("progress", this._handleManifestProgress, this); + queue.on("complete", this._handleManifestComplete, this, true); + queue.on("error", this._handleManifestError, this, true); + for(var i = 0, l = this.plugins.length; i < l; i++) { // conserve order of plugins + queue.installPlugin(this.plugins[i]); + } + queue.loadManifest(json); + } else { + this._sendComplete(); + } + }; + + /** + * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed. + * @method _handleManifestFileLoad + * @param {Event} event + * @private + */ + p._handleManifestFileLoad = function (event) { + event.target = null; + this.dispatchEvent(event); + }; + + /** + * The manifest has completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} + * {{#crossLink "Event"}}{{/crossLink}} from the ManifestLoader. + * @method _handleManifestComplete + * @param {Event} event + * @private + */ + p._handleManifestComplete = function (event) { + this._loadedItems = this._manifestQueue.getItems(true); + this._sendComplete(); + }; + + /** + * The manifest has reported progress. + * @method _handleManifestProgress + * @param {ProgressEvent} event + * @private + */ + p._handleManifestProgress = function (event) { + this.progress = event.progress * (1 - s.MANIFEST_PROGRESS) + s.MANIFEST_PROGRESS; + this._sendProgress(this.progress); + }; + + /** + * The manifest has reported an error with one of the files. + * @method _handleManifestError + * @param {ErrorEvent} event + * @private + */ + p._handleManifestError = function (event) { + var newEvent = new createjs.Event("fileerror"); + newEvent.item = event.data; + this.dispatchEvent(newEvent); + }; + + createjs.ManifestLoader = createjs.promote(ManifestLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// SoundLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(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"); + +}()); + +//############################################################################## +// VideoLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for video files. + * @class VideoLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @extends AbstractMediaLoader + * @constructor + */ + function VideoLoader(loadItem, preferXHR) { + this.AbstractMediaLoader_constructor(loadItem, preferXHR, createjs.Types.VIDEO); + + if (createjs.DomUtils.isVideoTag(loadItem) || createjs.DomUtils.isVideoTag(loadItem.src)) { + this.setTag(createjs.DomUtils.isVideoTag(loadItem)?loadItem:loadItem.src); + + // We can't use XHR for a tag that's passed in. + this._preferXHR = false; + } else { + this.setTag(this._createTag()); + } + }; + + var p = createjs.extend(VideoLoader, createjs.AbstractMediaLoader); + var s = VideoLoader; + + /** + * Create a new video tag + * + * @returns {HTMLElement} + * @private + */ + p._createTag = function () { + return createjs.Elements.video(); + }; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/VIDEO:property"}}{{/crossLink}}. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.VIDEO; + }; + + createjs.VideoLoader = createjs.promote(VideoLoader, "AbstractMediaLoader"); + +}()); + +//############################################################################## +// SpriteSheetLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for EaselJS SpriteSheets. Images inside the spritesheet definition are loaded before the loader + * completes. To load SpriteSheets using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} + * as part of the {{#crossLink "LoadItem"}}{{/crossLink}}. Note that the {{#crossLink "JSONLoader"}}{{/crossLink}} + * and {{#crossLink "JSONPLoader"}}{{/crossLink}} are higher priority loaders, so SpriteSheets must + * set the {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property + * to {{#crossLink "Types/SPRITESHEET:property"}}{{/crossLink}}. + * + * The {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/crossOrigin:property"}}{{/crossLink}} as well + * as the {{#crossLink "LoadQueue's"}}{{/crossLink}} `basePath` argument and {{#crossLink "LoadQueue/_preferXHR"}}{{/crossLink}} + * property supplied to the {{#crossLink "LoadQueue"}}{{/crossLink}} are passed on to the sub-manifest that loads + * the SpriteSheet images. + * + * Note that the SpriteSheet JSON does not respect the {{#crossLink "LoadQueue/_preferXHR:property"}}{{/crossLink}} + * property, which should instead be determined by the presence of a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} + * property on the SpriteSheet load item. This is because the JSON loaded will have a different format depending on + * if it is loaded as JSON, so just changing `preferXHR` is not enough to change how it is loaded. + * @class SpriteSheetLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function SpriteSheetLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.SPRITESHEET); + + // protected properties + /** + * An internal queue which loads the SpriteSheet's images. + * @method _manifestQueue + * @type {LoadQueue} + * @private + */ + this._manifestQueue = null; + } + + var p = createjs.extend(SpriteSheetLoader, createjs.AbstractLoader); + var s = SpriteSheetLoader; + + // static properties + /** + * The amount of progress that the manifest itself takes up. + * @property SPRITESHEET_PROGRESS + * @type {number} + * @default 0.25 (25%) + * @private + * @static + */ + s.SPRITESHEET_PROGRESS = 0.25; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/SPRITESHEET:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.SPRITESHEET; + }; + + // public methods + p.destroy = function() { + this.AbstractLoader_destroy(); + this._manifestQueue.close(); + }; + + // protected methods + p._createRequest = function() { + var callback = this._item.callback; + if (callback != null) { + this._request = new createjs.JSONPLoader(this._item); + } else { + this._request = new createjs.JSONLoader(this._item); + } + }; + + p.handleEvent = function (event) { + switch (event.type) { + case "complete": + this._rawResult = event.target.getResult(true); + this._result = event.target.getResult(); + this._sendProgress(s.SPRITESHEET_PROGRESS); + this._loadManifest(this._result); + return; + case "progress": + event.loaded *= s.SPRITESHEET_PROGRESS; + this.progress = event.loaded / event.total; + if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } + this._sendProgress(event); + return; + } + this.AbstractLoader_handleEvent(event); + }; + + /** + * Create and load the images once the SpriteSheet JSON has been loaded. + * @method _loadManifest + * @param {Object} json + * @private + */ + p._loadManifest = function (json) { + if (json && json.images) { + var queue = this._manifestQueue = new createjs.LoadQueue(this._preferXHR, this._item.path, this._item.crossOrigin); + queue.on("complete", this._handleManifestComplete, this, true); + queue.on("fileload", this._handleManifestFileLoad, this); + queue.on("progress", this._handleManifestProgress, this); + queue.on("error", this._handleManifestError, this, true); + queue.loadManifest(json.images); + } + }; + + /** + * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed. + * @method _handleManifestFileLoad + * @param {Event} event + * @private + */ + p._handleManifestFileLoad = function (event) { + var image = event.result; + if (image != null) { + var images = this.getResult().images; + var pos = images.indexOf(event.item.src); + images[pos] = image; + } + }; + + /** + * The images have completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} + * {{#crossLink "Event"}}{{/crossLink}} from the SpriteSheetLoader. + * @method _handleManifestComplete + * @param {Event} event + * @private + */ + p._handleManifestComplete = function (event) { + this._result = new createjs.SpriteSheet(this._result); + this._loadedItems = this._manifestQueue.getItems(true); + this._sendComplete(); + }; + + /** + * The images {{#crossLink "LoadQueue"}}{{/crossLink}} has reported progress. + * @method _handleManifestProgress + * @param {ProgressEvent} event + * @private + */ + p._handleManifestProgress = function (event) { + this.progress = event.progress * (1 - s.SPRITESHEET_PROGRESS) + s.SPRITESHEET_PROGRESS; + this._sendProgress(this.progress); + }; + + /** + * An image has reported an error. + * @method _handleManifestError + * @param {ErrorEvent} event + * @private + */ + p._handleManifestError = function (event) { + var newEvent = new createjs.Event("fileerror"); + newEvent.item = event.data; + this.dispatchEvent(newEvent); + }; + + createjs.SpriteSheetLoader = createjs.promote(SpriteSheetLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// SVGLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for SVG files. + * @class SVGLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @extends AbstractLoader + * @constructor + */ + function SVGLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.SVG); + + // public properties + this.resultFormatter = this._formatResult; + + // protected properties + this._tagSrcAttribute = "data"; + + if (preferXHR) { + this.setTag(createjs.Elements.svg()); + } else { + this.setTag(createjs.Elements.object()); + this.getTag().type = "image/svg+xml"; + } + }; + + var p = createjs.extend(SVGLoader, createjs.AbstractLoader); + var s = SVGLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/SVG:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.SVG; + }; + + // protected methods + /** + * The result formatter for SVG files. + * @method _formatResult + * @param {AbstractLoader} loader + * @returns {Object} + * @private + */ + p._formatResult = function (loader) { + // mime should be image/svg+xml, but Opera requires text/xml + var xml = createjs.DataUtils.parseXML(loader.getResult(true)); + var tag = loader.getTag(); + + if (!this._preferXHR && document.body.contains(tag)) { + document.body.removeChild(tag); + } + + if (xml.documentElement != null) { + var element = xml.documentElement; + // Support loading an SVG from a different domain in ID + if (document.importNode) { + element = document.importNode(element, true); + } + tag.appendChild(element); + return tag; + } else { // For browsers that don't support SVG, just give them the XML. (IE 9-8) + return xml; + } + }; + + createjs.SVGLoader = createjs.promote(SVGLoader, "AbstractLoader"); + +}()); + +//############################################################################## +// XMLLoader.js +//############################################################################## + +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for CSS files. + * @class XMLLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function XMLLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, true, createjs.Types.XML); + + // public properties + this.resultFormatter = this._formatResult; + }; + + var p = createjs.extend(XMLLoader, createjs.AbstractLoader); + var s = XMLLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/XML: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.XML; + }; + + // protected methods + /** + * The result formatter for XML files. + * @method _formatResult + * @param {AbstractLoader} loader + * @returns {XMLDocument} + * @private + */ + p._formatResult = function (loader) { + return createjs.DataUtils.parseXML(loader.getResult(true)); + }; + + createjs.XMLLoader = createjs.promote(XMLLoader, "AbstractLoader"); + +}()); \ No newline at end of file diff --git a/lib/preloadjs.min.js b/lib/preloadjs.min.js new file mode 100644 index 00000000..733df517 --- /dev/null +++ b/lib/preloadjs.min.js @@ -0,0 +1,14 @@ +/*! +* @license PreloadJS +* Visit http://createjs.com/ for documentation, updates and examples. +* +* Copyright (c) 2011-2015 gskinner.com, inc. +* +* Distributed under the terms of the MIT license. +* http://www.opensource.org/licenses/mit-license.html +* +* This notice shall be included in all copies or substantial portions of the Software. +*/ +this.createjs=this.createjs||{},function(){"use strict";var a=createjs.PreloadJS=createjs.PreloadJS||{};a.version="1.0.0",a.buildDate="Thu, 14 Sep 2017 19:47:47 GMT"}(),this.createjs=this.createjs||{},createjs.extend=function(a,b){"use strict";function c(){this.constructor=a}return c.prototype=b.prototype,a.prototype=new c},this.createjs=this.createjs||{},createjs.promote=function(a,b){"use strict";var c=a.prototype,d=Object.getPrototypeOf&&Object.getPrototypeOf(c)||c.__proto__;if(d){c[(b+="_")+"constructor"]=d.constructor;for(var e in d)c.hasOwnProperty(e)&&"function"==typeof d[e]&&(c[b+e]=d[e])}return a},this.createjs=this.createjs||{},createjs.deprecate=function(a,b){"use strict";return function(){var c="Deprecated property or method '"+b+"'. See docs for info.";return console&&(console.warn?console.warn(c):console.log(c)),a&&a.apply(this,arguments)}},this.createjs=this.createjs||{},function(){"use strict";createjs.proxy=function(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){return a.apply(b,Array.prototype.slice.call(arguments,0).concat(c))}}}(),this.createjs=this.createjs||{},createjs.indexOf=function(a,b){"use strict";for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1},this.createjs=this.createjs||{},function(){"use strict";function Event(a,b,c){this.type=a,this.target=null,this.currentTarget=null,this.eventPhase=0,this.bubbles=!!b,this.cancelable=!!c,this.timeStamp=(new Date).getTime(),this.defaultPrevented=!1,this.propagationStopped=!1,this.immediatePropagationStopped=!1,this.removed=!1}var a=Event.prototype;a.preventDefault=function(){this.defaultPrevented=this.cancelable&&!0},a.stopPropagation=function(){this.propagationStopped=!0},a.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},a.remove=function(){this.removed=!0},a.clone=function(){return new Event(this.type,this.bubbles,this.cancelable)},a.set=function(a){for(var b in a)this[b]=a[b];return this},a.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=Event}(),this.createjs=this.createjs||{},function(){"use strict";function ErrorEvent(a,b,c){this.Event_constructor("error"),this.title=a,this.message=b,this.data=c}var a=createjs.extend(ErrorEvent,createjs.Event);a.clone=function(){return new createjs.ErrorEvent(this.title,this.message,this.data)},createjs.ErrorEvent=createjs.promote(ErrorEvent,"Event")}(),this.createjs=this.createjs||{},function(){"use strict";function EventDispatcher(){this._listeners=null,this._captureListeners=null}var a=EventDispatcher.prototype;EventDispatcher.initialize=function(b){b.addEventListener=a.addEventListener,b.on=a.on,b.removeEventListener=b.off=a.removeEventListener,b.removeAllEventListeners=a.removeAllEventListeners,b.hasEventListener=a.hasEventListener,b.dispatchEvent=a.dispatchEvent,b._dispatchEvent=a._dispatchEvent,b.willTrigger=a.willTrigger},a.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},a.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},a.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},a.off=a.removeEventListener,a.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},a.dispatchEvent=function(a,b,c){if("string"==typeof a){var d=this._listeners;if(!(b||d&&d[a]))return!0;a=new createjs.Event(a,b,c)}else a.target&&a.clone&&(a=a.clone());try{a.target=this}catch(e){}if(a.bubbles&&this.parent){for(var f=this,g=[f];f.parent;)g.push(f=f.parent);var h,i=g.length;for(h=i-1;h>=0&&!a.propagationStopped;h--)g[h]._dispatchEvent(a,1+(0==h));for(h=1;i>h&&!a.propagationStopped;h++)g[h]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return!a.defaultPrevented},a.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},a.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},a.toString=function(){return"[EventDispatcher]"},a._dispatchEvent=function(a,b){var c,d,e=2>=b?this._captureListeners:this._listeners;if(a&&e&&(d=e[a.type])&&(c=d.length)){try{a.currentTarget=this}catch(f){}try{a.eventPhase=0|b}catch(f){}a.removed=!1,d=d.slice();for(var g=0;c>g&&!a.immediatePropagationStopped;g++){var h=d[g];h.handleEvent?h.handleEvent(a):h(a),a.removed&&(this.off(a.type,h,1==b),a.removed=!1)}}2===b&&this._dispatchEvent(a,2.1)},createjs.EventDispatcher=EventDispatcher}(),this.createjs=this.createjs||{},function(){"use strict";function ProgressEvent(a,b){this.Event_constructor("progress"),this.loaded=a,this.total=null==b?1:b,this.progress=0==b?0:this.loaded/this.total}var a=createjs.extend(ProgressEvent,createjs.Event);a.clone=function(){return new createjs.ProgressEvent(this.loaded,this.total)},createjs.ProgressEvent=createjs.promote(ProgressEvent,"Event")}(window),function(){function a(b,d){function f(a){if(f[a]!==q)return f[a];var b;if("bug-string-char-index"==a)b="a"!="a"[0];else if("json"==a)b=f("json-stringify")&&f("json-parse");else{var c,e='{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';if("json-stringify"==a){var i=d.stringify,k="function"==typeof i&&t;if(k){(c=function(){return 1}).toJSON=c;try{k="0"===i(0)&&"0"===i(new g)&&'""'==i(new h)&&i(s)===q&&i(q)===q&&i()===q&&"1"===i(c)&&"[1]"==i([c])&&"[null]"==i([q])&&"null"==i(null)&&"[null,null,null]"==i([q,s,null])&&i({a:[c,!0,!1,null,"\x00\b\n\f\r "]})==e&&"1"===i(null,c)&&"[\n 1,\n 2\n]"==i([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==i(new j(-864e13))&&'"+275760-09-13T00:00:00.000Z"'==i(new j(864e13))&&'"-000001-01-01T00:00:00.000Z"'==i(new j(-621987552e5))&&'"1969-12-31T23:59:59.999Z"'==i(new j(-1))}catch(l){k=!1}}b=k}if("json-parse"==a){var m=d.parse;if("function"==typeof m)try{if(0===m("0")&&!m(!1)){c=m(e);var n=5==c.a.length&&1===c.a[0];if(n){try{n=!m('" "')}catch(l){}if(n)try{n=1!==m("01")}catch(l){}if(n)try{n=1!==m("1.")}catch(l){}}}}catch(l){n=!1}b=n}}return f[a]=!!b}b||(b=e.Object()),d||(d=e.Object());var g=b.Number||e.Number,h=b.String||e.String,i=b.Object||e.Object,j=b.Date||e.Date,k=b.SyntaxError||e.SyntaxError,l=b.TypeError||e.TypeError,m=b.Math||e.Math,n=b.JSON||e.JSON;"object"==typeof n&&n&&(d.stringify=n.stringify,d.parse=n.parse);var o,p,q,r=i.prototype,s=r.toString,t=new j(-0xc782b5b800cec);try{t=-109252==t.getUTCFullYear()&&0===t.getUTCMonth()&&1===t.getUTCDate()&&10==t.getUTCHours()&&37==t.getUTCMinutes()&&6==t.getUTCSeconds()&&708==t.getUTCMilliseconds()}catch(u){}if(!f("json")){var v="[object Function]",w="[object Date]",x="[object Number]",y="[object String]",z="[object Array]",A="[object Boolean]",B=f("bug-string-char-index");if(!t)var C=m.floor,D=[0,31,59,90,120,151,181,212,243,273,304,334],E=function(a,b){return D[b]+365*(a-1970)+C((a-1969+(b=+(b>1)))/4)-C((a-1901+b)/100)+C((a-1601+b)/400)};if((o=r.hasOwnProperty)||(o=function(a){var b,c={};return(c.__proto__=null,c.__proto__={toString:1},c).toString!=s?o=function(a){var b=this.__proto__,c=a in(this.__proto__=null,this);return this.__proto__=b,c}:(b=c.constructor,o=function(a){var c=(this.constructor||b).prototype;return a in this&&!(a in c&&this[a]===c[a])}),c=null,o.call(this,a)}),p=function(a,b){var d,e,f,g=0;(d=function(){this.valueOf=0}).prototype.valueOf=0,e=new d;for(f in e)o.call(e,f)&&g++;return d=e=null,g?p=2==g?function(a,b){var c,d={},e=s.call(a)==v;for(c in a)e&&"prototype"==c||o.call(d,c)||!(d[c]=1)||!o.call(a,c)||b(c)}:function(a,b){var c,d,e=s.call(a)==v;for(c in a)e&&"prototype"==c||!o.call(a,c)||(d="constructor"===c)||b(c);(d||o.call(a,c="constructor"))&&b(c)}:(e=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"],p=function(a,b){var d,f,g=s.call(a)==v,h=!g&&"function"!=typeof a.constructor&&c[typeof a.hasOwnProperty]&&a.hasOwnProperty||o;for(d in a)g&&"prototype"==d||!h.call(a,d)||b(d);for(f=e.length;d=e[--f];h.call(a,d)&&b(d));}),p(a,b)},!f("json-stringify")){var F={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"},G="000000",H=function(a,b){return(G+(b||0)).slice(-a)},I="\\u00",J=function(a){for(var b='"',c=0,d=a.length,e=!B||d>10,f=e&&(B?a.split(""):a);d>c;c++){var g=a.charCodeAt(c);switch(g){case 8:case 9:case 10:case 12:case 13:case 34:case 92:b+=F[g];break;default:if(32>g){b+=I+H(2,g.toString(16));break}b+=e?f[c]:a.charAt(c)}}return b+'"'},K=function(a,b,c,d,e,f,g){var h,i,j,k,m,n,r,t,u,v,B,D,F,G,I,L;try{h=b[a]}catch(M){}if("object"==typeof h&&h)if(i=s.call(h),i!=w||o.call(h,"toJSON"))"function"==typeof h.toJSON&&(i!=x&&i!=y&&i!=z||o.call(h,"toJSON"))&&(h=h.toJSON(a));else if(h>-1/0&&1/0>h){if(E){for(m=C(h/864e5),j=C(m/365.2425)+1970-1;E(j+1,0)<=m;j++);for(k=C((m-E(j,0))/30.42);E(j,k+1)<=m;k++);m=1+m-E(j,k),n=(h%864e5+864e5)%864e5,r=C(n/36e5)%24,t=C(n/6e4)%60,u=C(n/1e3)%60,v=n%1e3}else j=h.getUTCFullYear(),k=h.getUTCMonth(),m=h.getUTCDate(),r=h.getUTCHours(),t=h.getUTCMinutes(),u=h.getUTCSeconds(),v=h.getUTCMilliseconds();h=(0>=j||j>=1e4?(0>j?"-":"+")+H(6,0>j?-j:j):H(4,j))+"-"+H(2,k+1)+"-"+H(2,m)+"T"+H(2,r)+":"+H(2,t)+":"+H(2,u)+"."+H(3,v)+"Z"}else h=null;if(c&&(h=c.call(b,a,h)),null===h)return"null";if(i=s.call(h),i==A)return""+h;if(i==x)return h>-1/0&&1/0>h?""+h:"null";if(i==y)return J(""+h);if("object"==typeof h){for(G=g.length;G--;)if(g[G]===h)throw l();if(g.push(h),B=[],I=f,f+=e,i==z){for(F=0,G=h.length;G>F;F++)D=K(F,h,c,d,e,f,g),B.push(D===q?"null":D);L=B.length?e?"[\n"+f+B.join(",\n"+f)+"\n"+I+"]":"["+B.join(",")+"]":"[]"}else p(d||h,function(a){var b=K(a,h,c,d,e,f,g);b!==q&&B.push(J(a)+":"+(e?" ":"")+b)}),L=B.length?e?"{\n"+f+B.join(",\n"+f)+"\n"+I+"}":"{"+B.join(",")+"}":"{}";return g.pop(),L}};d.stringify=function(a,b,d){var e,f,g,h;if(c[typeof b]&&b)if((h=s.call(b))==v)f=b;else if(h==z){g={};for(var i,j=0,k=b.length;k>j;i=b[j++],h=s.call(i),(h==y||h==x)&&(g[i]=1));}if(d)if((h=s.call(d))==x){if((d-=d%1)>0)for(e="",d>10&&(d=10);e.lengthL;)switch(e=f.charCodeAt(L)){case 9:case 10:case 13:case 32:L++;break;case 123:case 125:case 91:case 93:case 58:case 44:return a=B?f.charAt(L):f[L],L++,a;case 34:for(a="@",L++;g>L;)if(e=f.charCodeAt(L),32>e)P();else if(92==e)switch(e=f.charCodeAt(++L)){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:a+=O[e],L++;break;case 117:for(b=++L,c=L+4;c>L;L++)e=f.charCodeAt(L),e>=48&&57>=e||e>=97&&102>=e||e>=65&&70>=e||P();a+=N("0x"+f.slice(b,L));break;default:P()}else{if(34==e)break;for(e=f.charCodeAt(L),b=L;e>=32&&92!=e&&34!=e;)e=f.charCodeAt(++L);a+=f.slice(b,L)}if(34==f.charCodeAt(L))return L++,a;P();default:if(b=L,45==e&&(d=!0,e=f.charCodeAt(++L)),e>=48&&57>=e){for(48==e&&(e=f.charCodeAt(L+1),e>=48&&57>=e)&&P(),d=!1;g>L&&(e=f.charCodeAt(L),e>=48&&57>=e);L++);if(46==f.charCodeAt(L)){for(c=++L;g>c&&(e=f.charCodeAt(c),e>=48&&57>=e);c++);c==L&&P(),L=c}if(e=f.charCodeAt(L),101==e||69==e){for(e=f.charCodeAt(++L),(43==e||45==e)&&L++,c=L;g>c&&(e=f.charCodeAt(c),e>=48&&57>=e);c++);c==L&&P(),L=c}return+f.slice(b,L)}if(d&&P(),"true"==f.slice(L,L+4))return L+=4,!0;if("false"==f.slice(L,L+5))return L+=5,!1;if("null"==f.slice(L,L+4))return L+=4,null;P()}return"$"},R=function(a){var b,c;if("$"==a&&P(),"string"==typeof a){if("@"==(B?a.charAt(0):a[0]))return a.slice(1);if("["==a){for(b=[];a=Q(),"]"!=a;c||(c=!0))c&&(","==a?(a=Q(),"]"==a&&P()):P()),","==a&&P(),b.push(R(a));return b}if("{"==a){for(b={};a=Q(),"}"!=a;c||(c=!0))c&&(","==a?(a=Q(),"}"==a&&P()):P()),(","==a||"string"!=typeof a||"@"!=(B?a.charAt(0):a[0])||":"!=Q())&&P(),b[a.slice(1)]=R(Q());return b}P()}return a},S=function(a,b,c){var d=T(a,b,c);d===q?delete a[b]:a[b]=d},T=function(a,b,c){var d,e=a[b];if("object"==typeof e&&e)if(s.call(e)==z)for(d=e.length;d--;)S(e,d,c);else p(e,function(a){S(e,a,c)});return c.call(a,b,e)};d.parse=function(a,b){var c,d;return L=0,M=""+a,c=R(Q()),"$"!=Q()&&P(),L=M=null,b&&s.call(b)==v?T((d={},d[""]=c,d),"",b):c}}}return d.runInContext=a,d}var b="function"==typeof define&&define.amd,c={"function":!0,object:!0},d=c[typeof exports]&&exports&&!exports.nodeType&&exports,e=c[typeof window]&&window||this,f=d&&c[typeof module]&&module&&!module.nodeType&&"object"==typeof global&&global;if(!f||f.global!==f&&f.window!==f&&f.self!==f||(e=f),d&&!b)a(e,d);else{var g=e.JSON,h=e.JSON3,i=!1,j=a(e,e.JSON3={noConflict:function(){return i||(i=!0,e.JSON=g,e.JSON3=h,g=h=null),j}});e.JSON={parse:j.parse,stringify:j.stringify}}b&&define(function(){return j})}.call(this),function(){var a={};a.a=function(){return a.el("a")},a.svg=function(){return a.el("svg")},a.object=function(){return a.el("object")},a.image=function(){return a.el("image")},a.img=function(){return a.el("img")},a.style=function(){return a.el("style")},a.link=function(){return a.el("link")},a.script=function(){return a.el("script")},a.audio=function(){return a.el("audio")},a.video=function(){return a.el("video")},a.text=function(a){return document.createTextNode(a)},a.el=function(a){return document.createElement(a)},createjs.Elements=a}(),function(){var a={};a.ABSOLUTE_PATT=/^(?:\w+:)?\/{2}/i,a.RELATIVE_PATT=/^[.\/]*?\//i,a.EXTENSION_PATT=/\/?[^\/]+\.(\w{1,5})$/i,a.parseURI=function(b){var c={absolute:!1,relative:!1,protocol:null,hostname:null,port:null,pathname:null,search:null,hash:null,host:null};if(null==b)return c;var d=createjs.Elements.a();d.href=b;for(var e in c)e in d&&(c[e]=d[e]);var f=b.indexOf("?");f>-1&&(b=b.substr(0,f));var g;return a.ABSOLUTE_PATT.test(b)?c.absolute=!0:a.RELATIVE_PATT.test(b)&&(c.relative=!0),(g=b.match(a.EXTENSION_PATT))&&(c.extension=g[1].toLowerCase()),c},a.formatQueryString=function(a,b){if(null==a)throw new Error("You must specify data.");var c=[];for(var d in a)c.push(d+"="+escape(a[d]));return b&&(c=c.concat(b)),c.join("&")},a.buildURI=function(a,b){if(null==b)return a;var c=[],d=a.indexOf("?");if(-1!=d){var e=a.slice(d+1);c=c.concat(e.split("&"))}return-1!=d?a.slice(0,d)+"?"+this.formatQueryString(b,c):a+"?"+this.formatQueryString(b,c)},a.isCrossDomain=function(a){var b=createjs.Elements.a();b.href=a.src;var c=createjs.Elements.a();c.href=location.href;var d=""!=b.hostname&&(b.port!=c.port||b.protocol!=c.protocol||b.hostname!=c.hostname);return d},a.isLocal=function(a){var b=createjs.Elements.a();return b.href=a.src,""==b.hostname&&"file:"==b.protocol},createjs.URLUtils=a}(),function(){var a={container:null};a.appendToHead=function(b){a.getHead().appendChild(b)},a.appendToBody=function(b){if(null==a.container){a.container=document.createElement("div"),a.container.id="preloadjs-container";var c=a.container.style;c.visibility="hidden",c.position="absolute",c.width=a.container.style.height="10px",c.overflow="hidden",c.transform=c.msTransform=c.webkitTransform=c.oTransform="translate(-10px, -10px)",a.getBody().appendChild(a.container)}a.container.appendChild(b)},a.getHead=function(){return document.head||document.getElementsByTagName("head")[0]},a.getBody=function(){return document.body||document.getElementsByTagName("body")[0]},a.removeChild=function(a){a.parent&&a.parent.removeChild(a)},a.isImageTag=function(a){return a instanceof HTMLImageElement},a.isAudioTag=function(a){return window.HTMLAudioElement?a instanceof HTMLAudioElement:!1},a.isVideoTag=function(a){return window.HTMLVideoElement?a instanceof HTMLVideoElement:!1},createjs.DomUtils=a}(),function(){var a={};a.parseXML=function(a){var b=null;try{if(window.DOMParser){var c=new DOMParser;b=c.parseFromString(a,"text/xml")}}catch(d){}if(!b)try{b=new ActiveXObject("Microsoft.XMLDOM"),b.async=!1,b.loadXML(a)}catch(d){b=null}return b},a.parseJSON=function(a){if(null==a)return null;try{return JSON.parse(a)}catch(b){throw b}},createjs.DataUtils=a}(),this.createjs=this.createjs||{},function(){var a={};a.BINARY="binary",a.CSS="css",a.FONT="font",a.FONTCSS="fontcss",a.IMAGE="image",a.JAVASCRIPT="javascript",a.JSON="json",a.JSONP="jsonp",a.MANIFEST="manifest",a.SOUND="sound",a.VIDEO="video",a.SPRITESHEET="spritesheet",a.SVG="svg",a.TEXT="text",a.XML="xml",createjs.Types=a}(),this.createjs=this.createjs||{},function(){var a={};a.POST="POST",a.GET="GET",createjs.Methods=a}(),this.createjs=this.createjs||{},function(){"use strict";function LoadItem(){this.src=null,this.type=null,this.id=null,this.maintainOrder=!1,this.callback=null,this.data=null,this.method=createjs.Methods.GET,this.values=null,this.headers=null,this.withCredentials=!1,this.mimeType=null,this.crossOrigin=null,this.loadTimeout=b.LOAD_TIMEOUT_DEFAULT}var a=LoadItem.prototype={},b=LoadItem;b.LOAD_TIMEOUT_DEFAULT=8e3,b.create=function(a){if("string"==typeof a){var c=new LoadItem;return c.src=a,c}if(a instanceof b)return a;if(a instanceof Object&&a.src)return null==a.loadTimeout&&(a.loadTimeout=b.LOAD_TIMEOUT_DEFAULT),a;throw new Error("Type not recognized.")},a.set=function(a){for(var b in a)this[b]=a[b];return this},createjs.LoadItem=b}(),function(){var a={};a.isBinary=function(a){switch(a){case createjs.Types.IMAGE:case createjs.Types.BINARY:return!0;default:return!1}},a.isText=function(a){switch(a){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!0;default:return!1}},a.getTypeByExtension=function(a){if(null==a)return createjs.Types.TEXT;switch(a.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=a}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractLoader(a,b,c){this.EventDispatcher_constructor(),this.loaded=!1,this.canceled=!1,this.progress=0,this.type=c,this.resultFormatter=null,this._item=a?createjs.LoadItem.create(a):null,this._preferXHR=b,this._result=null,this._rawResult=null,this._loadedItems=null,this._tagSrcAttribute=null,this._tag=null}var a=createjs.extend(AbstractLoader,createjs.EventDispatcher),b=AbstractLoader;try{Object.defineProperties(b,{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(c){}a.getItem=function(){return this._item},a.getResult=function(a){return a?this._rawResult:this._result},a.getTag=function(){return this._tag},a.setTag=function(a){this._tag=a},a.load=function(){this._createRequest(),this._request.on("complete",this,this),this._request.on("progress",this,this),this._request.on("loadStart",this,this),this._request.on("abort",this,this),this._request.on("timeout",this,this),this._request.on("error",this,this);var a=new createjs.Event("initialize");a.loader=this._request,this.dispatchEvent(a),this._request.load()},a.cancel=function(){this.canceled=!0,this.destroy()},a.destroy=function(){this._request&&(this._request.removeAllEventListeners(),this._request.destroy()),this._request=null,this._item=null,this._rawResult=null,this._result=null,this._loadItems=null,this.removeAllEventListeners()},a.getLoadedItems=function(){return this._loadedItems},a._createRequest=function(){this._request=this._preferXHR?new createjs.XHRRequest(this._item):new createjs.TagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},a._createTag=function(){return null},a._sendLoadStart=function(){this._isCanceled()||this.dispatchEvent("loadstart")},a._sendProgress=function(a){if(!this._isCanceled()){var b=null;"number"==typeof a?(this.progress=a,b=new createjs.ProgressEvent(this.progress)):(b=a,this.progress=a.loaded/a.total,b.progress=this.progress,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0)),this.hasEventListener("progress")&&this.dispatchEvent(b)}},a._sendComplete=function(){if(!this._isCanceled()){this.loaded=!0;var a=new createjs.Event("complete");a.rawResult=this._rawResult,null!=this._result&&(a.result=this._result),this.dispatchEvent(a)}},a._sendError=function(a){!this._isCanceled()&&this.hasEventListener("error")&&(null==a&&(a=new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY")),this.dispatchEvent(a))},a._isCanceled=function(){return null==window.createjs||this.canceled?!0:!1},a.resultFormatter=null,a.handleEvent=function(a){switch(a.type){case"complete":this._rawResult=a.target._response;var b=this.resultFormatter&&this.resultFormatter(this);b instanceof Function?b.call(this,createjs.proxy(this._resultFormatSuccess,this),createjs.proxy(this._resultFormatFailed,this)):(this._result=b||this._rawResult,this._sendComplete());break;case"progress":this._sendProgress(a);break;case"error":this._sendError(a);break;case"loadstart":this._sendLoadStart();break;case"abort":case"timeout":this._isCanceled()||this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_"+a.type.toUpperCase()+"_ERROR"))}},a._resultFormatSuccess=function(a){this._result=a,this._sendComplete()},a._resultFormatFailed=function(a){this._sendError(a)},a.toString=function(){return"[PreloadJS AbstractLoader]"},createjs.AbstractLoader=createjs.promote(AbstractLoader,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractMediaLoader(a,b,c){this.AbstractLoader_constructor(a,b,c),this.resultFormatter=this._formatResult,this._tagSrcAttribute="src",this.on("initialize",this._updateXHR,this)}var a=createjs.extend(AbstractMediaLoader,createjs.AbstractLoader);a.load=function(){this._tag||(this._tag=this._createTag(this._item.src)),this._tag.preload="auto",this._tag.load(),this.AbstractLoader_load()},a._createTag=function(){},a._createRequest=function(){this._request=this._preferXHR?new createjs.XHRRequest(this._item):new createjs.MediaTagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},a._updateXHR=function(a){a.loader.setResponseType&&a.loader.setResponseType("blob")},a._formatResult=function(a){if(this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.onstalled=null,this._preferXHR){var b=window.URL||window.webkitURL,c=a.getResult(!0);a.getTag().src=b.createObjectURL(c)}return a.getTag()},createjs.AbstractMediaLoader=createjs.promote(AbstractMediaLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";var AbstractRequest=function(a){this._item=a},a=createjs.extend(AbstractRequest,createjs.EventDispatcher);a.load=function(){},a.destroy=function(){},a.cancel=function(){},createjs.AbstractRequest=createjs.promote(AbstractRequest,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function TagRequest(a,b,c){this.AbstractRequest_constructor(a),this._tag=b,this._tagSrcAttribute=c,this._loadedHandler=createjs.proxy(this._handleTagComplete,this),this._addedToDOM=!1}var a=createjs.extend(TagRequest,createjs.AbstractRequest);a.load=function(){this._tag.onload=createjs.proxy(this._handleTagComplete,this),this._tag.onreadystatechange=createjs.proxy(this._handleReadyStateChange,this),this._tag.onerror=createjs.proxy(this._handleError,this);var a=new createjs.Event("initialize");a.loader=this._tag,this.dispatchEvent(a),this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout),this._tag[this._tagSrcAttribute]=this._item.src,null==this._tag.parentNode&&(createjs.DomUtils.appendToBody(this._tag),this._addedToDOM=!0)},a.destroy=function(){this._clean(),this._tag=null,this.AbstractRequest_destroy()},a._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},a._handleError=function(){this._clean(),this.dispatchEvent("error")},a._handleTagComplete=function(){this._rawResult=this._tag,this._result=this.resultFormatter&&this.resultFormatter(this)||this._rawResult,this._clean(),this.dispatchEvent("complete")},a._handleTimeout=function(){this._clean(),this.dispatchEvent(new createjs.Event("timeout"))},a._clean=function(){this._tag.onload=null,this._tag.onreadystatechange=null,this._tag.onerror=null,this._addedToDOM&&null!=this._tag.parentNode&&this._tag.parentNode.removeChild(this._tag),clearTimeout(this._loadTimeout)},a._handleStalled=function(){},createjs.TagRequest=createjs.promote(TagRequest,"AbstractRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function MediaTagRequest(a,b,c){this.AbstractRequest_constructor(a),this._tag=b,this._tagSrcAttribute=c,this._loadedHandler=createjs.proxy(this._handleTagComplete,this)}var a=createjs.extend(MediaTagRequest,createjs.TagRequest);a.load=function(){var a=createjs.proxy(this._handleStalled,this);this._stalledCallback=a;var b=createjs.proxy(this._handleProgress,this);this._handleProgress=b,this._tag.addEventListener("stalled",a),this._tag.addEventListener("progress",b),this._tag.addEventListener&&this._tag.addEventListener("canplaythrough",this._loadedHandler,!1),this.TagRequest_load()},a._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},a._handleStalled=function(){},a._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.ProgressEvent(a.loaded,a.total);this.dispatchEvent(b)}},a._clean=function(){this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.removeEventListener("stalled",this._stalledCallback),this._tag.removeEventListener("progress",this._progressCallback),this.TagRequest__clean()},createjs.MediaTagRequest=createjs.promote(MediaTagRequest,"TagRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function XHRRequest(a){this.AbstractRequest_constructor(a),this._request=null,this._loadTimeout=null,this._xhrLevel=1,this._response=null,this._rawResponse=null,this._canceled=!1,this._handleLoadStartProxy=createjs.proxy(this._handleLoadStart,this),this._handleProgressProxy=createjs.proxy(this._handleProgress,this),this._handleAbortProxy=createjs.proxy(this._handleAbort,this),this._handleErrorProxy=createjs.proxy(this._handleError,this),this._handleTimeoutProxy=createjs.proxy(this._handleTimeout,this),this._handleLoadProxy=createjs.proxy(this._handleLoad,this),this._handleReadyStateChangeProxy=createjs.proxy(this._handleReadyStateChange,this),!this._createXHR(a)}var a=createjs.extend(XHRRequest,createjs.AbstractRequest);XHRRequest.ACTIVEX_VERSIONS=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],a.getResult=function(a){return a&&this._rawResponse?this._rawResponse:this._response},a.cancel=function(){this.canceled=!0,this._clean(),this._request.abort()},a.load=function(){if(null==this._request)return void this._handleError();null!=this._request.addEventListener?(this._request.addEventListener("loadstart",this._handleLoadStartProxy,!1),this._request.addEventListener("progress",this._handleProgressProxy,!1),this._request.addEventListener("abort",this._handleAbortProxy,!1),this._request.addEventListener("error",this._handleErrorProxy,!1),this._request.addEventListener("timeout",this._handleTimeoutProxy,!1),this._request.addEventListener("load",this._handleLoadProxy,!1),this._request.addEventListener("readystatechange",this._handleReadyStateChangeProxy,!1)):(this._request.onloadstart=this._handleLoadStartProxy,this._request.onprogress=this._handleProgressProxy,this._request.onabort=this._handleAbortProxy,this._request.onerror=this._handleErrorProxy,this._request.ontimeout=this._handleTimeoutProxy,this._request.onload=this._handleLoadProxy,this._request.onreadystatechange=this._handleReadyStateChangeProxy),1==this._xhrLevel&&(this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout));try{this._item.values?this._request.send(createjs.URLUtils.formatQueryString(this._item.values)):this._request.send()}catch(a){this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND",null,a))}},a.setResponseType=function(a){"blob"===a&&(a=window.URL?"blob":"arraybuffer",this._responseType=a),this._request.responseType=a},a.getAllResponseHeaders=function(){return this._request.getAllResponseHeaders instanceof Function?this._request.getAllResponseHeaders():null},a.getResponseHeader=function(a){return this._request.getResponseHeader instanceof Function?this._request.getResponseHeader(a):null},a._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.ProgressEvent(a.loaded,a.total);this.dispatchEvent(b)}},a._handleLoadStart=function(){clearTimeout(this._loadTimeout),this.dispatchEvent("loadstart")},a._handleAbort=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED",null,a))},a._handleError=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent(a.message))},a._handleReadyStateChange=function(){4==this._request.readyState&&this._handleLoad()},a._handleLoad=function(){if(!this.loaded){this.loaded=!0;var a=this._checkError();if(a)return void this._handleError(a);if(this._response=this._getResponse(),"arraybuffer"===this._responseType)try{this._response=new Blob([this._response])}catch(b){if(window.BlobBuilder=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,"TypeError"===b.name&&window.BlobBuilder){var c=new BlobBuilder;c.append(this._response),this._response=c.getBlob()}}this._clean(),this.dispatchEvent(new createjs.Event("complete"))}},a._handleTimeout=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT",null,a))},a._checkError=function(){var a=parseInt(this._request.status);return a>=400&&599>=a?new Error(a):0==a&&/^https?:/.test(location.protocol)?new Error(0):null},a._getResponse=function(){if(null!=this._response)return this._response; +if(null!=this._request.response)return this._request.response;try{if(null!=this._request.responseText)return this._request.responseText}catch(a){}try{if(null!=this._request.responseXML)return this._request.responseXML}catch(a){}return null},a._createXHR=function(a){var b=createjs.URLUtils.isCrossDomain(a),c={},d=null;if(window.XMLHttpRequest)d=new XMLHttpRequest,b&&void 0===d.withCredentials&&window.XDomainRequest&&(d=new XDomainRequest);else{for(var e=0,f=s.ACTIVEX_VERSIONS.length;f>e;e++){var g=s.ACTIVEX_VERSIONS[e];try{d=new ActiveXObject(g);break}catch(h){}}if(null==d)return!1}null==a.mimeType&&createjs.RequestUtils.isText(a.type)&&(a.mimeType="text/plain; charset=utf-8"),a.mimeType&&d.overrideMimeType&&d.overrideMimeType(a.mimeType),this._xhrLevel="string"==typeof d.responseType?2:1;var i=null;if(i=a.method==createjs.Methods.GET?createjs.URLUtils.buildURI(a.src,a.values):a.src,d.open(a.method||createjs.Methods.GET,i,!0),b&&d instanceof XMLHttpRequest&&1==this._xhrLevel&&(c.Origin=location.origin),a.values&&a.method==createjs.Methods.POST&&(c["Content-Type"]="application/x-www-form-urlencoded"),b||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest"),a.headers)for(var j in a.headers)c[j]=a.headers[j];for(j in c)d.setRequestHeader(j,c[j]);return d instanceof XMLHttpRequest&&void 0!==a.withCredentials&&(d.withCredentials=a.withCredentials),this._request=d,!0},a._clean=function(){clearTimeout(this._loadTimeout),null!=this._request.removeEventListener?(this._request.removeEventListener("loadstart",this._handleLoadStartProxy),this._request.removeEventListener("progress",this._handleProgressProxy),this._request.removeEventListener("abort",this._handleAbortProxy),this._request.removeEventListener("error",this._handleErrorProxy),this._request.removeEventListener("timeout",this._handleTimeoutProxy),this._request.removeEventListener("load",this._handleLoadProxy),this._request.removeEventListener("readystatechange",this._handleReadyStateChangeProxy)):(this._request.onloadstart=null,this._request.onprogress=null,this._request.onabort=null,this._request.onerror=null,this._request.ontimeout=null,this._request.onload=null,this._request.onreadystatechange=null)},a.toString=function(){return"[PreloadJS XHRRequest]"},createjs.XHRRequest=createjs.promote(XHRRequest,"AbstractRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function LoadQueue(a,b,c){this.AbstractLoader_constructor(),this._plugins=[],this._typeCallbacks={},this._extensionCallbacks={},this.next=null,this.maintainScriptOrder=!0,this.stopOnError=!1,this._maxConnections=1,this._availableLoaders=[createjs.FontLoader,createjs.ImageLoader,createjs.JavaScriptLoader,createjs.CSSLoader,createjs.JSONLoader,createjs.JSONPLoader,createjs.SoundLoader,createjs.ManifestLoader,createjs.SpriteSheetLoader,createjs.XMLLoader,createjs.SVGLoader,createjs.BinaryLoader,createjs.VideoLoader,createjs.TextLoader],this._defaultLoaderLength=this._availableLoaders.length,this.init(a,b,c)}var a=createjs.extend(LoadQueue,createjs.AbstractLoader),b=LoadQueue;try{Object.defineProperties(b,{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(c){}a.init=function(a,b,c){this.preferXHR=!0,this._preferXHR=!0,this.setPreferXHR(a),this._paused=!1,this._basePath=b,this._crossOrigin=c,this._loadStartWasDispatched=!1,this._currentlyLoadingScript=null,this._currentLoads=[],this._loadQueue=[],this._loadQueueBackup=[],this._loadItemsById={},this._loadItemsBySrc={},this._loadedResults={},this._loadedRawResults={},this._numItems=0,this._numItemsLoaded=0,this._scriptOrder=[],this._loadedScripts=[],this._lastProgress=0/0},a.registerLoader=function(a){if(!a||!a.canLoadItem)throw new Error("loader is of an incorrect type.");if(-1!=this._availableLoaders.indexOf(a))throw new Error("loader already exists.");this._availableLoaders.unshift(a)},a.unregisterLoader=function(a){var b=this._availableLoaders.indexOf(a);-1!=b&&b0)return;var c=!1;if(b){for(;b.length;){var d=b.pop(),e=this.getResult(d);for(f=this._loadQueue.length-1;f>=0;f--)if(g=this._loadQueue[f].getItem(),g.id==d||g.src==d){this._loadQueue.splice(f,1)[0].cancel();break}for(f=this._loadQueueBackup.length-1;f>=0;f--)if(g=this._loadQueueBackup[f].getItem(),g.id==d||g.src==d){this._loadQueueBackup.splice(f,1)[0].cancel();break}if(e)this._disposeItem(this.getItem(d));else for(var f=this._currentLoads.length-1;f>=0;f--){var g=this._currentLoads[f].getItem();if(g.id==d||g.src==d){this._currentLoads.splice(f,1)[0].cancel(),c=!0;break}}}c&&this._loadNext()}else{this.close();for(var h in this._loadItemsById)this._disposeItem(this._loadItemsById[h]);this.init(this.preferXHR,this._basePath)}},a.reset=function(){this.close();for(var a in this._loadItemsById)this._disposeItem(this._loadItemsById[a]);for(var b=[],c=0,d=this._loadQueueBackup.length;d>c;c++)b.push(this._loadQueueBackup[c].getItem());this.loadManifest(b,!1)},a.installPlugin=function(a){if(null!=a&&null!=a.getPreloadHandlers){this._plugins.push(a);var b=a.getPreloadHandlers();if(b.scope=a,null!=b.types)for(var c=0,d=b.types.length;d>c;c++)this._typeCallbacks[b.types[c]]=b;if(null!=b.extensions)for(c=0,d=b.extensions.length;d>c;c++)this._extensionCallbacks[b.extensions[c]]=b}},a.setMaxConnections=function(a){this._maxConnections=a,!this._paused&&this._loadQueue.length>0&&this._loadNext()},a.loadFile=function(a,b,c){if(null==a){var d=new createjs.ErrorEvent("PRELOAD_NO_FILE");return void this._sendError(d)}this._addItem(a,null,c),this.setPaused(b!==!1?!1:!0)},a.loadManifest=function(a,c,d){var e=null,f=null;if(Array.isArray(a)){if(0==a.length){var g=new createjs.ErrorEvent("PRELOAD_MANIFEST_EMPTY");return void this._sendError(g)}e=a}else if("string"==typeof a)e=[{src:a,type:b.MANIFEST}];else{if("object"!=typeof a){var g=new createjs.ErrorEvent("PRELOAD_MANIFEST_NULL");return void this._sendError(g)}if(void 0!==a.src){if(null==a.type)a.type=b.MANIFEST;else if(a.type!=b.MANIFEST){var g=new createjs.ErrorEvent("PRELOAD_MANIFEST_TYPE");this._sendError(g)}e=[a]}else void 0!==a.manifest&&(e=a.manifest,f=a.path)}for(var h=0,i=e.length;i>h;h++)this._addItem(e[h],f,d);this.setPaused(c!==!1?!1:!0)},a.load=function(){this.setPaused(!1)},a.getItem=function(a){return this._loadItemsById[a]||this._loadItemsBySrc[a]},a.getResult=function(a,b){var c=this._loadItemsById[a]||this._loadItemsBySrc[a];if(null==c)return null;var d=c.id;return b&&this._loadedRawResults[d]?this._loadedRawResults[d]:this._loadedResults[d]},a.getItems=function(a){var b=[];for(var c in this._loadItemsById){var d=this._loadItemsById[c],e=this.getResult(c);(a!==!0||null!=e)&&b.push({item:d,result:e,rawResult:this.getResult(c,!0)})}return b},a.setPaused=function(a){this._paused=a,this._paused||this._loadNext()},a.close=function(){for(;this._currentLoads.length;)this._currentLoads.pop().cancel();this._scriptOrder.length=0,this._loadedScripts.length=0,this.loadStartWasDispatched=!1,this._itemCount=0,this._lastProgress=0/0},a._addItem=function(a,b,c){var d=this._createLoadItem(a,b,c);if(null!=d){var e=this._createLoader(d);null!=e&&("plugins"in e&&(e.plugins=this._plugins),d._loader=e,this._loadQueue.push(e),this._loadQueueBackup.push(e),this._numItems++,this._updateProgress(),(this.maintainScriptOrder&&d.type==createjs.Types.JAVASCRIPT||d.maintainOrder===!0)&&(this._scriptOrder.push(d),this._loadedScripts.push(null)))}},a._createLoadItem=function(a,b,c){var d=createjs.LoadItem.create(a);if(null==d)return null;var e="",f=c||this._basePath;if(d.src instanceof Object){if(!d.type)return null;if(b){e=b;var g=createjs.URLUtils.parseURI(b);null==f||g.absolute||g.relative||(e=f+e)}else null!=f&&(e=f)}else{var h=createjs.URLUtils.parseURI(d.src);h.extension&&(d.ext=h.extension),null==d.type&&(d.type=createjs.RequestUtils.getTypeByExtension(d.ext));var i=d.src;if(!h.absolute&&!h.relative)if(b){e=b;var g=createjs.URLUtils.parseURI(b);i=b+i,null==f||g.absolute||g.relative||(e=f+e)}else null!=f&&(e=f);d.src=e+d.src}d.path=e,(void 0===d.id||null===d.id||""===d.id)&&(d.id=i);var j=this._typeCallbacks[d.type]||this._extensionCallbacks[d.ext];if(j){var k=j.callback.call(j.scope,d,this);if(k===!1)return null;k===!0||null!=k&&(d._loader=k),h=createjs.URLUtils.parseURI(d.src),null!=h.extension&&(d.ext=h.extension)}return this._loadItemsById[d.id]=d,this._loadItemsBySrc[d.src]=d,null==d.crossOrigin&&(d.crossOrigin=this._crossOrigin),d},a._createLoader=function(a){if(null!=a._loader)return a._loader;for(var b=this.preferXHR,c=0;c=this._maxConnections);a++){var b=this._loadQueue[a];this._canStartLoad(b)&&(this._loadQueue.splice(a,1),a--,this._loadItem(b))}}},a._loadItem=function(a){a.on("fileload",this._handleFileLoad,this),a.on("progress",this._handleProgress,this),a.on("complete",this._handleFileComplete,this),a.on("error",this._handleError,this),a.on("fileerror",this._handleFileError,this),this._currentLoads.push(a),this._sendFileStart(a.getItem()),a.load()},a._handleFileLoad=function(a){a.target=null,this.dispatchEvent(a)},a._handleFileError=function(a){var b=new createjs.ErrorEvent("FILE_LOAD_ERROR",null,a.item);this._sendError(b)},a._handleError=function(a){var b=a.target;this._numItemsLoaded++,this._finishOrderedItem(b,!0),this._updateProgress();var c=new createjs.ErrorEvent("FILE_LOAD_ERROR",null,b.getItem());this._sendError(c),this.stopOnError?this.setPaused(!0):(this._removeLoadItem(b),this._cleanLoadItem(b),this._loadNext())},a._handleFileComplete=function(a){var b=a.target,c=b.getItem(),d=b.getResult();this._loadedResults[c.id]=d;var e=b.getResult(!0);null!=e&&e!==d&&(this._loadedRawResults[c.id]=e),this._saveLoadedItems(b),this._removeLoadItem(b),this._finishOrderedItem(b)||this._processFinishedLoad(c,b),this._cleanLoadItem(b)},a._saveLoadedItems=function(a){var b=a.getLoadedItems();if(null!==b)for(var c=0;cb;b++){var c=this._loadedScripts[b];if(null===c)break;if(c!==!0){var d=this._loadedResults[c.id];c.type==createjs.Types.JAVASCRIPT&&createjs.DomUtils.appendToHead(d);var e=c._loader;this._processFinishedLoad(c,e),this._loadedScripts[b]=!0}}},a._processFinishedLoad=function(a,b){if(this._numItemsLoaded++,!this.maintainScriptOrder&&a.type==createjs.Types.JAVASCRIPT){var c=b.getTag();createjs.DomUtils.appendToHead(c)}this._updateProgress(),this._sendFileComplete(a,b),this._loadNext()},a._canStartLoad=function(a){if(!this.maintainScriptOrder||a.preferXHR)return!0;var b=a.getItem();if(b.type!=createjs.Types.JAVASCRIPT)return!0;if(this._currentlyLoadingScript)return!1;for(var c=this._scriptOrder.indexOf(b),d=0;c>d;){var e=this._loadedScripts[d];if(null==e)return!1;d++}return this._currentlyLoadingScript=!0,!0},a._removeLoadItem=function(a){for(var b=this._currentLoads.length,c=0;b>c;c++)if(this._currentLoads[c]==a){this._currentLoads.splice(c,1);break}},a._cleanLoadItem=function(a){var b=a.getItem();b&&delete b._loader},a._handleProgress=function(a){var b=a.target;this._sendFileProgress(b.getItem(),b.progress),this._updateProgress()},a._updateProgress=function(){var a=this._numItemsLoaded/this._numItems,b=this._numItems-this._numItemsLoaded;if(b>0){for(var c=0,d=0,e=this._currentLoads.length;e>d;d++)c+=this._currentLoads[d].progress;a+=c/b*(b/this._numItems)}this._lastProgress!=a&&(this._sendProgress(a),this._lastProgress=a)},a._disposeItem=function(a){delete this._loadedResults[a.id],delete this._loadedRawResults[a.id],delete this._loadItemsById[a.id],delete this._loadItemsBySrc[a.src]},a._sendFileProgress=function(a,b){if(!this._isCanceled()&&!this._paused&&this.hasEventListener("fileprogress")){var c=new createjs.Event("fileprogress");c.progress=b,c.loaded=b,c.total=1,c.item=a,this.dispatchEvent(c)}},a._sendFileComplete=function(a,b){if(!this._isCanceled()&&!this._paused){var c=new createjs.Event("fileload");c.loader=b,c.item=a,c.result=this._loadedResults[a.id],c.rawResult=this._loadedRawResults[a.id],a.completeHandler&&a.completeHandler(c),this.hasEventListener("fileload")&&this.dispatchEvent(c)}},a._sendFileStart=function(a){var b=new createjs.Event("filestart");b.item=a,this.hasEventListener("filestart")&&this.dispatchEvent(b)},a.toString=function(){return"[PreloadJS LoadQueue]"},createjs.LoadQueue=createjs.promote(LoadQueue,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function TextLoader(a){this.AbstractLoader_constructor(a,!0,createjs.Types.TEXT)}var a=(createjs.extend(TextLoader,createjs.AbstractLoader),TextLoader);a.canLoadItem=function(a){return a.type==createjs.Types.TEXT},createjs.TextLoader=createjs.promote(TextLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function BinaryLoader(a){this.AbstractLoader_constructor(a,!0,createjs.Types.BINARY),this.on("initialize",this._updateXHR,this)}var a=createjs.extend(BinaryLoader,createjs.AbstractLoader),b=BinaryLoader;b.canLoadItem=function(a){return a.type==createjs.Types.BINARY},a._updateXHR=function(a){a.loader.setResponseType("arraybuffer")},createjs.BinaryLoader=createjs.promote(BinaryLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function CSSLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.Types.CSS),this.resultFormatter=this._formatResult,this._tagSrcAttribute="href",this._tag=b?createjs.Elements.style():createjs.Elements.link(),this._tag.rel="stylesheet",this._tag.type="text/css"}var a=createjs.extend(CSSLoader,createjs.AbstractLoader),b=CSSLoader;b.canLoadItem=function(a){return a.type==createjs.Types.CSS},a._formatResult=function(a){if(this._preferXHR){var b=a.getTag();if(b.styleSheet)b.styleSheet.cssText=a.getResult(!0);else{var c=createjs.Elements.text(a.getResult(!0));b.appendChild(c)}}else b=this._tag;return createjs.DomUtils.appendToHead(b),b},createjs.CSSLoader=createjs.promote(CSSLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function FontLoader(a,b){this.AbstractLoader_constructor(a,b,a.type),this._faces={},this._watched=[],this._count=0,this._watchInterval=null,this._loadTimeout=null,this._injectCSS=void 0===a.injectCSS?!0:a.injectCSS,this.dispatchEvent("initialize")}var a=createjs.extend(FontLoader,createjs.AbstractLoader);FontLoader.canLoadItem=function(a){return a.type==createjs.Types.FONT||a.type==createjs.Types.FONTCSS},FontLoader.sampleText="abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ",FontLoader._ctx=document.createElement("canvas").getContext("2d"),FontLoader._referenceFonts=["serif","monospace"],FontLoader.WEIGHT_REGEX=/[- ._]*(thin|normal|book|regular|medium|black|heavy|[1-9]00|(?:extra|ultra|semi|demi)?[- ._]*(?:light|bold))[- ._]*/gi,FontLoader.STYLE_REGEX=/[- ._]*(italic|oblique)[- ._]*/gi,FontLoader.FONT_FORMAT={woff2:"woff2",woff:"woff",ttf:"truetype",otf:"truetype"},FontLoader.FONT_WEIGHT={thin:100,extralight:200,ultralight:200,light:300,semilight:300,demilight:300,book:"normal",regular:"normal",semibold:600,demibold:600,extrabold:800,ultrabold:800,black:900,heavy:900},FontLoader.WATCH_DURATION=10,a.load=function(){if(this.type==createjs.Types.FONTCSS){var a=this._watchCSS();if(!a)return void this.AbstractLoader_load()}else if(this._item.src instanceof Array)this._watchFontArray();else{var b=this._defFromSrc(this._item.src);this._watchFont(b),this._injectStyleTag(this._cssFromDef(b))}this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout),this.dispatchEvent("loadstart")},a._handleTimeout=function(){this._stopWatching(),this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT"))},a._createRequest=function(){return this._request},a.handleEvent=function(a){switch(a.type){case"complete":this._rawResult=a.target._response,this._result=!0,this._parseCSS(this._rawResult);break;case"error":this._stopWatching(),this.AbstractLoader_handleEvent(a)}},a._watchCSS=function(){var a=this._item.src;return a instanceof HTMLStyleElement&&(this._injectCSS&&!a.parentNode&&(document.head||document.getElementsByTagName("head")[0]).appendChild(a),this._injectCSS=!1,a="\n"+a.textContent),-1!==a.search(/\n|\r|@font-face/i)?(this._parseCSS(a),!0):(this._request=new createjs.XHRRequest(this._item),!1)},a._parseCSS=function(a){for(var b=/@font-face\s*\{([^}]+)}/g;;){var c=b.exec(a);if(!c)break;this._watchFont(this._parseFontFace(c[1]))}this._injectStyleTag(a)},a._watchFontArray=function(){for(var a,b=this._item.src,c="",d=b.length-1;d>=0;d--){var e=b[d];a="string"==typeof e?this._defFromSrc(e):this._defFromObj(e),this._watchFont(a),c+=this._cssFromDef(a)+"\n"}this._injectStyleTag(c)},a._injectStyleTag=function(a){if(this._injectCSS){var b=document.head||document.getElementsByTagName("head")[0],c=document.createElement("style");c.type="text/css",c.styleSheet?c.styleSheet.cssText=a:c.appendChild(document.createTextNode(a)),b.appendChild(c)}},a._parseFontFace=function(a){var b=this._getCSSValue(a,"font-family"),c=this._getCSSValue(a,"src");return b&&c?this._defFromObj({family:b,src:c,style:this._getCSSValue(a,"font-style"),weight:this._getCSSValue(a,"font-weight")}):null},a._watchFont=function(a){a&&!this._faces[a.id]&&(this._faces[a.id]=a,this._watched.push(a),this._count++,this._calculateReferenceSizes(a),this._startWatching())},a._startWatching=function(){null==this._watchInterval&&(this._watchInterval=setInterval(createjs.proxy(this._watch,this),FontLoader.WATCH_DURATION))},a._stopWatching=function(){clearInterval(this._watchInterval),clearTimeout(this._loadTimeout),this._watchInterval=null},a._watch=function(){for(var a=this._watched,b=FontLoader._referenceFonts,c=a.length,d=c-1;d>=0;d--)for(var e=a[d],f=e.refs,g=f.length-1;g>=0;g--){var h=this._getTextWidth(e.family+","+b[g],e.weight,e.style);if(h!=f[g]){var i=new createjs.Event("fileload");e.type="font-family",i.item=e,this.dispatchEvent(i),a.splice(d,1);break}}if(c!==a.length){var i=new createjs.ProgressEvent(this._count-a.length,this._count);this.dispatchEvent(i)}0===c&&(this._stopWatching(),this._sendComplete())},a._calculateReferenceSizes=function(a){for(var b=FontLoader._referenceFonts,c=a.refs=[],d=0;dc;c++)b.installPlugin(this.plugins[c]);b.loadManifest(a)}else this._sendComplete()},a._handleManifestFileLoad=function(a){a.target=null,this.dispatchEvent(a)},a._handleManifestComplete=function(){this._loadedItems=this._manifestQueue.getItems(!0),this._sendComplete()},a._handleManifestProgress=function(a){this.progress=a.progress*(1-b.MANIFEST_PROGRESS)+b.MANIFEST_PROGRESS,this._sendProgress(this.progress)},a._handleManifestError=function(a){var b=new createjs.Event("fileerror");b.item=a.data,this.dispatchEvent(b)},createjs.ManifestLoader=createjs.promote(ManifestLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function SoundLoader(a,b){this.AbstractMediaLoader_constructor(a,b,createjs.Types.SOUND),createjs.DomUtils.isAudioTag(a)?this._tag=a:createjs.DomUtils.isAudioTag(a.src)?this._tag=a:createjs.DomUtils.isAudioTag(a.tag)&&(this._tag=createjs.DomUtils.isAudioTag(a)?a:a.src),null!=this._tag&&(this._preferXHR=!1)}var a=createjs.extend(SoundLoader,createjs.AbstractMediaLoader),b=SoundLoader;b.canLoadItem=function(a){return a.type==createjs.Types.SOUND},a._createTag=function(a){var b=createjs.Elements.audio();return b.autoplay=!1,b.preload="none",b.src=a,b},createjs.SoundLoader=createjs.promote(SoundLoader,"AbstractMediaLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function VideoLoader(a,b){this.AbstractMediaLoader_constructor(a,b,createjs.Types.VIDEO),createjs.DomUtils.isVideoTag(a)||createjs.DomUtils.isVideoTag(a.src)?(this.setTag(createjs.DomUtils.isVideoTag(a)?a:a.src),this._preferXHR=!1):this.setTag(this._createTag())}var a=createjs.extend(VideoLoader,createjs.AbstractMediaLoader),b=VideoLoader;a._createTag=function(){return createjs.Elements.video()},b.canLoadItem=function(a){return a.type==createjs.Types.VIDEO},createjs.VideoLoader=createjs.promote(VideoLoader,"AbstractMediaLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function SpriteSheetLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.Types.SPRITESHEET),this._manifestQueue=null}var a=createjs.extend(SpriteSheetLoader,createjs.AbstractLoader),b=SpriteSheetLoader;b.SPRITESHEET_PROGRESS=.25,b.canLoadItem=function(a){return a.type==createjs.Types.SPRITESHEET},a.destroy=function(){this.AbstractLoader_destroy(),this._manifestQueue.close()},a._createRequest=function(){var a=this._item.callback;this._request=null!=a?new createjs.JSONPLoader(this._item):new createjs.JSONLoader(this._item)},a.handleEvent=function(a){switch(a.type){case"complete":return this._rawResult=a.target.getResult(!0),this._result=a.target.getResult(),this._sendProgress(b.SPRITESHEET_PROGRESS),void this._loadManifest(this._result);case"progress":return a.loaded*=b.SPRITESHEET_PROGRESS,this.progress=a.loaded/a.total,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0),void this._sendProgress(a)}this.AbstractLoader_handleEvent(a)},a._loadManifest=function(a){if(a&&a.images){var b=this._manifestQueue=new createjs.LoadQueue(this._preferXHR,this._item.path,this._item.crossOrigin);b.on("complete",this._handleManifestComplete,this,!0),b.on("fileload",this._handleManifestFileLoad,this),b.on("progress",this._handleManifestProgress,this),b.on("error",this._handleManifestError,this,!0),b.loadManifest(a.images)}},a._handleManifestFileLoad=function(a){var b=a.result;if(null!=b){var c=this.getResult().images,d=c.indexOf(a.item.src);c[d]=b}},a._handleManifestComplete=function(){this._result=new createjs.SpriteSheet(this._result),this._loadedItems=this._manifestQueue.getItems(!0),this._sendComplete()},a._handleManifestProgress=function(a){this.progress=a.progress*(1-b.SPRITESHEET_PROGRESS)+b.SPRITESHEET_PROGRESS,this._sendProgress(this.progress)},a._handleManifestError=function(a){var b=new createjs.Event("fileerror");b.item=a.data,this.dispatchEvent(b)},createjs.SpriteSheetLoader=createjs.promote(SpriteSheetLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function SVGLoader(a,b){this.AbstractLoader_constructor(a,b,createjs.Types.SVG),this.resultFormatter=this._formatResult,this._tagSrcAttribute="data",b?this.setTag(createjs.Elements.svg()):(this.setTag(createjs.Elements.object()),this.getTag().type="image/svg+xml") +}var a=createjs.extend(SVGLoader,createjs.AbstractLoader),b=SVGLoader;b.canLoadItem=function(a){return a.type==createjs.Types.SVG},a._formatResult=function(a){var b=createjs.DataUtils.parseXML(a.getResult(!0)),c=a.getTag();if(!this._preferXHR&&document.body.contains(c)&&document.body.removeChild(c),null!=b.documentElement){var d=b.documentElement;return document.importNode&&(d=document.importNode(d,!0)),c.appendChild(d),c}return b},createjs.SVGLoader=createjs.promote(SVGLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function XMLLoader(a){this.AbstractLoader_constructor(a,!0,createjs.Types.XML),this.resultFormatter=this._formatResult}var a=createjs.extend(XMLLoader,createjs.AbstractLoader),b=XMLLoader;b.canLoadItem=function(a){return a.type==createjs.Types.XML},a._formatResult=function(a){return createjs.DataUtils.parseXML(a.getResult(!0))},createjs.XMLLoader=createjs.promote(XMLLoader,"AbstractLoader")}(); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 00000000..24cd55f8 --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "preloadjs", + "npmName": "preloadjs", + "version": "1.0.1", + "description": "PreloadJS makes it easy to preload your assets: images, sounds, JavaScript, fonts, JSON, and text data", + "main": "lib/preloadjs.js", + "jsdelivr": "lib/preloadjs.min.js", + "directories": { + "doc": "docs", + "example": "examples", + "lib": "lib", + "test": "tests" + }, + "npmFileMap": [ + { + "basePath": "lib", + "files": [ + "**/*" + ] + } + ], + "repository": { + "type": "git", + "url": "git+https://github.com/CreateJS/PreloadJS.git" + }, + "keywords": [ + "createjs", + "preloadjs", + "gskinner", + "preload", + "preloading", + "progress", + "XHR", + "javascript", + "html5" + ], + "author": "gskinner.com, inc.", + "license": "MIT", + "bugs": { + "url": "https://github.com/CreateJS/PreloadJS/issues" + }, + "homepage": "https://createjs.com/preloadjs/" +} diff --git a/spikes/FontLoading/fonts/regul-bold.woff b/spikes/FontLoading/fonts/regul-bold.woff new file mode 100644 index 00000000..f526d85e Binary files /dev/null and b/spikes/FontLoading/fonts/regul-bold.woff differ diff --git a/spikes/FontLoading/fonts/regul-book.woff b/spikes/FontLoading/fonts/regul-book.woff new file mode 100644 index 00000000..51abdeab Binary files /dev/null and b/spikes/FontLoading/fonts/regul-book.woff differ diff --git a/spikes/FontLoading/testArr.html b/spikes/FontLoading/testArr.html new file mode 100644 index 00000000..691e5f9c --- /dev/null +++ b/spikes/FontLoading/testArr.html @@ -0,0 +1,45 @@ + + + + + + + + + +
    + Hello World! +
    +
    + Hello World! +
    +
    + + +
    + + + \ No newline at end of file diff --git a/spikes/FontLoading/testArrSrc.html b/spikes/FontLoading/testArrSrc.html new file mode 100644 index 00000000..a9b8e36d --- /dev/null +++ b/spikes/FontLoading/testArrSrc.html @@ -0,0 +1,35 @@ + + + + + + + + + + +
    + Hello World! +
    +
    + Hello World! +
    +
    + + +
    + + + \ No newline at end of file diff --git a/spikes/FontLoading/testCSS.html b/spikes/FontLoading/testCSS.html new file mode 100644 index 00000000..7be66f1f --- /dev/null +++ b/spikes/FontLoading/testCSS.html @@ -0,0 +1,45 @@ + + + + + + + + + + + +
    + Hello World! +
    +
    + Hello World! +
    +
    + + +
    + + + \ No newline at end of file diff --git a/spikes/FontLoading/testGoogleFonts.html b/spikes/FontLoading/testGoogleFonts.html new file mode 100644 index 00000000..4823f4e6 --- /dev/null +++ b/spikes/FontLoading/testGoogleFonts.html @@ -0,0 +1,29 @@ + + + + + + + + + + +
    + Hello World! +
    +
    + + +
    + + + \ No newline at end of file diff --git a/spikes/FontLoading/testSrc.html b/spikes/FontLoading/testSrc.html new file mode 100644 index 00000000..2c4fcdd8 --- /dev/null +++ b/spikes/FontLoading/testSrc.html @@ -0,0 +1,31 @@ + + + + + + + + + + + +
    + Hello World! +
    +
    + + +
    + + + \ No newline at end of file diff --git a/spikes/FontLoading/typekit.html b/spikes/FontLoading/typekit.html new file mode 100644 index 00000000..04b58aa2 --- /dev/null +++ b/spikes/FontLoading/typekit.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/createjs/events/ErrorEvent.js b/src/createjs/events/ErrorEvent.js new file mode 100644 index 00000000..88ed99b2 --- /dev/null +++ b/src/createjs/events/ErrorEvent.js @@ -0,0 +1,80 @@ +/* +* Event +* Visit http://createjs.com/ for documentation, updates and examples. +* +* Copyright (c) 2010 gskinner.com, inc. +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following +* conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +*/ + +/** + * @module CreateJS + */ + +// namespace: +this.createjs = this.createjs||{}; + +(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"); + +}()); \ No newline at end of file diff --git a/src/createjs/events/Event.js b/src/createjs/events/Event.js index 1dc3820e..f010e269 100644 --- a/src/createjs/events/Event.js +++ b/src/createjs/events/Event.js @@ -28,9 +28,10 @@ /** * A collection of Classes that are shared across all the CreateJS libraries. The classes are included in the minified - * files of each library and are available on the createsjs namespace directly. + * files of each library and are available on the createjs namespace directly. * *

    Example

    + * * myObject.addEventListener("change", createjs.proxy(myMethod, scope)); * * @module CreateJS @@ -43,164 +44,146 @@ this.createjs = this.createjs||{}; (function() { "use strict"; -/** - * Contains properties and methods shared by all events for use with - * {{#crossLink "EventDispatcher"}}{{/crossLink}}. - * - * Note that Event objects are often reused, so you should never - * rely on an event object's state outside of the call stack it was received in. - * @class Event - * @param {String} type The event type. - * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. - * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. - * @constructor - **/ -var Event = function(type, bubbles, cancelable) { - this.initialize(type, bubbles, cancelable); -}; -var p = Event.prototype; - -// events: - -// public properties: - - /** - * The type of event. - * @property type - * @type String - **/ - p.type = null; - - /** - * The object that generated an event. - * @property target - * @type Object - * @default null - * @readonly - */ - p.target = null; - - /** - * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will - * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event - * is generated from childObj, then a listener on parentObj would receive the event with - * target=childObj (the original target) and currentTarget=parentObj (where the listener was added). - * @property currentTarget - * @type Object - * @default null - * @readonly - */ - p.currentTarget = null; - - /** - * For bubbling events, this indicates the current event phase:
      - *
    1. capture phase: starting from the top parent to the target
    2. - *
    3. at target phase: currently being dispatched from the target
    4. - *
    5. bubbling phase: from the target to the top parent
    6. - *
    - * @property eventPhase - * @type Number - * @default 0 - * @readonly - */ - p.eventPhase = 0; - - /** - * Indicates whether the event will bubble through the display list. - * @property bubbles - * @type Boolean - * @default false - * @readonly - */ - p.bubbles = false; - - /** - * 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 - */ - p.cancelable = false; - - /** - * The epoch time at which this event was created. - * @property timeStamp - * @type Number - * @default 0 - * @readonly - */ - p.timeStamp = 0; - - /** - * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called - * on this event. - * @property defaultPrevented - * @type Boolean - * @default false - * @readonly - */ - p.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 - */ - p.propagationStopped = false; - - /** - * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called - * on this event. - * @property immediatePropagationStopped - * @type Boolean - * @default false - * @readonly - */ - p.immediatePropagationStopped = false; - - /** - * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event. - * @property removed - * @type Boolean - * @default false - * @readonly - */ - p.removed = false; - // constructor: /** - * Initialization method. - * @method initialize + * Contains properties and methods shared by all events for use with + * {{#crossLink "EventDispatcher"}}{{/crossLink}}. + * + * Note that Event objects are often reused, so you should never + * rely on an event object's state outside of the call stack it was received in. + * @class Event * @param {String} type The event type. - * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. - * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. - * @protected + * @param {Boolean} [bubbles=false] Indicates whether the event will bubble through the display list. + * @param {Boolean} [cancelable=false] Indicates whether the default behaviour of this event can be cancelled. + * @constructor **/ - p.initialize = function(type, bubbles, cancelable) { + function Event(type, bubbles, cancelable) { + + + // public properties: + /** + * The type of event. + * @property type + * @type String + **/ this.type = type; - this.bubbles = bubbles; - this.cancelable = cancelable; + + /** + * The object that generated an event. + * @property target + * @type Object + * @default null + * @readonly + */ + this.target = null; + + /** + * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will + * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event + * is generated from childObj, then a listener on parentObj would receive the event with + * target=childObj (the original target) and currentTarget=parentObj (where the listener was added). + * @property currentTarget + * @type Object + * @default null + * @readonly + */ + this.currentTarget = null; + + /** + * For bubbling events, this indicates the current event phase:
      + *
    1. capture phase: starting from the top parent to the target
    2. + *
    3. at target phase: currently being dispatched from the target
    4. + *
    5. bubbling phase: from the target to the top parent
    6. + *
    + * @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. - * Mirrors the DOM event standard. + * Sets {{#crossLink "Event/defaultPrevented:property"}}{{/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 = true; + this.defaultPrevented = this.cancelable&&true; }; /** - * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true. + * Sets {{#crossLink "Event/propagationStopped:property"}}{{/crossLink}} to true. * Mirrors the DOM event standard. * @method stopPropagation **/ @@ -209,8 +192,8 @@ var p = Event.prototype; }; /** - * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and - * {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true. + * Sets {{#crossLink "Event/propagationStopped:property"}}{{/crossLink}} and + * {{#crossLink "Event/immediatePropagationStopped:property"}}{{/crossLink}} to true. * Mirrors the DOM event standard. * @method stopImmediatePropagation **/ @@ -240,6 +223,19 @@ var p = Event.prototype; 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. @@ -250,5 +246,5 @@ var p = Event.prototype; return "[Event (type="+this.type+")]"; }; -createjs.Event = Event; + createjs.Event = Event; }()); diff --git a/src/createjs/events/EventDispatcher.js b/src/createjs/events/EventDispatcher.js index 361d18bb..4526fa66 100644 --- a/src/createjs/events/EventDispatcher.js +++ b/src/createjs/events/EventDispatcher.js @@ -36,61 +36,83 @@ this.createjs = this.createjs||{}; (function() { "use strict"; -/** - * EventDispatcher provides methods for managing queues of event listeners and dispatching events. - * - * You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the - * EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method. - * - * Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the - * DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports - * bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent. - * - * EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier - * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The - * {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to - * {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}. - * - * Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}} - * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also - * includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener. - * - *

    Example

    - * Add EventDispatcher capabilities to the "MyClass" class. - * - * EventDispatcher.initialize(MyClass.prototype); - * - * Add an event (see {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}}). - * - * instance.addEventListener("eventName", handlerMethod); - * function handlerMethod(event) { - * console.log(event.target + " Was Clicked"); - * } - * - * Maintaining proper scope
    - * Scope (ie. "this") can be be a challenge with events. Using the {{#crossLink "EventDispatcher/on"}}{{/crossLink}} - * method to subscribe to events simplifies this. - * - * instance.addEventListener("click", function(event) { - * console.log(instance == this); // false, scope is ambiguous. - * }); - * - * instance.on("click", function(event) { - * console.log(instance == this); // true, "on" uses dispatcher scope by default. - * }); - * - * If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage scope. - * - * - * @class EventDispatcher - * @constructor - **/ -var EventDispatcher = function() { -/* this.initialize(); */ // not needed. -}; -var p = EventDispatcher.prototype; +// 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. * @@ -113,30 +135,6 @@ var p = EventDispatcher.prototype; target.willTrigger = p.willTrigger; }; -// constructor: - -// private properties: - /** - * @protected - * @property _listeners - * @type Object - **/ - p._listeners = null; - - /** - * @protected - * @property _captureListeners - * @type Object - **/ - p._captureListeners = null; - -// constructor: - /** - * Initialization method. - * @method initialize - * @protected - **/ - p.initialize = function() {}; // public methods: /** @@ -177,7 +175,11 @@ var p = EventDispatcher.prototype; * only run once, associate arbitrary data with the listener, and remove the listener. * * This method works by creating an anonymous wrapper function and subscribing it with addEventListener. - * The created anonymous function is returned for use with .removeEventListener (or .off). + * 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

    * @@ -247,6 +249,9 @@ var p = EventDispatcher.prototype; /** * A shortcut to the removeEventListener method, with the same parameters and return value. This is a companion to the * .on method. + * + * IMPORTANT: 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. @@ -292,20 +297,25 @@ var p = EventDispatcher.prototype; * @method dispatchEvent * @param {Object | String | Event} eventObj An object with a "type" property, or a string type. * While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used, - * dispatchEvent will construct an Event instance with the specified type. - * @param {Object} [target] The object to use as the target property of the event object. This will default to the - * dispatching object. This parameter is deprecated and will be removed. - * @return {Boolean} Returns the value of eventObj.defaultPrevented. + * 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, target) { + p.dispatchEvent = function(eventObj, bubbles, cancelable) { if (typeof eventObj == "string") { - // won't bubble, so skip everything if there's no listeners: + // skip everything if there's no listeners and it doesn't bubble: var listeners = this._listeners; - if (!listeners || !listeners[eventObj]) { return false; } - eventObj = new createjs.Event(eventObj); + 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: deprecated. Target param is deprecated, only use case is MouseEvent/mousemove, remove. - eventObj.target = target||this; + + // 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); @@ -323,7 +333,7 @@ var p = EventDispatcher.prototype; list[i]._dispatchEvent(eventObj, 3); } } - return eventObj.defaultPrevented; + return !eventObj.defaultPrevented; }; /** @@ -365,21 +375,21 @@ var p = EventDispatcher.prototype; return "[EventDispatcher]"; }; + // private methods: /** * @method _dispatchEvent - * @param {Object | String | Event} eventObj + * @param {Object | Event} eventObj * @param {Object} eventPhase * @protected **/ p._dispatchEvent = function(eventObj, eventPhase) { - var l, listeners = (eventPhase==1) ? this._captureListeners : this._listeners; - if (eventObj && listeners) { - var arr = listeners[eventObj.type]; - if (!arr||!(l=arr.length)) { return; } - eventObj.currentTarget = this; - eventObj.eventPhase = eventPhase; + var l, arr, listeners = (eventPhase <= 2) ? this._captureListeners : this._listeners; + if (eventObj && listeners && (arr = listeners[eventObj.type]) && (l=arr.length)) { + try { eventObj.currentTarget = this; } catch (e) {} + try { eventObj.eventPhase = eventPhase|0; } catch (e) {} eventObj.removed = false; + arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch for (var i=0; iExample + * * myObject.addEventListener("change", createjs.proxy(myMethod, scope)); * * @class Utility Methods @@ -55,6 +56,7 @@ this.createjs = this.createjs||{}; * 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) { @@ -75,4 +77,4 @@ this.createjs = this.createjs||{}; }; } -}()); \ No newline at end of file +}()); diff --git a/src/preloadjs/AbstractLoader.js b/src/preloadjs/AbstractLoader.js deleted file mode 100644 index 2ea56900..00000000 --- a/src/preloadjs/AbstractLoader.js +++ /dev/null @@ -1,456 +0,0 @@ -/* -* AbstractLoader -* Visit http://createjs.com/ for documentation, updates and examples. -* -* -* Copyright (c) 2012 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * @module PreloadJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - /** - * The base loader, which defines all the generic callbacks and events. All loaders extend this class, including the - * {{#crossLink "LoadQueue"}}{{/crossLink}}. - * @class AbstractLoader - * @extends EventDispatcher - */ - var AbstractLoader = function () { - this.init(); - }; - - AbstractLoader.prototype = new createjs.EventDispatcher(); //TODO: TEST! - var p = AbstractLoader.prototype; - var s = AbstractLoader; - - /** - * The Regular Expression used to test file URLS for an absolute path. - * @property ABSOLUTE_PATH - * @static - * @type {RegExp} - * @since 0.4.2 - */ - s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i; - - /** - * The Regular Expression used to test file URLS for an absolute path. - * @property RELATIVE_PATH - * @static - * @type {RegExp} - * @since 0.4.2 - */ - 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 - * @static - * @type {RegExp} - * @since 0.4.2 - */ - s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i; - - /** - * 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 event. - * @property loaded - * @type {Boolean} - * @default false - */ - p.loaded = false; - - /** - * Determine if the loader was canceled. Canceled loads will not fire complete events. Note that - * {{#crossLink "LoadQueue"}}{{/crossLink}} queues should be closed using {{#crossLink "AbstractLoader/close"}}{{/crossLink}} - * instead of setting this property. - * @property canceled - * @type {Boolean} - * @default false - */ - p.canceled = false; - - /** - * The current load progress (percentage) for this item. This will be a number between 0 and 1. - * - *

    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 - */ - p.progress = 0; - - /** - * The item this loader represents. Note that this is null in a {{#crossLink "LoadQueue"}}{{/crossLink}}, but will - * be available on loaders such as {{#crossLink "XHRLoader"}}{{/crossLink}} and {{#crossLink "TagLoader"}}{{/crossLink}}. - * @property _item - * @type {Object} - * @private - */ - p._item = null; - -// Events - /** - * The event that is fired when the overall progress changes. - * @event progress - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Number} loaded The amount that has been loaded so far. Note that this is may just be a percentage of 1, - * since file sizes can not be determined before a load is kicked off, if at all. - * @param {Number} total The total number of bytes. Note that this may just be 1. - * @param {Number} progress The ratio that has been loaded between 0 and 1. - * @since 0.3.0 - */ - - /** - * The event that is fired when a load starts. - * @event loadstart - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.3.1 - */ - - /** - * The event that is fired when the entire queue has been loaded. - * @event complete - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.3.0 - */ - - /** - * The event that is fired when the loader encounters an error. If the error was encountered by a file, the event will - * contain the item that caused the error. There may be additional properties such as the error reason on event - * objects. - * @event error - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Object} [item] The item that was being loaded that caused the error. The item was specified in - * the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * call. If only a string path or tag was specified, the object will contain that value as a `src` property. - * @param {String} [error] The error object or text. - * @since 0.3.0 - */ - - //TODO: Deprecated - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}} - * event. - * @property onProgress - * @type {Function} - * @deprecated Use addEventListener and the "progress" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}} - * event. - * @property onLoadStart - * @type {Function} - * @deprecated Use addEventListener and the "loadstart" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} - * event. - * @property onComplete - * @type {Function} - * @deprecated Use addEventListener and the "complete" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} - * event. - * @property onError - * @type {Function} - * @deprecated Use addEventListener and the "error" event. - */ - - /** - * Get a reference to the manifest item that is loaded by this loader. In most cases this will be the value that was - * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or - * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will - * be an Object created by the LoadQueue. - * @return {Object} The manifest item that this loader is responsible for loading. - */ - p.getItem = function() { - return this._item; - }; - - /** - * Initialize the loader. This is called by the constructor. - * @method init - * @private - */ - p.init = function () {}; - - /** - * Begin loading the queued items. This method can be called when a {{#crossLink "LoadQueue"}}{{/crossLink}} is set - * up but not started immediately. - * @example - * var queue = new createjs.LoadQueue(); - * queue.addEventListener("complete", handleComplete); - * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet - * queue.load(); - * @method load - */ - p.load = function() {}; - - /** - * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from - * starting to download. Note that currently any active loads will remain open, and events may be processed. - * - * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead. - * @method close - */ - p.close = function() {}; - - -//Callback proxies - /** - * Dispatch a loadstart event. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}} event - * for details on the event payload. - * @method _sendLoadStart - * @protected - */ - p._sendLoadStart = function() { - if (this._isCanceled()) { return; } - this.dispatchEvent("loadstart"); - }; - - /** - * Dispatch a progress event. Please see the {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}} event for - * details on the event payload. - * @method _sendProgress - * @param {Number | Object} value The progress of the loaded item, or an object containing loaded - * and total properties. - * @protected - */ - p._sendProgress = function(value) { - if (this._isCanceled()) { return; } - var event = null; - if (typeof(value) == "number") { - this.progress = value; - event = new createjs.Event("progress"); - event.loaded = this.progress; - event.total = 1; - } else { - event = value; - this.progress = value.loaded / value.total; - if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } - } - event.progress = this.progress; - this.hasEventListener("progress") && this.dispatchEvent(event); - }; - - /** - * Dispatch a complete event. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event - * for details on the event payload. - * @method _sendComplete - * @protected - */ - p._sendComplete = function() { - if (this._isCanceled()) { return; } - this.dispatchEvent("complete"); - }; - - /** - * Dispatch an error event. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} event for - * details on the event payload. - * @method _sendError - * @param {Object} event The event object containing specific error properties. - * @protected - */ - p._sendError = function(event) { - if (this._isCanceled() || !this.hasEventListener("error")) { return; } - if (event == null) { - event = new createjs.Event("error"); - } - this.dispatchEvent(event); - }; - - /** - * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events - * do not cause issues after the queue has been cleaned up. - * @method _isCanceled - * @return {Boolean} If the loader has been canceled. - * @protected - */ - p._isCanceled = function() { - if (window.createjs == null || this.canceled) { - return true; - } - return false; - }; - - /** - * @method _parseURI - * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know: - *
      - *
    • If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or - * `//networkPath`)
    • - *
    • If the path is relative. Relative paths start with `../` or `/path` (or similar)
    • - *
    • The file extension. This is determined by the filename with an extension. Query strings are dropped, and - * the file path is expected to follow the format `name.ext`.
    • - *
    - * - * Note: This has changed from earlier versions, which used a single, complicated Regular Expression, which - * was difficult to maintain, and over-aggressive in determining all file properties. It has been simplified to - * only pull out what it needs. - * @param path - * @returns {Object} An Object with an `absolute` and `relative` Boolean, as well as an optional 'extension` String - * property, which is the lowercase extension. - * @private - */ - p._parseURI = function(path) { - var info = { absolute: false, relative:false }; - if (path == null) { return info; }; - - // Drop the query string - var queryIndex = path.indexOf("?"); - if (queryIndex > -1) { - path = path.substr(0,queryIndex); - } - - // Absolute - var match; - if (s.ABSOLUTE_PATT.test(path)) { - info.absolute = true; - - // Relative - } else if (s.RELATIVE_PATT.test(path)) { - info.relative = true; - } - - // Extension - if (match = path.match(s.EXTENSION_PATT)) { - info.extension = match[1].toLowerCase(); - } - return info; - }; - - /** - * Formats an object into a query string for either a POST or GET request. - * @method _formatQueryString - * @param {Object} data The data to convert to a query string. - * @param {Array} [query] Existing name/value pairs to append on to this query. - * @private - */ - p._formatQueryString = function(data, query) { - if (data == null) { - throw new Error('You must specify data.'); - } - var params = []; - for (var n in data) { - params.push(n+'='+escape(data[n])); - } - if (query) { - params = params.concat(query); - } - return params.join('&'); - }; - - /** - * A utility method that builds a file path using a source and a data object, and formats it into a new path. All - * of the loaders in PreloadJS use this method to compile paths when loading. - * @method buildPath - * @param {String} src The source path to add values to. - * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the - * path will be preserved. - * @returns {string} A formatted string that contains the path and the supplied parameters. - * @since 0.3.1 - */ - p.buildPath = function(src, 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 {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. - * @private - */ - p._isCrossDomain = function(item) { - var target = document.createElement("a"); - target.href = item.src; - - var host = document.createElement("a"); - host.href = location.href; - - var crossdomain = (target.hostname != "") && - (target.port != host.port || - target.protocol != host.protocol || - target.hostname != host.hostname); - return crossdomain; - } - - /** - * @method _isLocal - * @param {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. - * @private - */ - p._isLocal = function(item) { - var target = document.createElement("a"); - target.href = item.src; - return target.hostname == "" && target.protocol == "file:"; - }; - - /** - * @method toString - * @return {String} a string representation of the instance. - */ - p.toString = function() { - return "[PreloadJS AbstractLoader]"; - }; - - createjs.AbstractLoader = AbstractLoader; - -}()); diff --git a/src/preloadjs/LoadQueue.js b/src/preloadjs/LoadQueue.js index 52114af3..ccc5dfb8 100644 --- a/src/preloadjs/LoadQueue.js +++ b/src/preloadjs/LoadQueue.js @@ -1,31 +1,32 @@ /* -* LoadQueue -* Visit http://createjs.com/ for documentation, updates and examples. -* -* -* Copyright (c) 2012 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ + * LoadQueue + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + /** * PreloadJS provides a consistent way to preload content for use in HTML applications. Preloading can be done using * HTML tags, as well as XHR. @@ -65,13 +66,13 @@ *

    Browser Support

    * PreloadJS is partially supported in all browsers, and fully supported in all modern browsers. Known exceptions: *
    • XHR loading of any content will not work in many older browsers (See a matrix here: http://caniuse.com/xhr2). - * In many cases, you can fall back on tag loading (images, audio, CSS, scripts, SVG, and JSONP). Text and + * In many cases, you can fall back on tag loading (images, audio, CSS, scripts, and SVG). Text and * WebAudio will only work with XHR.
    • *
    • Some formats have poor support for complete events in IE 6, 7, and 8 (SVG, tag loading of scripts, XML/JSON)
    • *
    • Opera has poor support for SVG loading with XHR
    • *
    • CSS loading in Android and Safari will not work with tags (currently, a workaround is in progress)
    • *
    • Local loading is not permitted with XHR, which is required by some file formats. When testing local content - * use either a local server, or enable tag loading, which is supported for most formats. See {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} + * use either a local server, or enable tag loading, which is supported for most formats. See {{#crossLink "LoadQueue/setPreferXHR"}}{{/crossLink}} * for more information.
    • *
    * @@ -87,29 +88,30 @@ */ // namespace: -this.createjs = this.createjs||{}; +this.createjs = this.createjs || {}; /* -TODO: WINDOWS ISSUES - * No error for HTML audio in IE 678 - * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR - * No script complete handler in IE 67 TAGS (XHR is fine) - * No XML/JSON in IE6 TAGS - * Need to hide loading SVG in Opera TAGS - * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking) - * SVG no load or failure in Opera XHR - * Reported issues with IE7/8 + TODO: WINDOWS ISSUES + * No error for HTML audio in IE 678 + * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR + * No script complete handler in IE 67 TAGS (XHR is fine) + * No XML/JSON in IE6 TAGS + * Need to hide loading SVG in Opera TAGS + * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking) + * SVG no load or failure in Opera XHR + * Reported issues with IE7/8 */ -(function() { +(function () { "use strict"; +// constructor /** * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either * a single file, or queue of files. * * Creating a Queue
    - * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the useXHR + * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the preferXHR * argument to false. * * var queue = new createjs.LoadQueue(true); @@ -141,6 +143,10 @@ TODO: WINDOWS ISSUES * queue.loadFile({id:"image", src:"filePath/file.jpg"}); * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]); * + * // Use an external manifest + * queue.loadManifest("path/to/manifest.json"); + * queue.loadManifest({src:"manifest.json", type:"manifest"}); + * * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a @@ -154,41 +160,49 @@ TODO: WINDOWS ISSUES * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a * type property with any manifest item. * - * queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.LoadQueue.SOUND}); + * queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.Types.SOUND}); * * // Note that PreloadJS will not read a file extension from the query string - * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:createjs.LoadQueue.IMAGE}); + * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:createjs.Types.IMAGE}); * - * Supported types are defined on the LoadQueue class, and include: + * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include: *
      - *
    • {{#crossLink "LoadQueue/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
    • - *
    • {{#crossLink "LoadQueue/CSS:property"}}{{/crossLink}}: CSS files
    • - *
    • {{#crossLink "LoadQueue/IMAGE:property"}}{{/crossLink}}: Common image formats
    • - *
    • {{#crossLink "LoadQueue/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
    • - *
    • {{#crossLink "LoadQueue/JSON:property"}}{{/crossLink}}: JSON data
    • - *
    • {{#crossLink "LoadQueue/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
    • - *
    • {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see - * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}
    • - *
    • {{#crossLink "LoadQueue/SOUND:property"}}{{/crossLink}}: Audio file formats
    • - *
    • {{#crossLink "LoadQueue/SVG:property"}}{{/crossLink}}: SVG files
    • - *
    • {{#crossLink "LoadQueue/TEXT:property"}}{{/crossLink}}: Text files - XHR only
    • - *
    • {{#crossLink "LoadQueue/XML:property"}}{{/crossLink}}: XML data
    • + *
    • {{#crossLink "Types/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
    • + *
    • {{#crossLink "Types/CSS:property"}}{{/crossLink}}: CSS files
    • + *
    • {{#crossLink "Types/IMAGE:property"}}{{/crossLink}}: Common image formats
    • + *
    • {{#crossLink "Types/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
    • + *
    • {{#crossLink "Types/JSON:property"}}{{/crossLink}}: JSON data
    • + *
    • {{#crossLink "Types/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
    • + *
    • {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see + * {{#crossLink "AbstractLoader/loadManifest"}}{{/crossLink}}
    • + *
    • {{#crossLink "Types/SOUND:property"}}{{/crossLink}}: Audio file formats
    • + *
    • {{#crossLink "Types/SPRITESHEET:property"}}{{/crossLink}}: JSON SpriteSheet definitions. This + * will also load sub-images, and provide a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance.
    • + *
    • {{#crossLink "Types/SVG:property"}}{{/crossLink}}: SVG files
    • + *
    • {{#crossLink "Types/TEXT:property"}}{{/crossLink}}: Text files - XHR only
    • + *
    • {{#crossLink "Types/VIDEO:property"}}{{/crossLink}}: Video objects
    • + *
    • {{#crossLink "Types/XML:property"}}{{/crossLink}}: XML data
    • *
    * + * Note: Loader types used to be defined on LoadQueue, but have been moved to the Types class + * * Handling Results
    * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a - * resolved object that can be used immediately, including: + * formatted object that can be used immediately, including: *
      + *
    • Binary: The binary loaded result
    • + *
    • CSS: A <link /> tag
    • *
    • Image: An <img /> tag
    • - *
    • Audio: An <audio /> tag *
    • JavaScript: A <script /> tag
    • - *
    • CSS: A <link /> tag
    • - *
    • XML: An XML DOM node
    • + *
    • JSON/JSONP: A formatted JavaScript Object
    • + *
    • Manifest: A JavaScript object. + *
    • Sound: An <audio /> tag + *
    • SpriteSheet: A {{#crossLink "SpriteSheet"}}{{/crossLink}} instance, containing loaded images. *
    • SVG: An <object /> tag
    • - *
    • JSON: A formatted JavaScript Object
    • *
    • Text: Raw text
    • - *
    • Binary: The binary loaded result
    • + *
    • Video: A Video DOM node
    • + *
    • XML: An XML DOM node
    • *
    * * function handleFileLoad(event) { @@ -196,15 +210,15 @@ TODO: WINDOWS ISSUES * var type = item.type; * * // Add any images to the page body. - * if (type == createjs.LoadQueue.IMAGE) { + * if (type == createjs.Types.IMAGE) { * document.body.appendChild(event.result); * } * } * * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up - * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the "src" or - * file path can be used instead, including the `path` defined by a manifest, but not including a - * base path defined on the LoadQueue. It is recommended to always pass an id. + * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the + * "src" or file path can be used instead, including the `path` defined by a manifest, but not including + * a base path defined on the LoadQueue. It is recommended to always pass an id if you want to look up content. * * var image = queue.getResult("image"); * document.body.appendChild(image); @@ -238,7 +252,7 @@ TODO: WINDOWS ISSUES * * * @class LoadQueue - * @param {Boolean} [useXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP + * @param {Boolean} [preferXHR=true] Determines whether the preload instance will favor loading with XHR (XML HTTP * Requests), or HTML tags. When this is `false`, the queue will use tag loading when possible, and fall back on XHR * when necessary. * @param {String} [basePath=""] A path that will be prepended on to the source parameter of all items in the queue @@ -246,259 +260,366 @@ TODO: WINDOWS ISSUES * will not receive a base path. * @param {String|Boolean} [crossOrigin=""] An optional flag to support images loaded from a CORS-enabled server. To * use it, set this value to `true`, which will default the crossOrigin property on images to "Anonymous". Any - * string value will be passed through, but only "" and "Anonymous" are recommended. + * string value will be passed through, but only "" and "Anonymous" are recommended. Note: The crossOrigin + * parameter is deprecated. Use LoadItem.crossOrigin instead + * * @constructor * @extends AbstractLoader */ - var LoadQueue = function(useXHR, basePath, crossOrigin) { - this.init(useXHR, basePath, crossOrigin); - }; - - var p = LoadQueue.prototype = new createjs.AbstractLoader(); - var s = LoadQueue; - - /** - * Time in milliseconds to assume a load has failed. An {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} - * event is dispatched if the timeout is reached before any data is received. - * @property loadTimeout - * @type {Number} - * @default 8000 - * @static - * @since 0.4.1 - */ - s.loadTimeout = 8000; - - /** - * Time in milliseconds to assume a load has failed. - * @type {Number} - * @deprecated in favor of the {{#crossLink "LoadQueue/loadTimeout:property"}}{{/crossLink}} property. - */ - s.LOAD_TIMEOUT = 0; - -// Preload Types - /** - * 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 - */ - 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 - */ - s.CSS = "css"; - - /** - * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag. - * @property IMAGE - * @type {String} - * @default image - * @static - */ - s.IMAGE = "image"; + function LoadQueue (preferXHR, basePath, crossOrigin) { + this.AbstractLoader_constructor(); + + /** + * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}. + * @property _plugins + * @type {Array} + * @private + * @since 0.6.1 + */ + this._plugins = []; + + /** + * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the + * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} + * method for more information. + * @property _typeCallbacks + * @type {Object} + * @private + */ + this._typeCallbacks = {}; - /** - * 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 - */ - s.JAVASCRIPT = "javascript"; + /** + * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the + * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} + * method for more information. + * @property _extensionCallbacks + * @type {null} + * @private + */ + this._extensionCallbacks = {}; - /** - * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a - * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP, - * no matter what the {{#crossLink "LoadQueue/useXHR:property"}}{{/crossLink}} property is set to, and the JSON - * must contain a matching wrapper function. - * @property JSON - * @type {String} - * @default json - * @static - */ - s.JSON = "json"; + /** + * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and + * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed. + * @property next + * @type {LoadQueue} + * @default null + */ + this.next = null; + + /** + * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head + * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas + * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order + * specified. + * + * Any items can be set to load in order by setting the {{#crossLink "maintainOrder:property"}}{{/crossLink}} + * property on the load item, or by ensuring that only one connection can be open at a time using + * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Note that when the `maintainScriptOrder` property + * is set to `true`, scripts items are automatically set to `maintainOrder=true`, and changing the + * `maintainScriptOrder` to `false` during a load will not change items already in a queue. + * + *

    Example

    + * + * var queue = new createjs.LoadQueue(); + * queue.setMaxConnections(3); // Set a higher number to load multiple items at once + * queue.maintainScriptOrder = true; // Ensure scripts are loaded in order + * queue.loadManifest([ + * "script1.js", + * "script2.js", + * "image.png", // Load any time + * {src: "image2.png", maintainOrder: true} // Will wait for script2.js + * "image3.png", + * "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR) + * ]); + * + * @property maintainScriptOrder + * @type {Boolean} + * @default true + */ + this.maintainScriptOrder = true; + + /** + * Determines if the LoadQueue will stop processing the current queue when an error is encountered. + * @property stopOnError + * @type {Boolean} + * @default false + */ + this.stopOnError = false; + + /** + * The number of maximum open connections that a loadQueue tries to maintain. Please see + * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information. + * @property _maxConnections + * @type {Number} + * @default 1 + * @private + */ + this._maxConnections = 1; + + /** + * An internal list of all the default Loaders that are included with PreloadJS. Before an item is loaded, the + * available loader list is iterated, in the order they are included, and as soon as a loader indicates it can + * handle the content, it will be selected. The default loader, ({{#crossLink "TextLoader"}}{{/crossLink}} is + * last in the list, so it will be used if no other match is found. Typically, loaders will match based on the + * {{#crossLink "LoadItem/type"}}{{/crossLink}}, which is automatically determined using the file extension of + * the {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. + * + * Loaders can be removed from PreloadJS by simply not including them. + * + * Custom loaders installed using {{#crossLink "registerLoader"}}{{/crossLink}} will be prepended to this list + * so that they are checked first. + * @property _availableLoaders + * @type {Array} + * @private + * @since 0.6.0 + */ + this._availableLoaders = [ + createjs.FontLoader, + createjs.ImageLoader, + createjs.JavaScriptLoader, + createjs.CSSLoader, + createjs.JSONLoader, + createjs.JSONPLoader, + createjs.SoundLoader, + createjs.ManifestLoader, + createjs.SpriteSheetLoader, + createjs.XMLLoader, + createjs.SVGLoader, + createjs.BinaryLoader, + createjs.VideoLoader, + createjs.TextLoader + ]; + + /** + * The number of built in loaders, so they can't be removed by {{#crossLink "unregisterLoader"}}{{/crossLink}. + * @property _defaultLoaderLength + * @type {Number} + * @private + * @since 0.6.0 + */ + this._defaultLoaderLength = this._availableLoaders.length; + + this.init(preferXHR, basePath, crossOrigin); + } + + var p = createjs.extend(LoadQueue, createjs.AbstractLoader); + var s = LoadQueue; - /** - * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a - * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON. - * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/useXHR:property"}}{{/crossLink}} - * property is set to. - * @property JSONP - * @type {String} - * @default jsonp - * @static + // 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) {} + + /** + * An internal initialization method, which is used for initial set up, but also to reset the LoadQueue. + * @method init + * @param preferXHR + * @param basePath + * @param crossOrigin + * @private */ - s.JSONP = "jsonp"; + p.init = function (preferXHR, basePath, crossOrigin) { + + // public properties + + /** + * Try and use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR + * loading depending on the requirements for a media type. For example, HTML audio can not be loaded with XHR, + * and plain text can not be loaded with tags, so it will default the the correct type instead of using the + * user-defined type. + * @type {Boolean} + * @default true + * @since 0.6.0 + */ + this.preferXHR = true; //TODO: Get/Set + this._preferXHR = true; + this.setPreferXHR(preferXHR); + + // protected properties + /** + * Whether the queue is currently paused or not. + * @property _paused + * @type {boolean} + * @private + */ + this._paused = false; - /** - * 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/useXHR:property"}}{{/crossLink}} property is set to. - * @property MANIFEST - * @type {String} - * @default manifest - * @static - * @since 0.4.1 - */ - s.MANIFEST = "manifest"; + /** + * A path that will be prepended on to the item's {{#crossLink "LoadItem/src:property"}}{{/crossLink}}. The + * `_basePath` property will only be used if an item's source is relative, and does not include a protocol such + * as `http://`, or a relative path such as `../`. + * @property _basePath + * @type {String} + * @private + * @since 0.3.1 + */ + this._basePath = basePath; - /** - * 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 - */ - s.SOUND = "sound"; + /** + * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded + * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by + * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues, + * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are "" + * and "Anonymous". + * @property _crossOrigin + * @type {String} + * @default "" + * @private + * @since 0.4.1 + */ + this._crossOrigin = crossOrigin; + + /** + * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first + * file is requested. + * @property _loadStartWasDispatched + * @type {Boolean} + * @default false + * @private + */ + this._loadStartWasDispatched = false; - /** - * The preload type for SVG files. - * @property SVG - * @type {String} - * @default svg - * @static - */ - s.SVG = "svg"; + /** + * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when + * using a script tag to do preloading. + * @property _currentlyLoadingScript + * @type {Boolean} + * @private + */ + this._currentlyLoadingScript = null; + + /** + * An array containing the currently downloading files. + * @property _currentLoads + * @type {Array} + * @private + */ + this._currentLoads = []; - /** - * The preload type for text files, which is also the default file type if the type can not be determined. Text is - * loaded as raw text. - * @property TEXT - * @type {String} - * @default text - * @static - */ - s.TEXT = "text"; + /** + * An array containing the queued items that have not yet started downloading. + * @property _loadQueue + * @type {Array} + * @private + */ + this._loadQueue = []; - /** - * The preload type for xml files. XML is loaded into an XML document. - * @property XML - * @type {String} - * @default xml - * @static - */ - s.XML = "xml"; + /** + * An array containing downloads that have not completed, so that the LoadQueue can be properly reset. + * @property _loadQueueBackup + * @type {Array} + * @private + */ + this._loadQueueBackup = []; - /** - * Defines a POST request, use for a method value when loading data. - * - * @type {string} - */ - s.POST = 'POST'; + /** + * An object hash of items that have finished downloading, indexed by the {{#crossLink "LoadItem"}}{{/crossLink}} + * id. + * @property _loadItemsById + * @type {Object} + * @private + */ + this._loadItemsById = {}; - /** - * Defines a GET request, use for a method value when loading data. - * - * @type {string} - */ - s.GET = 'GET'; + /** + * An object hash of items that have finished downloading, indexed by {{#crossLink "LoadItem"}}{{/crossLink}} + * source. + * @property _loadItemsBySrc + * @type {Object} + * @private + */ + this._loadItemsBySrc = {}; + /** + * An object hash of loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}. + * @property _loadedResults + * @type {Object} + * @private + */ + this._loadedResults = {}; -// Prototype - /** - * A path that will be prepended on to the item's `src`. The `_basePath` property will only be used if an item's - * source is relative, and does not include a protocol such as `http://`, or a relative path such as `../`. - * @property _basePath - * @type {String} - * @private - * @since 0.3.1 - */ - p._basePath = null; + /** + * An object hash of un-parsed loaded items, indexed by the ID of the {{#crossLink "LoadItem"}}{{/crossLink}}. + * @property _loadedRawResults + * @type {Object} + * @private + */ + this._loadedRawResults = {}; - /** - * An optional flag to set on images that are loaded using PreloadJS, which enables CORS support. Images loaded - * cross-domain by servers that support CORS require the crossOrigin flag to be loaded and interacted with by - * a canvas. When loading locally, or with a server with no CORS support, this flag can cause other security issues, - * so it is recommended to only set it if you are sure the server supports it. Currently, supported values are "" - * and "Anonymous". - * @property _crossOrigin - * @type {String} - * @defaultValue "" - * @private - * @since 0.4.1 - */ - p._crossOrigin = ""; + /** + * The number of items that have been requested. This helps manage an overall progress without knowing how large + * the files are before they are downloaded. This does not include items inside of loaders such as the + * {{#crossLink "ManifestLoader"}}{{/crossLink}}. + * @property _numItems + * @type {Number} + * @default 0 + * @private + */ + this._numItems = 0; + + /** + * The number of items that have completed loaded. This helps manage an overall progress without knowing how large + * the files are before they are downloaded. + * @property _numItemsLoaded + * @type {Number} + * @default 0 + * @private + */ + this._numItemsLoaded = 0; + + /** + * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right + * order. + * @property _scriptOrder + * @type {Array} + * @private + */ + this._scriptOrder = []; - /** - * Use XMLHttpRequest (XHR) when possible. Note that LoadQueue will default to tag loading or XHR loading depending - * on the requirements for a media type. For example, HTML audio can not be loaded with XHR, and WebAudio can not be - * loaded with tags, so it will default the the correct type instead of using the user-defined type. - * - * Note: This property is read-only. To change it, please use the {{#crossLink "LoadQueue/setUseXHR"}}{{/crossLink}} - * method, or specify the `useXHR` argument in the LoadQueue constructor. - * - * @property useXHR - * @type {Boolean} - * @readOnly - * @default true - */ - p.useXHR = true; + /** + * A list of scripts that have been loaded. Items are added to this list as null when they are + * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true + * once they are complete and have been dispatched. + * @property _loadedScripts + * @type {Array} + * @private + */ + this._loadedScripts = []; - /** - * Determines if the LoadQueue will stop processing the current queue when an error is encountered. - * @property stopOnError - * @type {Boolean} - * @default false - */ - p.stopOnError = false; + /** + * The last progress amount. This is used to suppress duplicate progress events. + * @property _lastProgress + * @type {Number} + * @private + * @since 0.6.0 + */ + this._lastProgress = NaN; - /** - * Ensure loaded scripts "complete" in the order they are specified. Loaded scripts are added to the document head - * once they are loaded. Scripts loaded via tags will load one-at-a-time when this property is `true`, whereas - * scripts loaded using XHR can load in any order, but will "finish" and be added to the document in the order - * specified. - * - * Any items can be set to load in order by setting the `maintainOrder` property on the load item, or by ensuring - * that only one connection can be open at a time using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. - * Note that when the `maintainScriptOrder` property is set to `true`, scripts items are automatically set to - * `maintainOrder=true`, and changing the `maintainScriptOrder` to `false` during a load will not change items - * already in a queue. - * - *

    Example

    - * - * var queue = new createjs.LoadQueue(); - * queue.setMaxConnections(3); // Set a higher number to load multiple items at once - * queue.maintainScriptOrder = true; // Ensure scripts are loaded in order - * queue.loadManifest([ - * "script1.js", - * "script2.js", - * "image.png", // Load any time - * {src: "image2.png", maintainOrder: true} // Will wait for script2.js - * "image3.png", - * "script3.js" // Will wait for image2.png before loading (or completing when loading with XHR) - * ]); - * - * @property maintainScriptOrder - * @type {Boolean} - * @default true - */ - p.maintainScriptOrder = true; + }; - /** - * The next preload queue to process when this one is complete. If an error is thrown in the current queue, and - * {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} is `true`, the next queue will not be processed. - * @property next - * @type {LoadQueue} - * @default null - */ - p.next = null; +// static properties -// Events +// events /** * This event is fired when an individual file has loaded, and been processed. * @event fileload @@ -514,233 +635,73 @@ TODO: WINDOWS ISSUES */ /** - * This event is fired when an an individual file progress changes. + * This {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when an an individual file's progress changes. * @event fileprogress - * @param {Object} The object that dispatched the event. - * @param {String} type The event type. - * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the - * object will contain that value as a `src` property. - * @param {Number} loaded The number of bytes that have been loaded. Note that this may just be a percentage of 1. - * @param {Number} total The total number of bytes. If it is unknown, the value is 1. - * @param {Number} progress The amount that has been loaded between 0 and 1. * @since 0.3.0 */ /** * This event is fired when an individual file starts to load. * @event filestart - * @param {Object} The object that dispatched the event. + * @param {Object} target The object that dispatched the event. * @param {String} type The event type. * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the * object will contain that value as a property. */ - //TODO: Deprecated - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} - * event. - * @property onFileLoad - * @type {Function} - * @deprecated Use addEventListener and the "fileload" event. - */ - /** - * REMOVED. Use {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}} and the {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}} - * event. - * @property onFileProgress - * @type {Function} - * @deprecated Use addEventListener and the "fileprogress" event. - */ - - -// Protected - /** - * An object hash of callbacks that are fired for each file type before the file is loaded, giving plugins the - * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} - * method for more information. - * @property _typeCallbacks - * @type {Object} - * @private - */ - p._typeCallbacks = null; - - /** - * An object hash of callbacks that are fired for each file extension before the file is loaded, giving plugins the - * ability to override properties of the load. Please see the {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}} - * method for more information. - * @property _extensionCallbacks - * @type {null} - * @private - */ - p._extensionCallbacks = null; - - /** - * Determines if the loadStart event was dispatched already. This event is only fired one time, when the first - * file is requested. - * @property _loadStartWasDispatched - * @type {Boolean} - * @default false - * @private - */ - p._loadStartWasDispatched = false; - - /** - * The number of maximum open connections that a loadQueue tries to maintain. Please see - * {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} for more information. - * @property _maxConnections - * @type {Number} - * @default 1 - * @private - */ - p._maxConnections = 1; - - /** - * Determines if there is currently a script loading. This helps ensure that only a single script loads at once when - * using a script tag to do preloading. - * @property _currentlyLoadingScript - * @type {Boolean} - * @private - */ - p._currentlyLoadingScript = null; - - /** - * An array containing the currently downloading files. - * @property _currentLoads - * @type {Array} - * @private - */ - p._currentLoads = null; - - /** - * An array containing the queued items that have not yet started downloading. - * @property _loadQueue - * @type {Array} - * @private - */ - p._loadQueue = null; - - /** - * An array containing downloads that have not completed, so that the LoadQueue can be properly reset. - * @property _loadQueueBackup - * @type {Array} - * @private - */ - p._loadQueueBackup = null; - - /** - * An object hash of items that have finished downloading, indexed by item IDs. - * @property _loadItemsById - * @type {Object} - * @private - */ - p._loadItemsById = null; - /** - * An object hash of items that have finished downloading, indexed by item source. - * @property _loadItemsBySrc - * @type {Object} + * Although it extends {{#crossLink "AbstractLoader"}}{{/crossLink}}, the `initialize` event is never fired from + * a LoadQueue instance. + * @event initialize * @private */ - p._loadItemsBySrc = null; +// public methods /** - * An object hash of loaded items, indexed by the ID of the load item. - * @property _loadedResults - * @type {Object} - * @private - */ - p._loadedResults = null; - - /** - * An object hash of un-parsed loaded items, indexed by the ID of the load item. - * @property _loadedRawResults - * @type {Object} - * @private + * Register a custom loaders class. New loaders are given precedence over loaders added earlier and default loaders. + * It is recommended that loaders extend {{#crossLink "AbstractLoader"}}{{/crossLink}}. Loaders can only be added + * once, and will be prepended to the list of available loaders. + * @method registerLoader + * @param {Function|AbstractLoader} loader The AbstractLoader class to add. + * @since 0.6.0 */ - p._loadedRawResults = null; - - /** - * The number of items that have been requested. This helps manage an overall progress without knowing how large - * the files are before they are downloaded. - * @property _numItems - * @type {Number} - * @default 0 - * @private - */ - p._numItems = 0; - - /** - * The number of items that have completed loaded. This helps manage an overall progress without knowing how large - * the files are before they are downloaded. - * @property _numItemsLoaded - * @type {Number} - * @default 0 - * @private - */ - p._numItemsLoaded = 0; + p.registerLoader = function (loader) { + if (!loader || !loader.canLoadItem) { + throw new Error("loader is of an incorrect type."); + } else if (this._availableLoaders.indexOf(loader) != -1) { + throw new Error("loader already exists."); //LM: Maybe just silently fail here + } - /** - * A list of scripts in the order they were requested. This helps ensure that scripts are "completed" in the right - * order. - * @property _scriptOrder - * @type {Array} - * @private - */ - p._scriptOrder = null; + this._availableLoaders.unshift(loader); + }; /** - * A list of scripts that have been loaded. Items are added to this list as null when they are - * requested, contain the loaded item if it has completed, but not been dispatched to the user, and true - * once they are complete and have been dispatched. - * @property _loadedScripts - * @type {Array} - * @private + * Remove a custom loader added using {{#crossLink "registerLoader"}}{{/crossLink}}. Only custom loaders can be + * unregistered, the default loaders will always be available. + * @method unregisterLoader + * @param {Function|AbstractLoader} loader The AbstractLoader class to remove */ - p._loadedScripts = null; - - // Overrides abstract method in AbstractLoader - p.init = function(useXHR, basePath, crossOrigin) { - this._numItems = this._numItemsLoaded = 0; - this._paused = false; - this._loadStartWasDispatched = false; - - this._currentLoads = []; - this._loadQueue = []; - this._loadQueueBackup = []; - this._scriptOrder = []; - this._loadedScripts = []; - this._loadItemsById = {}; - this._loadItemsBySrc = {}; - this._loadedResults = {}; - this._loadedRawResults = {}; - - // Callbacks for plugins - this._typeCallbacks = {}; - this._extensionCallbacks = {}; - - this._basePath = basePath; - this.setUseXHR(useXHR); - this._crossOrigin = (crossOrigin === true) - ? "Anonymous" : (crossOrigin === false || crossOrigin == null) - ? "" : crossOrigin; + p.unregisterLoader = function (loader) { + var idx = this._availableLoaders.indexOf(loader); + if (idx != -1 && idx < this._defaultLoaderLength - 1) { + this._availableLoaders.splice(idx, 1); + } }; /** - * Change the usXHR value. Note that if this is set to true, it may fail depending on the browser's capabilities. - * Additionally, some files require XHR in order to load, such as JSON (without JSONP), Text, and XML, so XHR will - * be used regardless of what is passed to this method. - * @method setUseXHR - * @param {Boolean} value The new useXHR value to set. - * @return {Boolean} The new useXHR value. If XHR is not supported by the browser, this will return false, even if - * the provided value argument was true. - * @since 0.3.0 + * Change the {{#crossLink "preferXHR:property"}}{{/crossLink}} value. Note that if this is set to `true`, it may + * fail, or be ignored depending on the browser's capabilities and the load type. + * @method setPreferXHR + * @param {Boolean} value + * @returns {Boolean} The value of {{#crossLink "preferXHR"}}{{/crossLink}} that was successfully set. + * @since 0.6.0 */ - p.setUseXHR = function(value) { + p.setPreferXHR = function (value) { // Determine if we can use XHR. XHR defaults to TRUE, but the browser may not support it. //TODO: Should we be checking for the other XHR types? Might have to do a try/catch on the different types similar to createXHR. - this.useXHR = (value != false && window.XMLHttpRequest != null); - return this.useXHR; + this.preferXHR = (value != false && window.XMLHttpRequest != null); + return this.preferXHR; }; /** @@ -749,7 +710,7 @@ TODO: WINDOWS ISSUES * @method removeAll * @since 0.3.0 */ - p.removeAll = function() { + p.removeAll = function () { this.remove(); }; @@ -773,10 +734,10 @@ TODO: WINDOWS ISSUES * items, or multiple items as arguments. * @since 0.3.0 */ - p.remove = function(idsOrUrls) { + p.remove = function (idsOrUrls) { var args = null; - if (idsOrUrls && !(idsOrUrls instanceof Array)) { + if (idsOrUrls && !Array.isArray(idsOrUrls)) { args = [idsOrUrls]; } else if (idsOrUrls) { args = idsOrUrls; @@ -792,41 +753,39 @@ TODO: WINDOWS ISSUES for (var n in this._loadItemsById) { this._disposeItem(this._loadItemsById[n]); } - this.init(this.useXHR, this._basePath, this._crossOrigin); + this.init(this.preferXHR, this._basePath); - // Remove specific items + // Remove specific items } else { while (args.length) { var item = args.pop(); var r = this.getResult(item); //Remove from the main load Queue - for (i = this._loadQueue.length-1;i>=0;i--) { + for (i = this._loadQueue.length - 1; i >= 0; i--) { loadItem = this._loadQueue[i].getItem(); if (loadItem.id == item || loadItem.src == item) { - this._loadQueue.splice(i,1)[0].cancel(); + this._loadQueue.splice(i, 1)[0].cancel(); break; } } //Remove from the backup queue - for (i = this._loadQueueBackup.length-1;i>=0;i--) { + for (i = this._loadQueueBackup.length - 1; i >= 0; i--) { loadItem = this._loadQueueBackup[i].getItem(); if (loadItem.id == item || loadItem.src == item) { - this._loadQueueBackup.splice(i,1)[0].cancel(); + this._loadQueueBackup.splice(i, 1)[0].cancel(); break; } } if (r) { - delete this._loadItemsById[r.id]; - delete this._loadItemsBySrc[r.src]; - this._disposeItem(r); + this._disposeItem(this.getItem(item)); } else { - for (var i=this._currentLoads.length-1;i>=0;i--) { + for (var i = this._currentLoads.length - 1; i >= 0; i--) { var loadItem = this._currentLoads[i].getItem(); if (loadItem.id == item || loadItem.src == item) { - this._currentLoads.splice(i,1)[0].cancel(); + this._currentLoads.splice(i, 1)[0].cancel(); itemsWereRemoved = true; break; } @@ -849,7 +808,7 @@ TODO: WINDOWS ISSUES * @method reset * @since 0.3.0 */ - p.reset = function() { + p.reset = function () { this.close(); for (var n in this._loadItemsById) { this._disposeItem(this._loadItemsById[n]); @@ -857,57 +816,13 @@ TODO: WINDOWS ISSUES //Reset the queue to its start state var a = []; - for (var i=0, l=this._loadQueueBackup.length; inot a binary type, as we can not play - * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get - * a binary result to work with. Binary files are loaded using XHR2. - * @method isBinary - * @param {String} type The item type. - * @return {Boolean} If the specified type is binary. - * @private - */ - s.isBinary = function(type) { - switch (type) { - case createjs.LoadQueue.IMAGE: - case createjs.LoadQueue.BINARY: - return true; - default: - return false; - } - }; - - - /** - * 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. - * @private - */ - s.isText = function(type) { - switch (type) { - case createjs.LoadQueue.TEXT: - case createjs.LoadQueue.JSON: - case createjs.LoadQueue.MANIFEST: - case createjs.LoadQueue.XML: - case createjs.LoadQueue.HTML: - case createjs.LoadQueue.CSS: - case createjs.LoadQueue.SVG: - case createjs.LoadQueue.JAVASCRIPT: - return true; - default: - return false; - } - }; - /** * Register a plugin. Plugins can map to load types (sound, image, etc), or specific extensions (png, mp3, etc). * Currently, only one plugin can exist per type/extension. @@ -926,19 +841,26 @@ TODO: WINDOWS ISSUES * @method installPlugin * @param {Function} plugin The plugin class to install. */ - p.installPlugin = function(plugin) { - if (plugin == null || plugin.getPreloadHandlers == null) { return; } - var map = plugin.getPreloadHandlers(); - map.scope = plugin; - - if (map.types != null) { - for (var i=0, l=map.types.length; i - *
  • A string path to a resource. Note that this kind of load item will be converted to an object (see below) + * @param {LoadItem|Object|String} file The file object or path to load. A file can be either + *
      + *
    • A {{#crossLink "LoadItem"}}{{/crossLink}} instance
    • + *
    • An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
    • + *
    • OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}} * in the background.
    • - *
    • OR an object that contains:
        - *
      • src: The source of the file that is being loaded. This property is required. The source can - * either be a string (recommended), or an HTML tag.
      • - *
      • type: The type of file that will be loaded (image, sound, json, etc). PreloadJS does auto-detection - * of types using the extension. Supported types are defined on LoadQueue, such as LoadQueue.IMAGE. - * It is recommended that a type is specified when a non-standard file URI (such as a php script) us used.
      • - *
      • id: A string identifier which can be used to reference the loaded object.
      • - *
      • maintainOrder: Set to `true` to ensure this asset loads in the order defined in the manifest. This - * will happen when the max connections has been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}), - * and will only affect other assets also defined as `maintainOrder`. Everything else 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`.
      • - *
      • callback: Optional, used for JSONP requests, to define what method to call when the JSONP is loaded.
      • - *
      • data: An arbitrary data object, which is included with the loaded object
      • - *
      • method: used to define if this request uses GET or POST when sending data to the server. The default - * value is "GET"
      • - *
      • values: Optional object of name/value pairs to send to the server.
      • - *
      • headers: Optional 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 if needed.
      • - *
      - *
    + * * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is * `true`, the queue will resume automatically. * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the - * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}}, + * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}}, * its files will NOT use the basePath parameter. The basePath parameter is deprecated. * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue * constructor, or a `path` property in a manifest definition. */ - p.loadFile = function(file, loadNow, basePath) { + p.loadFile = function (file, loadNow, basePath) { if (file == null) { - var event = new createjs.Event("error"); - event.text = "PRELOAD_NO_FILE"; + var event = new createjs.ErrorEvent("PRELOAD_NO_FILE"); this._sendError(event); return; } @@ -1049,30 +951,12 @@ TODO: WINDOWS ISSUES * * Each "file" in a manifest can be either: *
      - *
    • A string path to a resource (string). Note that this kind of load item will be converted to an object - * (see below) in the background.
    • - *
    • OR an object that contains:
        - *
      • src: The source of the file that is being loaded. This property is required. The source can - * either be a string (recommended), or an HTML tag.
      • - *
      • type: The type of file that will be loaded (image, sound, json, etc). PreloadJS does auto-detection - * of types using the extension. Supported types are defined on LoadQueue, such as {{#crossLink "LoadQueue/IMAGE:property"}}{{/crossLink}}. - * It is recommended that a type is specified when a non-standard file URI (such as a php script) us used.
      • - *
      • id: A string identifier which can be used to reference the loaded object.
      • - *
      • maintainOrder: Set to `true` to ensure this asset loads in the order defined in the manifest. This - * will happen when the max connections has been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}), - * and will only affect other assets also defined as `maintainOrder`. Everything else 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`.
      • - *
      • callback: Optional, used for JSONP requests, to define what method to call when the JSONP is loaded.
      • - *
      • data: An arbitrary data object, which is included with the loaded object
      • - *
      • method: used to define if this request uses GET or POST when sending data to the server. The default - * value is "GET"
      • - *
      • values: Optional object of name/value pairs to send to the server.
      • - *
      • headers: Optional 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 if needed.
      • - *
      + *
    • A {{#crossLink "LoadItem"}}{{/crossLink}} instance
    • + *
    • An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
    • + *
    • OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}} + * in the background.
    • *
    + * * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} and this value is * `true`, the queue will resume automatically. @@ -1082,26 +966,27 @@ TODO: WINDOWS ISSUES * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue * constructor, or a `path` property in a manifest definition. */ - p.loadManifest = function(manifest, loadNow, basePath) { + p.loadManifest = function (manifest, loadNow, basePath) { var fileList = null; var path = null; // Array-based list of items - if (manifest instanceof Array) { + if (Array.isArray(manifest)) { if (manifest.length == 0) { - var event = new createjs.Event("error"); - event.text = "PRELOAD_MANIFEST_EMPTY"; + var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_EMPTY"); this._sendError(event); return; } fileList = manifest; - // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded. + // String-based. Only file manifests can be specified this way. Any other types will cause an error when loaded. } else if (typeof(manifest) === "string") { - fileList = [{ - src: manifest, - type: s.MANIFEST - }]; + fileList = [ + { + src: manifest, + type: s.MANIFEST + } + ]; } else if (typeof(manifest) == "object") { @@ -1110,27 +995,25 @@ TODO: WINDOWS ISSUES if (manifest.type == null) { manifest.type = s.MANIFEST; } else if (manifest.type != s.MANIFEST) { - var event = new createjs.Event("error"); - event.text = "PRELOAD_MANIFEST_ERROR"; + var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_TYPE"); this._sendError(event); } fileList = [manifest]; - // An object that defines a manifest + // An object that defines a manifest } else if (manifest.manifest !== undefined) { fileList = manifest.manifest; path = manifest.path; } - // Unsupported. This will throw an error. + // Unsupported. This will throw an error. } else { - var event = new createjs.Event("error"); - event.text = "PRELOAD_MANIFEST_NULL"; + var event = new createjs.ErrorEvent("PRELOAD_MANIFEST_NULL"); this._sendError(event); return; } - for (var i=0, l=fileList.length; i + *
      *
    • An image tag (<image />) for images
    • *
    • A script tag for JavaScript (<script />). Note that scripts are automatically added to the HTML * DOM.
    • @@ -1184,12 +1070,14 @@ TODO: WINDOWS ISSUES * loaded audio. Specifically, audio loaded by Flash and WebAudio will return a loader object using this method * which can not be used to play audio back. *
    - * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item` + * This object is also returned via the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event as the 'item` * parameter. Note that if a raw result is requested, but not found, the result will be returned instead. */ - p.getResult = function(value, rawResult) { + p.getResult = function (value, rawResult) { var item = this._loadItemsById[value] || this._loadItemsBySrc[value]; - if (item == null) { return null; } + if (item == null) { + return null; + } var id = item.id; if (rawResult && this._loadedRawResults[id]) { return this._loadedRawResults[id]; @@ -1197,34 +1085,68 @@ TODO: WINDOWS ISSUES return this._loadedResults[id]; }; + /** + * Generate an list of items loaded by this queue. + * @method getItems + * @param {Boolean} loaded Determines if only items that have been loaded should be returned. If false, in-progress + * and failed load items will also be included. + * @returns {Array} A list of objects that have been loaded. Each item includes the {{#crossLink "LoadItem"}}{{/crossLink}}, + * result, and rawResult. + * @since 0.6.0 + */ + p.getItems = function (loaded) { + var arr = []; + for (var n in this._loadItemsById) { + var item = this._loadItemsById[n]; + var result = this.getResult(n); + if (loaded === true && result == null) { + continue; + } + arr.push({ + item: item, + result: result, + rawResult: this.getResult(n, true) + }); + } + return arr; + }; + /** * Pause or resume the current load. Active loads will not be cancelled, but the next items in the queue will not * be processed when active loads complete. LoadQueues are not paused by default. * - * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, - * a paused queue will be resumed, unless the `loadNow` argument is `false`. + * Note that if new items are added to the queue using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or + * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}, a paused queue will be resumed, unless the `loadNow` + * argument is `false`. * @method setPaused * @param {Boolean} value Whether the queue should be paused or not. */ - p.setPaused = function(value) { + p.setPaused = function (value) { this._paused = value; if (!this._paused) { this._loadNext(); } }; - // Overrides abstract method in AbstractLoader - p.close = function() { + /** + * Close the active queue. Closing a queue completely empties the queue, and prevents any remaining items from + * starting to download. Note that currently any active loads will remain open, and events may be processed. + * + * To stop and restart a queue, use the {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}} method instead. + * @method close + */ + p.close = function () { while (this._currentLoads.length) { this._currentLoads.pop().cancel(); } this._scriptOrder.length = 0; this._loadedScripts.length = 0; this.loadStartWasDispatched = false; + this._itemCount = 0; + this._lastProgress = NaN; }; - -//Protected Methods +// protected methods /** * Add an item to the queue. Items are formatted into a usable object containing all the properties necessary to * load the content. The load queue is populated with the loader instance that handles preloading, and not the load @@ -1240,11 +1162,16 @@ TODO: WINDOWS ISSUES * version. * @private */ - p._addItem = function(value, path, basePath) { + p._addItem = function (value, path, basePath) { var item = this._createLoadItem(value, path, basePath); // basePath and manifest path are added to the src. - if (item == null) { return; } // Sometimes plugins or types should be skipped. + if (item == null) { + return; + } // Sometimes plugins or types should be skipped. var loader = this._createLoader(item); if (loader != null) { + if ("plugins" in loader) { + loader.plugins = this._plugins; + } item._loader = loader; this._loadQueue.push(loader); this._loadQueueBackup.push(loader); @@ -1254,8 +1181,8 @@ TODO: WINDOWS ISSUES // Only worry about script order when using XHR to load scripts. Tags are only loading one at a time. if ((this.maintainScriptOrder - && item.type == createjs.LoadQueue.JAVASCRIPT - //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way + && item.type == createjs.Types.JAVASCRIPT + //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way ) || item.maintainOrder === true) { this._scriptOrder.push(item); @@ -1265,7 +1192,7 @@ TODO: WINDOWS ISSUES }; /** - * Create a refined load item, which contains all the required properties (src, type, extension, tag). The type of + * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of * item is determined by browser support, requirements based on the file type, and developer settings. For example, * XHR is only used for file types that support it in new browsers. * @@ -1273,7 +1200,7 @@ TODO: WINDOWS ISSUES * alter the load item. * @method _createLoadItem * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded. - * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will + * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}} * when it is added. * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to @@ -1281,46 +1208,22 @@ TODO: WINDOWS ISSUES * @return {Object} The loader instance that will be used. * @private */ - p._createLoadItem = function(value, path, basePath) { - var item = null; - - // Create/modify a load item - switch(typeof(value)) { - case "string": - item = { - src: value - }; break; - case "object": - if (window.HTMLAudioElement && value instanceof window.HTMLAudioElement) { - item = { - tag: value, - src: item.tag.src, - type: createjs.LoadQueue.SOUND - }; - } else { - item = value; - } - break; - default: - return null; + p._createLoadItem = function (value, path, basePath) { + var item = createjs.LoadItem.create(value); + if (item == null) { + return null; } - // Determine Extension, etc. - var match = this._parseURI(item.src); - if (match.extension) { item.ext = match.extension; } - if (item.type == null) { - item.type = this._getTypeByExtension(item.ext); - } - - // Inject path & basePath var bp = ""; // Store the generated basePath var useBasePath = basePath || this._basePath; - var autoId = item.src; - if (!match.absolute && !match.relative) { + + if (item.src instanceof Object) { + if (!item.type) { + return null; + } // the the src is an object, type is required to pass off to plugin if (path) { bp = path; - var pathMatch = this._parseURI(path); - autoId = path + autoId; + var pathMatch = createjs.URLUtils.parseURI(path); // Also append basePath if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) { bp = useBasePath + bp; @@ -1328,61 +1231,63 @@ TODO: WINDOWS ISSUES } else if (useBasePath != null) { bp = useBasePath; } - } - item.src = bp + item.src; - item.path = bp; - - if (item.type == createjs.LoadQueue.JSON || item.type == createjs.LoadQueue.MANIFEST) { - item._loadAsJSONP = (item.callback != null); - } - - if (item.type == createjs.LoadQueue.JSONP && item.callback == null) { - throw new Error('callback is required for loading JSONP requests.'); - } + } else { + // Determine Extension, etc. + var match = createjs.URLUtils.parseURI(item.src); + if (match.extension) { + item.ext = match.extension; + } + if (item.type == null) { + item.type = createjs.RequestUtils.getTypeByExtension(item.ext); + } - // Create a tag for the item. This ensures there is something to either load with or populate when finished. - if (item.tag === undefined || item.tag === null) { - item.tag = this._createTag(item); + // Inject path & basePath + var autoId = item.src; + if (!match.absolute && !match.relative) { + if (path) { + bp = path; + var pathMatch = createjs.URLUtils.parseURI(path); + autoId = path + autoId; + // Also append basePath + if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) { + bp = useBasePath + bp; + } + } else if (useBasePath != null) { + bp = useBasePath; + } + } + item.src = bp + item.src; } + item.path = bp; // If there's no id, set one now. if (item.id === undefined || item.id === null || item.id === "") { - item.id = autoId; + item.id = autoId; } // Give plugins a chance to modify the loadItem: var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext]; if (customHandler) { // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately) - var result = customHandler.callback.call(customHandler.scope, item.src, item.type, item.id, item.data, - bp, this); - // NOTE: BasePath argument is deprecated. We pass it to plugins.allow SoundJS to modify the file. to sanymore. The full path is sent to the plugin + var result = customHandler.callback.call(customHandler.scope, item, this); // The plugin will handle the load, or has canceled it. Ignore it. if (result === false) { return null; - // Load as normal: + // Load as normal: } else if (result === true) { // Do Nothing - // Result is a loader class: - } else { - if (result.src != null) { item.src = result.src; } - if (result.id != null) { item.id = result.id; } // TODO: Evaluate this. An overridden ID could be problematic - if (result.tag != null) { // Assumes that the returned tag either has a load method or a src setter. - item.tag = result.tag; - } - if (result.completeHandler != null) { item.completeHandler = result.completeHandler; } - - // Allow type overriding: - if (result.type) { item.type = result.type; } + // Result is a loader class: + } else if (result != null) { + item._loader = result; + } - // Update the extension in case the type changed: - match = this._parseURI(item.src); - if (match.extension != null) { - item.ext = match.extension; - } + // Update the extension in case the type changed: + match = createjs.URLUtils.parseURI(item.src); + if (match.extension != null) { + item.ext = match.extension; } } @@ -1390,6 +1295,10 @@ TODO: WINDOWS ISSUES this._loadItemsById[item.id] = item; this._loadItemsBySrc[item.src] = item; + if (item.crossOrigin == null) { + item.crossOrigin = this._crossOrigin; + } + return item; }; @@ -1400,37 +1309,25 @@ TODO: WINDOWS ISSUES * @return {AbstractLoader} A loader that can be used to load content. * @private */ - p._createLoader = function(item) { + p._createLoader = function (item) { + if (item._loader != null) { // A plugin already specified a loader + return item._loader; + } + // Initially, try and use the provided/supported XHR mode: - var useXHR = this.useXHR; + var preferXHR = this.preferXHR; - // Determine the XHR usage overrides: - switch (item.type) { - case createjs.LoadQueue.JSON: - case createjs.LoadQueue.MANIFEST: - useXHR = !item._loadAsJSONP; - break; - case createjs.LoadQueue.XML: - case createjs.LoadQueue.TEXT: - useXHR = true; // Always use XHR2 with text/XML - break; - case createjs.LoadQueue.SOUND: - case createjs.LoadQueue.JSONP: - useXHR = false; // Never load audio using XHR. WebAudio will provide its own loader. - break; - case null: - return null; - // Note: IMAGE, CSS, SCRIPT, SVG can all use TAGS or XHR. + for (var i = 0; i < this._availableLoaders.length; i++) { + var loader = this._availableLoaders[i]; + if (loader && loader.canLoadItem(item)) { + return new loader(item, preferXHR); + } } - if (useXHR) { - return new createjs.XHRLoader(item, this._crossOrigin); - } else { - return new createjs.TagLoader(item); - } + // TODO: Log error (requires createjs.log) + return null; }; - /** * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event * is processed. The queue will "fill up" any empty slots, up to the max connection specified using @@ -1439,8 +1336,10 @@ TODO: WINDOWS ISSUES * @method _loadNext * @private */ - p._loadNext = function() { - if (this._paused) { return; } + p._loadNext = function () { + if (this._paused) { + return; + } // Only dispatch loadstart event when the first file is loaded. if (!this._loadStartWasDispatched) { @@ -1462,108 +1361,181 @@ TODO: WINDOWS ISSUES } // Must iterate forwards to load in the right order. - for (var i=0; i= this._maxConnections) { break; } + for (var i = 0; i < this._loadQueue.length; i++) { + if (this._currentLoads.length >= this._maxConnections) { + break; + } var loader = this._loadQueue[i]; // Determine if we should be only loading one tag-script at a time: // Note: maintainOrder items don't do anything here because we can hold onto their loaded value - if (!this._canStartLoad(loader)) { continue; } + if (!this._canStartLoad(loader)) { + continue; + } this._loadQueue.splice(i, 1); - i--; - this._loadItem(loader); + i--; + this._loadItem(loader); } }; /** - * Begin loading an item. Events are not added to the loaders until the load starts. + * Begin loading an item. Event listeners are not added to the loaders until the load starts. * @method _loadItem * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader. * @private */ - p._loadItem = function(loader) { + p._loadItem = function (loader) { + loader.on("fileload", this._handleFileLoad, this); loader.on("progress", this._handleProgress, this); loader.on("complete", this._handleFileComplete, this); - loader.on("error", this._handleFileError, this); + loader.on("error", this._handleError, this); + loader.on("fileerror", this._handleFileError, this); this._currentLoads.push(loader); this._sendFileStart(loader.getItem()); loader.load(); }; + /** + * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}} + * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}} + * events. + * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader. + * @private + * @since 0.6.0 + */ + p._handleFileLoad = function (event) { + event.target = null; + this.dispatchEvent(event); + }; + + /** + * The callback that is fired when a loader encounters an error from an internal file load operation. This enables + * loaders like M + * @param event + * @private + */ + p._handleFileError = function (event) { + var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, event.item); + this._sendError(newEvent); + }; + /** * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} * is set to `true`. - * @method _handleFileError - * @param {Object} event The error event, containing relevant error information. + * @method _handleError + * @param {ErrorEvent} event The error event, containing relevant error information. * @private */ - p._handleFileError = function(event) { + p._handleError = function (event) { var loader = event.target; this._numItemsLoaded++; this._finishOrderedItem(loader, true); this._updateProgress(); - var newEvent = new createjs.Event("error"); - newEvent.text = "FILE_LOAD_ERROR"; - newEvent.item = loader.getItem(); + var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem()); // TODO: Propagate actual error message. this._sendError(newEvent); if (!this.stopOnError) { this._removeLoadItem(loader); + this._cleanLoadItem(loader); this._loadNext(); + } else { + this.setPaused(true); } }; /** * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML, - * CSS, JavaScript, etc) is available as the "rawResult" event, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. + * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. * @method _handleFileComplete - * @param {Object} event The event object from the loader. + * @param {Event} event The event object from the loader. * @private */ - p._handleFileComplete = function(event) { + p._handleFileComplete = function (event) { var loader = event.target; var item = loader.getItem(); - this._loadedResults[item.id] = loader.getResult(); - if (loader instanceof createjs.XHRLoader) { - this._loadedRawResults[item.id] = loader.getResult(true); + var result = loader.getResult(); + this._loadedResults[item.id] = result; + var rawResult = loader.getResult(true); + if (rawResult != null && rawResult !== result) { + this._loadedRawResults[item.id] = rawResult; } - // Clean up the load item + this._saveLoadedItems(loader); + + // Remove the load item this._removeLoadItem(loader); if (!this._finishOrderedItem(loader)) { // The item was NOT managed, so process it now this._processFinishedLoad(item, loader); } + + // Clean up the load item + this._cleanLoadItem(loader); + }; + + /** + * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}). + * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the + * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}} + * methods. + * @method _saveLoadedItems + * @param {AbstractLoader} loader + * @protected + * @since 0.6.0 + */ + p._saveLoadedItems = function (loader) { + // TODO: Not sure how to handle this. Would be nice to expose the items. + // Loaders may load sub-items. This adds them to this queue + var list = loader.getLoadedItems(); + if (list === null) { + return; + } + + for (var i = 0; i < list.length; i++) { + var item = list[i].item; + + // Store item lookups + this._loadItemsBySrc[item.src] = item; + this._loadItemsById[item.id] = item; + + // Store loaded content + this._loadedResults[item.id] = list[i].result; + this._loadedRawResults[item.id] = list[i].rawResult; + } }; /** - * Flag an item as finished. If the item's order is being managed, then set it up to finish + * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if + * so, trigger prior items to trigger as well. * @method _finishOrderedItem * @param {AbstractLoader} loader + * @param {Boolean} loadFailed * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate * behaviour if it is. * @private */ - p._finishOrderedItem = function(loader, loadFailed) { + p._finishOrderedItem = function (loader, loadFailed) { var item = loader.getItem(); - if ((this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT) + if ((this.maintainScriptOrder && item.type == createjs.Types.JAVASCRIPT) || item.maintainOrder) { //TODO: Evaluate removal of the _currentlyLoadingScript - if (loader instanceof createjs.TagLoader && item.type == createjs.LoadQueue.JAVASCRIPT) { + if (loader instanceof createjs.JavaScriptLoader) { this._currentlyLoadingScript = false; } var index = createjs.indexOf(this._scriptOrder, item); - if (index == -1) { return false; } // This loader no longer exists + if (index == -1) { + return false; + } // This loader no longer exists this._loadedScripts[index] = (loadFailed === true) ? true : item; this._checkScriptLoadOrder(); @@ -1576,8 +1548,8 @@ TODO: WINDOWS ISSUES /** * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the * order they were added, but with a "null" value. When they are completed, the value is set to the load item, - * and then when they are processed and dispatched, the value is set to true. This method simply - * iterates the array, and ensures that any loaded items that are not preceded by a null value are + * and then when they are processed and dispatched, the value is set to `true`. This method simply + * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are * dispatched. * @method _checkScriptLoadOrder * @private @@ -1585,15 +1557,19 @@ TODO: WINDOWS ISSUES p._checkScriptLoadOrder = function () { var l = this._loadedScripts.length; - for (var i=0;ibefore * the script can even be started, since it exist in the DOM while loading. * @method _canStartLoad - * @param {XHRLoader|TagLoader} loader The loader for the item + * @param {AbstractLoader} loader The loader for the item * @return {Boolean} Whether the item can start a load or not. * @private */ - p._canStartLoad = function(loader) { - if (!this.maintainScriptOrder || loader instanceof createjs.XHRLoader) { return true; } + p._canStartLoad = function (loader) { + if (!this.maintainScriptOrder || loader.preferXHR) { + return true; + } var item = loader.getItem(); - if (item.type != createjs.LoadQueue.JAVASCRIPT) { return true; } - if (this._currentlyLoadingScript) { return false; } + if (item.type != createjs.Types.JAVASCRIPT) { + return true; + } + if (this._currentlyLoadingScript) { + return false; + } var index = this._scriptOrder.indexOf(item); var i = 0; while (i < index) { var checkItem = this._loadedScripts[i]; - if (checkItem == null) { return false; } + if (checkItem == null) { + return false; + } i++; } this._currentlyLoadingScript = true; @@ -1656,26 +1641,37 @@ TODO: WINDOWS ISSUES * @param {AbstractLoader} loader A loader instance to remove. * @private */ - p._removeLoadItem = function(loader) { - var item = loader.getItem(); - delete item._loader; - delete item._loadAsJSONP; - + p._removeLoadItem = function (loader) { var l = this._currentLoads.length; - for (var i=0;i + * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be: + *
      *
    • 5/10 of the items in the queue (50%)
    • *
    • plus 20% of item 6's slot (2%)
    • - *
    • equals 52%
    + *
  • equals 52%
  • + * * @method _updateProgress * @private */ p._updateProgress = function () { var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress - var remaining = this._numItems-this._numItemsLoaded; + var remaining = this._numItems - this._numItemsLoaded; if (remaining > 0) { var chunk = 0; - for (var i=0, l=this._currentLoads.length; iLoadQueue.IMAGE
    or null if it can not be - * determined by the extension. - * @private - */ - p._getTypeByExtension = function(extension) { - if (extension == null) { - return createjs.LoadQueue.TEXT; - } - switch (extension.toLowerCase()) { - case "jpeg": - case "jpg": - case "gif": - case "png": - case "webp": - case "bmp": - return createjs.LoadQueue.IMAGE; - case "ogg": - case "mp3": - case "wav": - return createjs.LoadQueue.SOUND; - case "json": - return createjs.LoadQueue.JSON; - case "xml": - return createjs.LoadQueue.XML; - case "css": - return createjs.LoadQueue.CSS; - case "js": - return createjs.LoadQueue.JAVASCRIPT; - case 'svg': - return createjs.LoadQueue.SVG; - default: - return createjs.LoadQueue.TEXT; - } - }; - /** - * Dispatch a fileprogress event (and onFileProgress callback). Please see the LoadQueue.fileprogress + * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}} * event for details on the event payload. * @method _sendFileProgress - * @param {Object} item The item that is being loaded. + * @param {LoadItem|Object} item The item that is being loaded. * @param {Number} progress The amount the item has been loaded (between 0 and 1). * @protected */ - p._sendFileProgress = function(item, progress) { - if (this._isCanceled()) { - this._cleanUp(); + p._sendFileProgress = function (item, progress) { + if (this._isCanceled() || this._paused) { + return; + } + if (!this.hasEventListener("fileprogress")) { return; } - if (!this.hasEventListener("fileprogress")) { return; } + //LM: Rework ProgressEvent to support this? var event = new createjs.Event("fileprogress"); event.progress = progress; event.loaded = progress; @@ -1835,15 +1750,17 @@ TODO: WINDOWS ISSUES }; /** - * Dispatch a fileload event. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for + * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for * details on the event payload. * @method _sendFileComplete - * @param {Object} item The item that is being loaded. - * @param {TagLoader | XHRLoader} loader + * @param {LoadItemObject} item The item that is being loaded. + * @param {AbstractLoader} loader * @protected */ - p._sendFileComplete = function(item, loader) { - if (this._isCanceled()) { return; } + p._sendFileComplete = function (item, loader) { + if (this._isCanceled() || this._paused) { + return; + } var event = new createjs.Event("fileload"); event.loader = loader; @@ -1851,59 +1768,30 @@ TODO: WINDOWS ISSUES event.result = this._loadedResults[item.id]; event.rawResult = this._loadedRawResults[item.id]; - // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this. - if (item.completeHandler) { - item.completeHandler(event); - } + // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this. + if (item.completeHandler) { + item.completeHandler(event); + } this.hasEventListener("fileload") && this.dispatchEvent(event); }; /** - * Dispatch a filestart event immediately before a file starts to load. Please see the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} - * event for details on the event payload. + * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see + * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload. * @method _sendFileStart - * @param {Object} item The item that is being loaded. + * @param {LoadItem|Object} item The item that is being loaded. * @protected */ - p._sendFileStart = function(item) { + p._sendFileStart = function (item) { var event = new createjs.Event("filestart"); event.item = item; this.hasEventListener("filestart") && this.dispatchEvent(event); }; - /** - * REMOVED. Use createjs.proxy instead - * @method proxy - * @param {Function} method The function to call - * @param {Object} scope The scope to call the method name on - * @static - * @private - * @deprecated In favour of the createjs.proxy method (see LoadQueue source). - */ - - p.toString = function() { + p.toString = function () { return "[PreloadJS LoadQueue]"; }; - createjs.LoadQueue = LoadQueue; - - -// Helper methods - - // An additional module to determine the current browser, version, operating system, and other environmental variables. - var BrowserDetect = function() {} - - BrowserDetect.init = function() { - var agent = navigator.userAgent; - BrowserDetect.isFirefox = (agent.indexOf("Firefox") > -1); - BrowserDetect.isOpera = (window.opera != null); - BrowserDetect.isChrome = (agent.indexOf("Chrome") > -1); - BrowserDetect.isIOS = agent.indexOf("iPod") > -1 || agent.indexOf("iPhone") > -1 || agent.indexOf("iPad") > -1; - }; - - BrowserDetect.init(); - - createjs.LoadQueue.BrowserDetect = BrowserDetect; - + createjs.LoadQueue = createjs.promote(LoadQueue, "AbstractLoader"); }()); diff --git a/src/preloadjs/TagLoader.js b/src/preloadjs/TagLoader.js deleted file mode 100644 index e4bb8a1a..00000000 --- a/src/preloadjs/TagLoader.js +++ /dev/null @@ -1,365 +0,0 @@ -/* -* TagLoader -* Visit http://createjs.com/ for documentation, updates and examples. -* -* -* Copyright (c) 2012 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * @module PreloadJS - */ - -// namespace: -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - /** - * A preloader that loads items using a tag-based approach. HTML audio and images can use this loader to load - * content cross-domain without security errors, whereas anything loaded with XHR has potential issues with cross- - * domain requests. - * - * Note for audio tags, TagLoader relies on the canPlayThrough event, which fires when the buffer - * is full enough to play the audio all the way through at the current download speed. This completely preloads most - * sound effects, however longer tracks like background audio will only load a portion before the event is fired. - * Most browsers (all excluding Chrome) will continue to preload once this is fired, so this is considered good - * enough for most cases. - * @class TagLoader - * @constructor - * @extends AbstractLoader - * @param {Object} item The item to load. Please see {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} for - * information on load items. - */ - var TagLoader = function (item) { - this.init(item); - }; - - var p = TagLoader.prototype = new createjs.AbstractLoader(); - -// Protected - - /** - * The timeout that is fired if nothing is loaded after a certain delay. See the LoadQueue.LOAD_TIMEOUT - * for the timeout duration. - * @property _loadTimeout - * @type {Number} - * @private - */ - p._loadTimeout = null; - - /** - * A reference to a bound function, which we need in order to properly remove the event handler when the load - * completes. - * @property _tagCompleteProxy - * @type {Function} - * @private - */ - p._tagCompleteProxy = null; - - /** - * Determines if the load item is an audio tag, since we take some specific approaches to properly load audio. - * @property _isAudio - * @type {Boolean} - * @default false - * @protected - */ - p._isAudio = false; - - /** - * The HTML tag or JavaScript object this loader uses to preload content. Note that a tag may be a custom object - * that matches the API of an HTML tag (load method, onload callback). For example, flash audio from SoundJS passes - * in a custom object to handle preloading for Flash audio and WebAudio. - * @property _tag - * @type {HTMLAudioElement | Object} - * @private - */ - p._tag = null; - - /** - * When loading a JSONP request this will be the parsed JSON result. - * - * @type {Object} - * @private - */ - p._jsonResult = null; - - // Overrides abstract method in AbstractLoader - p.init = function (item) { - this._item = item; - this._tag = item.tag; - this._isAudio = (window.HTMLAudioElement && item.tag instanceof window.HTMLAudioElement); - this._tagCompleteProxy = createjs.proxy(this._handleLoad, this); - }; - - /** - * Get the loaded content. This is usually an HTML tag or other tag-style object that has been fully loaded. If the - * loader is not complete, this will be null. - * @method getResult - * @return {HTMLImageElement | HTMLAudioElement | Object} The loaded and parsed content. - */ - p.getResult = function() { - if (this._item.type == createjs.LoadQueue.JSONP || this._item.type == createjs.LoadQueue.MANIFEST) { - return this._jsonResult; - } else { - return this._tag; - } - }; - - // Overrides abstract method in AbstractLoader - p.cancel = function() { - this.canceled = true; - this._clean(); - }; - - // Overrides abstract method in AbstractLoader - p.load = function() { - var item = this._item; - var tag = this._tag; - - clearTimeout(this._loadTimeout); // Clear out any existing timeout - var duration = createjs.LoadQueue.LOAD_TIMEOUT; - if (duration == 0) { duration = createjs.LoadQueue.loadTimeout; } - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), duration); - - if (this._isAudio) { - tag.src = null; // Unset the source so we can set the preload type to "auto" without kicking off a load. This is only necessary for audio tags passed in by the developer. - tag.preload = "auto"; - } - - // Handlers for all tags - tag.onerror = createjs.proxy(this._handleError, this); - // Note: We only get progress events in Chrome, but do not fully load tags in Chrome due to its behaviour, so we ignore progress. - - if (this._isAudio) { - tag.onstalled = createjs.proxy(this._handleStalled, this); - // This will tell us when audio is buffered enough to play through, but not when its loaded. - // The tag doesn't keep loading in Chrome once enough has buffered, and we have decided that behaviour is sufficient. - tag.addEventListener("canplaythrough", this._tagCompleteProxy, false); // canplaythrough callback doesn't work in Chrome, so we use an event. - } else { - tag.onload = createjs.proxy(this._handleLoad, this); - tag.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this); - } - - var src = this.buildPath(item.src, item.values); - - // Set the src after the events are all added. - switch(item.type) { - case createjs.LoadQueue.CSS: - tag.href = src; - break; - case createjs.LoadQueue.SVG: - tag.data = src; - break; - default: - tag.src = src; - } - - // If we're loading JSONP, we need to add our callback now. - if (item.type == createjs.LoadQueue.JSONP - || item.type == createjs.LoadQueue.JSON - || item.type == createjs.LoadQueue.MANIFEST) { - if (item.callback == null) { - throw new Error('callback is required for loading JSONP requests.'); - } - - if (window[item.callback] != null) { - throw new Error('JSONP callback "' + item.callback + '" already exists on window. You need to specify a different callback. Or re-name the current one.'); - } - - window[item.callback] = createjs.proxy(this._handleJSONPLoad, this); - } - - // If its SVG, it needs to be on the DOM to load (we remove it before sending complete). - // It is important that this happens AFTER setting the src/data. - if (item.type == createjs.LoadQueue.SVG || - item.type == createjs.LoadQueue.JSONP || - item.type == createjs.LoadQueue.JSON || - item.type == createjs.LoadQueue.MANIFEST || - item.type == createjs.LoadQueue.JAVASCRIPT || - item.type == createjs.LoadQueue.CSS) { - this._startTagVisibility = tag.style.visibility; - tag.style.visibility = "hidden"; - var node = document.body || document.getElementsByTagName("body")[0]; - if (node == null) { - if (item.type == createjs.LoadQueue.SVG) { - this._handleSVGError(); - return; - } else { - node = document.head || document.getElementsByTagName("head"); - } - } - node.appendChild(tag); - } - - // Note: Previous versions didn't seem to work when we called load() for OGG tags in Firefox. Seems fixed in 15.0.1 - if (tag.load != null) { - tag.load(); - } - }; - - p._handleSVGError = function() { - this._clean(); - var event = new createjs.Event("error"); - event.text = "SVG_NO_BODY"; - this._sendError(event); - }; - - p._handleJSONPLoad = function(data) { - this._jsonResult = data; - }; - - /** - * Handle an audio timeout. Newer browsers get a callback from the tags, but older ones may require a setTimeout - * to handle it. The setTimeout is always running until a response is handled by the browser. - * @method _handleTimeout - * @private - */ - p._handleTimeout = function() { - this._clean(); - var event = new createjs.Event("error"); - event.text = "PRELOAD_TIMEOUT"; - this._sendError(event); - }; - - /** - * Handle a stalled audio event. The main place we seem to get these is with HTMLAudio in Chrome when we try and - * playback audio that is already in a load, but not complete. - * @method _handleStalled - * @private - */ - p._handleStalled = function() { - //Ignore, let the timeout take care of it. Sometimes its not really stopped. - }; - - /** - * Handle an error event generated by the tag. - * @method _handleError - * @private - */ - p._handleError = function(event) { - this._clean(); - - var newEvent = new createjs.Event("error"); - //TODO: Propagate actual event error? - this._sendError(newEvent); - }; - - /** - * Handle the readyStateChange event from a tag. We sometimes need this in place of the onload event (mainly SCRIPT - * and LINK tags), but other cases may exist. - * @method _handleReadyStateChange - * @private - */ - p._handleReadyStateChange = function() { - clearTimeout(this._loadTimeout); - // This is strictly for tags in browsers that do not support onload. - var tag = this.getItem().tag; - - // Complete is for old IE support. - if (tag.readyState == "loaded" || tag.readyState == "complete") { - this._handleLoad(); - } - }; - - /** - * Handle a load (complete) event. This is called by tag callbacks, but also by readyStateChange and canPlayThrough - * events. Once loaded, the item is dispatched to the {{#crossLink "LoadQueue"}}{{/crossLink}}. - * @method _handleLoad - * @param {Object} [event] A load event from a tag. This is sometimes called from other handlers without an event. - * @private - */ - p._handleLoad = function(event) { - if (this._isCanceled()) { return; } - - var item = this.getItem(); - var tag = item.tag; - - if (this.loaded || this._isAudio && tag.readyState !== 4) { return; } //LM: Not sure if we still need the audio check. - this.loaded = true; - - // Remove from the DOM - switch (item.type) { - case createjs.LoadQueue.SVG: - case createjs.LoadQueue.JSON: - case createjs.LoadQueue.JSONP: // Note: Removing script tags is a fool's errand. - case createjs.LoadQueue.MANIFEST: - case createjs.LoadQueue.CSS: - // case createjs.LoadQueue.CSS: - //LM: We may need to remove CSS tags loaded using a LINK - tag.style.visibility = this._startTagVisibility; - tag.parentNode && tag.parentNode.contains(tag) && tag.parentNode.removeChild(tag); - break; - default: - } - - this._clean(); - this._sendComplete(); - }; - - /** - * Clean up the loader. - * This stops any timers and removes references to prevent errant callbacks and clean up memory. - * @method _clean - * @private - */ - p._clean = function() { - clearTimeout(this._loadTimeout); - - // Delete handlers. - var item = this.getItem(); - var tag = item.tag; - if (tag != null) { - tag.onload = null; - tag.removeEventListener && tag.removeEventListener("canplaythrough", this._tagCompleteProxy, false); - tag.onstalled = null; - tag.onprogress = null; - tag.onerror = null; - - //TODO: Test this - if (tag.parentNode != null - && item.type == createjs.LoadQueue.SVG - && item.type == createjs.LoadQueue.JSON - && item.type == createjs.LoadQueue.MANIFEST - && item.type == createjs.LoadQueue.CSS - && item.type == createjs.LoadQueue.JSONP) { - // Note: Removing script tags is a fool's errand. - tag.parentNode.removeChild(tag); - } - } - - var item = this.getItem(); - if (item.type == createjs.LoadQueue.JSONP - || item.type == createjs.LoadQueue.MANIFEST) { - window[item.callback] = null; - } - }; - - p.toString = function() { - return "[PreloadJS TagLoader]"; - }; - - createjs.TagLoader = TagLoader; - -}()); diff --git a/src/preloadjs/XHRLoader.js b/src/preloadjs/XHRLoader.js deleted file mode 100644 index 24aa97f0..00000000 --- a/src/preloadjs/XHRLoader.js +++ /dev/null @@ -1,1002 +0,0 @@ -/* - * XHRLoader - * Visit http://createjs.com/ for documentation, updates and examples. - * - * - * Copyright (c) 2012 gskinner.com, inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * @module PreloadJS - */ - -// namespace: -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - /** - * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used - * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary. - * XHR requests load the content as text or binary data, provide progress and consistent completion events, and - * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for - * cross-domain loading. - * @class XHRLoader - * @constructor - * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * for an overview of supported file properties. - * @param {String} [crossOrigin] An optional flag to support images loaded from a CORS-enabled server. Please see - * {{#crossLink "LoadQueue/_crossOrigin:property"}}{{/crossLink}} for more info. - * @extends AbstractLoader - */ - var XHRLoader = function (item, crossOrigin) { - this.init(item, crossOrigin); - }; - - var s = XHRLoader; - - /** - * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE. - * @property ACTIVEX_VERSIONS - * @type {Array} - * @since 0.4.2 - * @private - */ - s.ACTIVEX_VERSIONS = [ - "Msxml2.XMLHTTP.6.0", - "Msxml2.XMLHTTP.5.0", - "Msxml2.XMLHTTP.4.0", - "MSXML2.XMLHTTP.3.0", - "MSXML2.XMLHTTP", - "Microsoft.XMLHTTP" - ]; - - var p = XHRLoader.prototype = new createjs.AbstractLoader(); - - //Protected - /** - * A reference to the XHR request used to load the content. - * @property _request - * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP} - * @private - */ - p._request = null; - - /** - * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1, - * typically IE9). - * @property _loadTimeout - * @type {Number} - * @private - */ - p._loadTimeout = null; - - /** - * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect - * the version, so we use capabilities to make a best guess. - * @property _xhrLevel - * @type {Number} - * @default 1 - * @private - */ - p._xhrLevel = 1; - - /** - * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be - * null until the file is loaded. - * @property _response - * @type {mixed} - * @private - */ - p._response = null; - - /** - * The response of the loaded file before it is modified. In most cases, content is converted from raw text to - * an HTML tag or a formatted object which is set to the result property, but the developer may still - * want to access the raw content as it was loaded. - * @property _rawResponse - * @type {String|Object} - * @private - */ - p._rawResponse = null; - - /** - * See {{#crossLink "LoadQueue/_crossOrigin:property"}}{{/crossLink}} - * @property _crossOrigin - * @type {String} - * @defaultValue "" - * @private - */ - p._crossOrigin = ""; - - // Overrides abstract method in AbstractLoader - p.init = function (item, crossOrigin) { - this._item = item; - this._crossOrigin = crossOrigin; - if (!this._createXHR(item)) { - //TODO: Throw error? - } - }; - - /** - * Look up the loaded result. - * @method getResult - * @param {Boolean} [rawResult=false] Return a raw result instead of a formatted result. This applies to content - * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be - * returned instead. - * @return {Object} A result object containing the content that was loaded, such as: - *
      - *
    • An image tag (<image />) for images
    • - *
    • A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the - * HTML head.
    • - *
    • A style tag for CSS (<style />)
    • - *
    • Raw text for TEXT
    • - *
    • A formatted JavaScript object defined by JSON
    • - *
    • An XML document
    • - *
    • An binary arraybuffer loaded by XHR
    • - *
    - * Note that if a raw result is requested, but not found, the result will be returned instead. - */ - p.getResult = function (rawResult) { - if (rawResult && this._rawResponse) { - return this._rawResponse; - } - return this._response; - }; - - // Overrides abstract method in AbstractLoader - 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 - this._request.onloadstart = createjs.proxy(this._handleLoadStart, this); - this._request.onprogress = createjs.proxy(this._handleProgress, this); - this._request.onabort = createjs.proxy(this._handleAbort, this); - this._request.onerror = createjs.proxy(this._handleError, this); - this._request.ontimeout = createjs.proxy(this._handleTimeout, this); - // Set up a timeout if we don't have XHR2 - if (this._xhrLevel == 1) { - var duration = createjs.LoadQueue.LOAD_TIMEOUT; - if (duration == 0) { - duration = createjs.LoadQueue.loadTimeout; - } else { - try { console.warn("LoadQueue.LOAD_TIMEOUT has been deprecated in favor of LoadQueue.loadTimeout");} catch(e) {} - } - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), duration); - } - - // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. - this._request.onload = createjs.proxy(this._handleLoad, this); - - this._request.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this); - - // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome - try { - if (!this._item.values || this._item.method == createjs.LoadQueue.GET) { - this._request.send(); - } else if (this._item.method == createjs.LoadQueue.POST) { - this._request.send(this._formatQueryString(this._item.values)); - } - } catch (error) { - var event = new createjs.Event("error"); - event.error = error; - this._sendError(event); - } - }; - - /** - * 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; - } - }; - - /** - * 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.Event("progress"); - newEvent.loaded = event.loaded; - newEvent.total = event.total; - this._sendProgress(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._sendLoadStart(); - }; - - /** - * The XHR request has reported an abort event. - * @method handleAbort - * @param {Object} event The XHR abort event. - * @private - */ - p._handleAbort = function (event) { - this._clean(); - var newEvent = new createjs.Event("error"); - newEvent.text = "XHR_ABORTED"; - this._sendError(newEvent); - }; - - /** - * The XHR request has reported an error event. - * @method _handleError - * @param {Object} event The XHR error event. - * @private - */ - p._handleError = function (event) { - this._clean(); - var newEvent = new createjs.Event("error"); - //TODO: Propagate event error - this._sendError(newEvent); - }; - - /** - * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload - * event, so we must monitor the readyStateChange to determine if the file is loaded. - * @method _handleReadyStateChange - * @param {Object} event The XHR readyStateChange event. - * @private - */ - p._handleReadyStateChange = function (event) { - if (this._request.readyState == 4) { - this._handleLoad(); - } - }; - - /** - * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has - * request.readyState == 4. Only the first call to this method will be processed. - * @method _handleLoad - * @param {Object} event The XHR load event. - * @private - */ - p._handleLoad = function (event) { - if (this.loaded) { - return; - } - this.loaded = true; - - if (!this._checkError()) { - this._handleError(); - return; - } - - this._response = this._getResponse(); - this._clean(); - var isComplete = this._generateTag(); - if (isComplete) { - this._sendComplete(); - } - }; - - /** - * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout - * callback. - * @method _handleTimeout - * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout. - * @private - */ - p._handleTimeout = function (event) { - this._clean(); - var newEvent = new createjs.Event("error"); - newEvent.text = "PRELOAD_TIMEOUT"; - //TODO: Propagate actual event error - this._sendError(event); - }; - - -// Protected - /** - * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note - * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code. - * @method _checkError - * @return {Boolean} If the request status returns an error code. - * @private - */ - p._checkError = function () { - //LM: Probably need additional handlers here, maybe 501 - var status = parseInt(this._request.status); - - switch (status) { - case 404: // Not Found - case 0: // Not Loaded - return false; - } - return true; - }; - - /** - * Validate the response. Different browsers have different approaches, some of which throw errors when accessed - * in other browsers. If there is no response, the _response property will remain null. - * @method _getResponse - * @private - */ - p._getResponse = function () { - if (this._response != null) { - return this._response; - } - - if (this._request.response != null) { - return this._request.response; - } - - // Android 2.2 uses .responseText - try { - if (this._request.responseText != null) { - return this._request.responseText; - } - } catch (e) { - } - - // When loading XML, IE9 does not return .response, instead it returns responseXML.xml - //TODO: TEST - try { - if (this._request.responseXML != null) { - return this._request.responseXML; - } - } catch (e) { - } - return null; - }; - - /** - * Create an XHR request. Depending on a number of factors, we get totally different results. - *
    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 = this._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; irequired. The source can either be a + * string (recommended), or an HTML tag. + * This can also be an object, but in that case it has to include a type and be handled by a plugin. + * @property src + * @type {String} + * @default null + */ + this.src = null; + + /** + * The type file that is being loaded. The type of the file is usually inferred by the extension, but can also + * be set manually. This is helpful in cases where a file does not have an extension. + * @property type + * @type {String} + * @default null + */ + this.type = null; + + /** + * A string identifier which can be used to reference the loaded object. If none is provided, this will be + * automatically set to the {{#crossLink "src:property"}}{{/crossLink}}. + * @property id + * @type {String} + * @default null + */ + this.id = null; + + /** + * Determines if a manifest will maintain the order of this item, in relation to other items in the manifest + * that have also set the `maintainOrder` property to `true`. This only applies when the max connections has + * been set above 1 (using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}). Everything with this + * property set to `false` will finish as it is loaded. Ordered items are combined with script tags loading in + * order when {{#crossLink "LoadQueue/maintainScriptOrder:property"}}{{/crossLink}} is set to `true`. + * @property maintainOrder + * @type {Boolean} + * @default false + */ + this.maintainOrder = false; + + /** + * A callback used by JSONP requests that defines what global method to call when the JSONP content is loaded. + * @property callback + * @type {String} + * @default null + */ + this.callback = null; + + /** + * An arbitrary data object, which is included with the loaded object. + * @property data + * @type {Object} + * @default null + */ + this.data = null; + + /** + * The request method used for HTTP calls. Both {{#crossLink "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. + *
      + *
    • String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
    • + *
    • LoadItem instances are returned as-is
    • + *
    • Objects are returned with any needed properties added
    • + *
    + * @method create + * @param {LoadItem|String|Object} value The load item value + * @returns {LoadItem|Object} + * @static + */ + s.create = function (value) { + if (typeof value == "string") { + var item = new LoadItem(); + item.src = value; + return item; + } else if (value instanceof s) { + return value; + } else if (value instanceof Object && value.src) { + if (value.loadTimeout == null) { + value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT; + } + return value; + } else { + throw new Error("Type not recognized."); + } + }; + + /** + * Provides a chainable shortcut method for setting a number of properties on the instance. + * + *

    Example

    + * + * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true}); + * + * @method set + * @param {Object} props A generic object containing properties to copy to the LoadItem instance. + * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.) + */ + p.set = function(props) { + for (var n in props) { this[n] = props[n]; } + return this; + }; + + createjs.LoadItem = s; + +}()); diff --git a/src/preloadjs/data/Methods.js b/src/preloadjs/data/Methods.js new file mode 100644 index 00000000..92fe4da0 --- /dev/null +++ b/src/preloadjs/data/Methods.js @@ -0,0 +1,69 @@ +/* + * Methods + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function() { + + "use strict"; + + /** + * Defines the method types for XHR requests. Currently, PreloadJS only supports "POST" and "GET", however + * any HTML method can be used with PreloadJS utilities. + * + * @class Methods + * @static + */ + 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; +}()); diff --git a/src/preloadjs/data/Types.js b/src/preloadjs/data/Types.js new file mode 100644 index 00000000..93b739ce --- /dev/null +++ b/src/preloadjs/data/Types.js @@ -0,0 +1,229 @@ +/* + * Types + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function() { + + "use strict"; + + /** + * Defines the load types that PreloadJS supports by default. This is typically used when passing a type override to + * a {{#crossLink "LoadQueue"}}{{/crossLink}}. + * + *

    Example

    + * + * queue.loadFile({src:"https://somecdn/wfossn3", type:createjs.Types.IMAGE}); + * + * You can also use the string value: + * + * queue.loadFile({src:"https://somecdn/wfossn3", type:"image"}); + * + * @class Types + * @static + */ + + 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; +}()); diff --git a/src/preloadjs/events/ProgressEvent.js b/src/preloadjs/events/ProgressEvent.js new file mode 100644 index 00000000..69f61f81 --- /dev/null +++ b/src/preloadjs/events/ProgressEvent.js @@ -0,0 +1,90 @@ +/* + * ProgressEvent + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(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)); \ No newline at end of file diff --git a/src/preloadjs/loaders/AbstractLoader.js b/src/preloadjs/loaders/AbstractLoader.js new file mode 100644 index 00000000..a49adbc6 --- /dev/null +++ b/src/preloadjs/loaders/AbstractLoader.js @@ -0,0 +1,601 @@ +/* + * AbstractLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(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 () { + return this.canceled; + }; + + /** + * 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"); + +}()); diff --git a/src/preloadjs/loaders/AbstractMediaLoader.js b/src/preloadjs/loaders/AbstractMediaLoader.js new file mode 100644 index 00000000..ca8841bd --- /dev/null +++ b/src/preloadjs/loaders/AbstractMediaLoader.js @@ -0,0 +1,137 @@ +/* + * AbstractMediaLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // 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); + } + + var crossOrigin = this._item.crossOrigin; + if (crossOrigin === true) { crossOrigin = "Anonymous"; } + if (crossOrigin != null && !createjs.URLUtils.isLocal(this._item)) { + this._tag.crossOrigin = crossOrigin; + } + + 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"); + +}()); diff --git a/src/preloadjs/loaders/BinaryLoader.js b/src/preloadjs/loaders/BinaryLoader.js new file mode 100644 index 00000000..93c7ff6c --- /dev/null +++ b/src/preloadjs/loaders/BinaryLoader.js @@ -0,0 +1,82 @@ +/* + * BinaryLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for binary files. This is useful for loading web audio, or content that requires an ArrayBuffer. + * @class BinaryLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function BinaryLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, true, createjs.Types.BINARY); + this.on("initialize", this._updateXHR, this); + }; + + var p = createjs.extend(BinaryLoader, createjs.AbstractLoader); + var s = BinaryLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/BINARY:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.BINARY; + }; + + // private methods + /** + * Before the item loads, set the response type to "arraybuffer" + * @property _updateXHR + * @param {Event} event + * @private + */ + p._updateXHR = function (event) { + event.loader.setResponseType("arraybuffer"); + }; + + createjs.BinaryLoader = createjs.promote(BinaryLoader, "AbstractLoader"); + +}()); diff --git a/src/preloadjs/loaders/CSSLoader.js b/src/preloadjs/loaders/CSSLoader.js new file mode 100644 index 00000000..8972ee2a --- /dev/null +++ b/src/preloadjs/loaders/CSSLoader.js @@ -0,0 +1,113 @@ +/* + * CSSLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for CSS files. + * @class CSSLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @extends AbstractLoader + * @constructor + */ + function CSSLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.CSS); + + // public properties + this.resultFormatter = this._formatResult; + + // protected properties + this._tagSrcAttribute = "href"; + + if (preferXHR) { + this._tag = createjs.Elements.style(); + } else { + this._tag = createjs.Elements.link(); + } + + this._tag.rel = "stylesheet"; + this._tag.type = "text/css"; + }; + + var p = createjs.extend(CSSLoader, createjs.AbstractLoader); + var s = CSSLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/CSS:property"}}{{/crossLink}}. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.CSS; + }; + + // protected methods + /** + * The result formatter for CSS files. + * @method _formatResult + * @param {AbstractLoader} loader + * @returns {HTMLLinkElement|HTMLStyleElement} + * @private + */ + p._formatResult = function (loader) { + if (this._preferXHR) { + var tag = loader.getTag(); + + if (tag.styleSheet) { // IE + tag.styleSheet.cssText = loader.getResult(true); + } else { + var textNode = createjs.Elements.text(loader.getResult(true)); + tag.appendChild(textNode); + } + } else { + tag = this._tag; + } + + createjs.DomUtils.appendToHead(tag); + + return tag; + }; + + createjs.CSSLoader = createjs.promote(CSSLoader, "AbstractLoader"); + +}()); diff --git a/src/preloadjs/loaders/FontLoader.js b/src/preloadjs/loaders/FontLoader.js new file mode 100644 index 00000000..028d6137 --- /dev/null +++ b/src/preloadjs/loaders/FontLoader.js @@ -0,0 +1,579 @@ +/* + * FontLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + +// constructor: + /** + * A loader that handles font files, CSS definitions, and CSS paths. FontLoader doesn't actually preload fonts + * themselves, but rather generates CSS definitions, and then tests the size changes on an HTML5 Canvas element. + * + * Note that FontLoader does not support tag-based loading due to the requirement that CSS be read to determine the + * font definitions to test for. + * @class FontLoader + * @param {LoadItem|object|string} loadItem The item to be loaded. + * @extends AbstractLoader + * @constructor + **/ + function FontLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, loadItem.type); + + // private properties: + /** + * A lookup of font faces to load. + * @property _faces + * @protected + * @type Object + **/ + this._faces = {}; + + /** + * A list of font faces currently being "watched". Watched fonts will be tested on a regular interval, and be + * removed from this list when they are complete. + * @oroperty _watched + * @type {Array} + * @protected + */ + this._watched = []; + + /** + * A count of the total font faces to load. + * @property _count + * @type {number} + * @protected + * @default 0 + */ + this._count = 0; + + /** + * The interval for checking if fonts have been loaded. + * @property _watchInterval + * @type {Number} + * @protected + */ + this._watchInterval = null; + + /** + * The timeout for determining if a font can't be loaded. Uses the LoadItem {{#crossLink "LoadImte/timeout:property"}}{{/crossLink}} + * value. + * @property _loadTimeout + * @type {Number} + * @protected + */ + this._loadTimeout = null; + /** + * Determines if generated CSS should be injected into the document. + * @property _injectCSS + * @type {boolean} + * @protected + */ + this._injectCSS = (loadItem.injectCSS === undefined) ? true : loadItem.injectCSS; + + this.dispatchEvent("initialize"); + } + var p = createjs.extend(FontLoader, createjs.AbstractLoader); + + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/FONT: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 + */ + FontLoader.canLoadItem = function (item) { + return item.type == createjs.Types.FONT || item.type == createjs.Types.FONTCSS; + }; + +// static properties: + /** + * Sample text used by the FontLoader to determine if the font has been loaded. The sample text size is compared + * to the loaded font size, and a change indicates that the font has completed. + * @property sampleText + * @type {String} + * @default abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ + * @static + * @private + */ + FontLoader.sampleText = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + /** + * The canvas context used to test the font size. Note that this currently requires an HTML DOM. + * @property _ctx + * @type {CanvasRenderingContext2D} + * @static + * @private + */ + FontLoader._ctx = document.createElement("canvas").getContext("2d"); // TODO: Consider a method to do this like EaselJS Stage has. + + /** + * A list of reference fonts to test. Multiple faces are tested to address the rare case of a loaded font being the + * exact same dimensions as the test font. + * @property _referenceFonts + * @type {Array} + * @default ["serif", "monospace"] + * @private + */ + FontLoader._referenceFonts = ["serif","monospace"]; + + /** + * A regular expression that pulls out possible style values from the font name. + *
      + *
    • This includes font names that include thin, normal, book, regular, medium, black, and heavy (such as + * "Arial Black")
    • + *
    • Weight modifiers including extra, ultra, semi, demi, light, and bold (such as "WorkSans SemiBold")
    • + *
    + * + * Weight descriptions map to font weight values by default using the following (from + * http://www.w3.org/TR/css3-fonts/#font-weight-numeric-values): + *
      + *
    • 100 - Thin
    • + *
    • 200 - Extra Light, Ultra Light
    • + *
    • 300 - Light, Semi Light, Demi Light
    • + *
    • 400 - Normal, Book, Regular
    • + *
    • 500 - Medium
    • + *
    • 600 - Semi Bold, Demi Bold
    • + *
    • 700 - Bold
    • + *
    • 800 - Extra Bold, Ultra Bold
    • + *
    • 900 - Black, Heavy
    • + *
    + * @property WEIGHT_REGEX + * @type {RegExp} + * @static + */ + FontLoader.WEIGHT_REGEX = /[- ._]*(thin|normal|book|regular|medium|black|heavy|[1-9]00|(?:extra|ultra|semi|demi)?[- ._]*(?:light|bold))[- ._]*/ig; + + /** + * A regular expression that pulls out possible style values from the font name. These include "italic" + * and "oblique". + * @property STYLE_REGEX + * @type {RegExp} + * @static + */ + FontLoader.STYLE_REGEX = /[- ._]*(italic|oblique)[- ._]*/ig; + + /** + * A lookup of font types for generating a CSS definition. For example, TTF fonts requires a "truetype" type. + * @property FONT_FORMAT + * @type {Object} + * @static + */ + FontLoader.FONT_FORMAT = {woff2:"woff2", woff:"woff", ttf:"truetype", otf:"truetype"}; + + /** + * A lookup of font weights based on a name. These values are from http://www.w3.org/TR/css3-fonts/#font-weight-numeric-values. + * @property FONT_WEIGHT + * @type {Object} + * @static + */ + FontLoader.FONT_WEIGHT = {thin:100, extralight:200, ultralight:200, light:300, semilight:300, demilight:300, book:"normal", regular:"normal", semibold:600, demibold:600, extrabold:800, ultrabold:800, black:900, heavy:900}; + + /** + * The frequency in milliseconds to check for loaded fonts. + * @property WATCH_DURATION + * @type {number} + * @default 10 + * @static + */ + FontLoader.WATCH_DURATION = 10; +// public methods: + p.load = function() { + if (this.type == createjs.Types.FONTCSS) { + var loaded = this._watchCSS(); + + // If the CSS is not ready, it will create a request, which AbstractLoader can handle. + if (!loaded) { + this.AbstractLoader_load(); + return; + } + + } else if (this._item.src instanceof Array) { + this._watchFontArray(); + } else { + var def = this._defFromSrc(this._item.src); + this._watchFont(def); + this._injectStyleTag(this._cssFromDef(def)); + } + + this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); + + this.dispatchEvent("loadstart"); + }; + + /** + * The font load has timed out. This is called via a setTimeout. + * callback. + * @method _handleTimeout + * @protected + */ + p._handleTimeout = function () { + this._stopWatching(); + this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT")); + }; + + // WatchCSS does the work for us, and provides a modified src. + p._createRequest = function() { + return this._request; + }; + + // Events come from the internal XHR loader. + p.handleEvent = function (event) { + switch (event.type) { + case "complete": + this._rawResult = event.target._response; + this._result = true; + this._parseCSS(this._rawResult); + break; + + case "error": + this._stopWatching(); + this.AbstractLoader_handleEvent(event); + break; + } + }; + +// private methods: + /** + * Determine if the provided CSS is a string definition, CSS HTML element, or a CSS file URI. Depending on the + * format, the CSS will be parsed, or loaded. + * @method _watchCSS + * @returns {boolean} Whether or not the CSS is ready + * @protected + */ + p._watchCSS = function() { + var src = this._item.src; + + // An HTMLElement was passed in. Just use it. + if (src instanceof HTMLStyleElement) { + if (this._injectCSS && !src.parentNode) { (document.head || document.getElementsByTagName('head')[0]).appendChild(src); } + this._injectCSS = false; + src = "\n"+src.textContent; + } + + // A CSS string was passed in. Parse and use it + if (src.search(/\n|\r|@font-face/i) !== -1) { // css string. + this._parseCSS(src); + return true; + } + + // Load a CSS Path. Note that we CAN NOT load it without XHR because we need to read the CSS definition + this._request = new createjs.XHRRequest(this._item); + return false; + }; + + /** + * Parse a CSS string to determine the fonts to load. + * @method _parseCSS + * @param {String} css The CSS string to parse + * @protected + */ + p._parseCSS = function(css) { + var regex = /@font-face\s*\{([^}]+)}/g + while (true) { + var result = regex.exec(css); + if (!result) { break; } + this._watchFont(this._parseFontFace(result[1])); + } + this._injectStyleTag(css); + }; + + /** + * The provided fonts were an array of object or string definitions. Parse them, and inject any that are ready. + * @method _watchFontArray + * @protected + */ + p._watchFontArray = function() { + var arr = this._item.src, css = "", def; + for (var i=arr.length-1; i>=0; i--) { + var o = arr[i]; + if (typeof o === "string") { def = this._defFromSrc(o) } + else { def = this._defFromObj(o); } + this._watchFont(def); + css += this._cssFromDef(def)+"\n"; + } + this._injectStyleTag(css); + }; + + /** + * Inject any style definitions into the document head. This is necessary when the definition is just a string or + * object definition in order for the styles to be applied to the document. If the loaded fonts are already HTML CSS + * elements, they don't need to be appended again. + * @method _injectStyleTag + * @param {String} css The CSS string content to be appended to the + * @protected + */ + p._injectStyleTag = function(css) { + if (!this._injectCSS) { return; } + var head = document.head || document.getElementsByTagName('head')[0]; + var styleTag = document.createElement("style"); + styleTag.type = "text/css"; + if (styleTag.styleSheet){ + styleTag.styleSheet.cssText = css; + } else { + styleTag.appendChild(document.createTextNode(css)); + } + head.appendChild(styleTag); + }; + + /** + * Determine the font face from a CSS definition. + * @method _parseFontFace + * @param {String} str The CSS string definition + * @protected + * @return {String} A modified CSS object containing family name, src, style, and weight + */ + p._parseFontFace = function(str) { + var family = this._getCSSValue(str, "font-family"), src = this._getCSSValue(str, "src"); + if (!family || !src) { return null; } + return this._defFromObj({ + family: family, + src: src, + style: this._getCSSValue(str, "font-style"), + weight: this._getCSSValue(str, "font-weight") + }); + }; + + /** + * Add a font to the list of fonts currently being watched. If the font is already watched or loaded, it won't be + * added again. + * @method _watchFont + * @param {Object} def The font definition + * @protected + */ + p._watchFont = function(def) { + if (!def || this._faces[def.id]) { return; } + this._faces[def.id] = def; + this._watched.push(def); + this._count++; + + this._calculateReferenceSizes(def); + this._startWatching(); + }; + + /** + * Create a interval to check for loaded fonts. Only one interval is used for all fonts. The fonts are checked based + * on the {{#crossLink "FontLoader/WATCH_DURATION:property"}}{{/crossLink}}. + * @method _startWatching + * @protected + */ + p._startWatching = function() { + if (this._watchInterval != null) { return; } + this._watchInterval = setInterval(createjs.proxy(this._watch, this), FontLoader.WATCH_DURATION); + }; + + /** + * Clear the interval used to check fonts. This happens when all fonts are loaded, or an error occurs, such as a + * CSS file error, or a load timeout. + * @method _stopWatching + * @protected + */ + p._stopWatching = function() { + clearInterval(this._watchInterval); + clearTimeout(this._loadTimeout); + this._watchInterval = null; + }; + + /** + * Check all the fonts that have not been loaded. The fonts are drawn to a canvas in memory, and if their font size + * varies from the default text size, then the font is considered loaded. + * + * A {{#crossLink "AbstractLoader/fileload"}}{{/crossLink}} event will be dispatched when each file is loaded, along + * with the font family name as the `item` value. A {{#crossLink "ProgressEvent"}}{{/crossLink}} is dispatched a + * maximum of one time per check when any fonts are loaded, with the {{#crossLink "ProgressEvent/progress:property"}}{{/crossLink}} + * value showing the percentage of fonts that have loaded. + * @method _watch + * @protected + */ + p._watch = function() { + var defs = this._watched, refFonts = FontLoader._referenceFonts, l = defs.length; + for (var i = l - 1; i >= 0; i--) { + var def = defs[i], refs = def.refs; + for (var j = refs.length - 1; j >= 0; j--) { + var w = this._getTextWidth(def.family + "," + refFonts[j], def.weight, def.style); + if (w != refs[j]) { + var event = new createjs.Event("fileload"); + def.type = "font-family"; + event.item = def; + this.dispatchEvent(event); + defs.splice(i, 1); + break; + } + } + } + if (l !== defs.length) { + var event = new createjs.ProgressEvent(this._count-defs.length, this._count); + this.dispatchEvent(event); + } + if (l === 0) { + this._stopWatching(); + this._sendComplete(); + } + }; + + /** + * Determine the default size of the reference fonts used to compare against loaded fonts. + * @method _calculateReferenceSizes + * @param {Object} def The font definition to get the size of. + * @protected + */ + p._calculateReferenceSizes = function(def) { + var refFonts = FontLoader._referenceFonts; + var refs = def.refs = []; + for (var i=0; iwithout requiring CORS. + * JSONP files are loaded as JavaScript, and the "callback" is executed once they are loaded. The callback in the + * JSONP must match the callback passed to the loadItem. + * + *

    Example JSONP

    + * + * callbackName({ + * "name": "value", + * "num": 3, + * "obj": { "bool":true } + * }); + * + *

    Example

    + * + * var loadItem = {id:"json", type:"jsonp", src:"http://server.com/text.json", callback:"callbackName"} + * var queue = new createjs.LoadQueue(); + * queue.on("complete", handleComplete); + * queue.loadItem(loadItem); + * + * function handleComplete(event) } + * var json = queue.getResult("json"); + * console.log(json.obj.bool); // true + * } + * + * JSONP files loaded concurrently require a unique callback. To ensure JSONP files are loaded in order, + * either use the {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} method (set to 1), or set + * {{#crossLink "LoadItem/maintainOrder:property"}}{{/crossLink}} on items with the same callback. + * + * Important note: Some browsers will prevent JSONP from firing the callback if the file was loaded as JSON, and not + * JavaScript. You may have to have your server give you a JavaScript mime-type for this to work. + * + * @class JSONPLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function JSONPLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, false, createjs.Types.JSONP); + this.setTag(createjs.Elements.script()); + this.getTag().type = "text/javascript"; + }; + + var p = createjs.extend(JSONPLoader, createjs.AbstractLoader); + var s = JSONPLoader; + + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/JSONP:property"}}{{/crossLink}}. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.JSONP; + }; + + // public methods + p.cancel = function () { + this.AbstractLoader_cancel(); + this._dispose(); + }; + + /** + * Loads the JSONp file. Because of the unique loading needs of JSONp + * we don't use the AbstractLoader.load() method. + * + * @method load + * + */ + p.load = function () { + if (this._item.callback == null) { + throw new Error('callback is required for loading JSONP requests.'); + } + + // TODO: Look into creating our own iFrame to handle the load + // In the first attempt, FF did not get the result + // result instanceof Object did not work either + // so we would need to clone the result. + if (window[this._item.callback] != null) { + throw new Error( + "JSONP callback '" + + this._item.callback + + "' already exists on window. You need to specify a different callback or re-name the current one."); + } + + window[this._item.callback] = createjs.proxy(this._handleLoad, this); + createjs.DomUtils.appendToBody(this._tag); + + this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); + + // Load the tag + this._tag.src = this._item.src; + }; + + // private methods + /** + * Handle the JSONP callback, which is a public method defined on `window`. + * @method _handleLoad + * @param {Object} data The formatted JSON data. + * @private + */ + p._handleLoad = function (data) { + this._result = this._rawResult = data; + this._sendComplete(); + + this._dispose(); + }; + + /** + * The tag request has not loaded within the time specfied in loadTimeout. + * @method _handleError + * @param {Object} event The XHR error event. + * @private + */ + p._handleTimeout = function () { + this._dispose(); + this.dispatchEvent(new createjs.ErrorEvent("timeout")); + }; + + /** + * Clean up the JSONP load. This clears out the callback and script tag that this loader creates. + * @method _dispose + * @private + */ + p._dispose = function () { + createjs.DomUtils.removeChild(this._tag); + delete window[this._item.callback]; + + clearTimeout(this._loadTimeout); + }; + + createjs.JSONPLoader = createjs.promote(JSONPLoader, "AbstractLoader"); + +}()); diff --git a/src/preloadjs/loaders/JavaScriptLoader.js b/src/preloadjs/loaders/JavaScriptLoader.js new file mode 100644 index 00000000..e2844138 --- /dev/null +++ b/src/preloadjs/loaders/JavaScriptLoader.js @@ -0,0 +1,94 @@ +/* + * JavaScriptLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for JavaScript files. + * @class JavaScriptLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @extends AbstractLoader + * @constructor + */ + function JavaScriptLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.JAVASCRIPT); + + // public properties + this.resultFormatter = this._formatResult; + + // protected properties + this._tagSrcAttribute = "src"; + this.setTag(createjs.Elements.script()); + }; + + var p = createjs.extend(JavaScriptLoader, createjs.AbstractLoader); + var s = JavaScriptLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/JAVASCRIPT:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.JAVASCRIPT; + }; + + // protected methods + /** + * The result formatter for JavaScript files. + * @method _formatResult + * @param {AbstractLoader} loader + * @returns {HTMLLinkElement|HTMLStyleElement} + * @private + */ + p._formatResult = function (loader) { + var tag = loader.getTag(); + if (this._preferXHR) { + tag.text = loader.getResult(true); + } + return tag; + }; + + createjs.JavaScriptLoader = createjs.promote(JavaScriptLoader, "AbstractLoader"); + +}()); diff --git a/src/preloadjs/loaders/ManifestLoader.js b/src/preloadjs/loaders/ManifestLoader.js new file mode 100644 index 00000000..65b13f43 --- /dev/null +++ b/src/preloadjs/loaders/ManifestLoader.js @@ -0,0 +1,232 @@ +/* + * ManifestLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for JSON manifests. Items inside the manifest are loaded before the loader completes. To load manifests + * using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} as part of the + * {{#crossLink "LoadItem"}}{{/crossLink}}. + * + * The list of files in the manifest must be defined on the top-level JSON object in a `manifest` property. This + * example shows a sample manifest definition, as well as how to to include a sub-manifest. + * + * { + * "path": "assets/", + * "manifest": [ + * "image.png", + * {"src": "image2.png", "id":"image2"}, + * {"src": "sub-manifest.json", "type":"manifest", "callback":"jsonCallback"} + * ] + * } + * + * When a ManifestLoader has completed loading, the parent loader (usually a {{#crossLink "LoadQueue"}}{{/crossLink}}, + * but could also be another ManifestLoader) will inherit all the loaded items, so you can access them directly. + * + * Note that the {{#crossLink "JSONLoader"}}{{/crossLink}} and {{#crossLink "JSONPLoader"}}{{/crossLink}} are + * higher priority loaders, so manifests must set the {{#crossLink "LoadItem"}}{{/crossLink}} + * {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property to {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}}. + * + * Additionally, some browsers require the server to serve a JavaScript mime-type for JSONP, so it may not work in + * some conditions. + * @class ManifestLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function ManifestLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.MANIFEST); + + // Public Properties + /** + * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}, + * used to pass plugins to new LoadQueues that may be created. + * @property _plugins + * @type {Array} + * @private + * @since 0.6.1 + */ + this.plugins = null; + + + // Protected Properties + /** + * An internal {{#crossLink "LoadQueue"}}{{/crossLink}} that loads the contents of the manifest. + * @property _manifestQueue + * @type {LoadQueue} + * @private + */ + this._manifestQueue = null; + }; + + var p = createjs.extend(ManifestLoader, createjs.AbstractLoader); + var s = ManifestLoader; + + // static properties + /** + * The amount of progress that the manifest itself takes up. + * @property MANIFEST_PROGRESS + * @type {number} + * @default 0.25 (25%) + * @private + * @static + */ + s.MANIFEST_PROGRESS = 0.25; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/MANIFEST:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.MANIFEST; + }; + + // public methods + p.load = function () { + this.AbstractLoader_load(); + }; + + // protected methods + p._createRequest = function() { + var callback = this._item.callback; + if (callback != null) { + this._request = new createjs.JSONPLoader(this._item); + } else { + this._request = new createjs.JSONLoader(this._item); + } + }; + + p.handleEvent = function (event) { + switch (event.type) { + case "complete": + this._rawResult = event.target.getResult(true); + this._result = event.target.getResult(); + this._sendProgress(s.MANIFEST_PROGRESS); + this._loadManifest(this._result); + return; + case "progress": + event.loaded *= s.MANIFEST_PROGRESS; + this.progress = event.loaded / event.total; + if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } + this._sendProgress(event); + return; + } + this.AbstractLoader_handleEvent(event); + }; + + p.destroy = function() { + this.AbstractLoader_destroy(); + this._manifestQueue.close(); + }; + + /** + * Create and load the manifest items once the actual manifest has been loaded. + * @method _loadManifest + * @param {Object} json + * @private + */ + p._loadManifest = function (json) { + if (json && json.manifest) { + var queue = this._manifestQueue = new createjs.LoadQueue(this._preferXHR); + queue.on("fileload", this._handleManifestFileLoad, this); + queue.on("progress", this._handleManifestProgress, this); + queue.on("complete", this._handleManifestComplete, this, true); + queue.on("error", this._handleManifestError, this, true); + for(var i = 0, l = this.plugins.length; i < l; i++) { // conserve order of plugins + queue.installPlugin(this.plugins[i]); + } + queue.loadManifest(json); + } else { + this._sendComplete(); + } + }; + + /** + * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed. + * @method _handleManifestFileLoad + * @param {Event} event + * @private + */ + p._handleManifestFileLoad = function (event) { + event.target = null; + this.dispatchEvent(event); + }; + + /** + * The manifest has completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} + * {{#crossLink "Event"}}{{/crossLink}} from the ManifestLoader. + * @method _handleManifestComplete + * @param {Event} event + * @private + */ + p._handleManifestComplete = function (event) { + this._loadedItems = this._manifestQueue.getItems(true); + this._sendComplete(); + }; + + /** + * The manifest has reported progress. + * @method _handleManifestProgress + * @param {ProgressEvent} event + * @private + */ + p._handleManifestProgress = function (event) { + this.progress = event.progress * (1 - s.MANIFEST_PROGRESS) + s.MANIFEST_PROGRESS; + this._sendProgress(this.progress); + }; + + /** + * The manifest has reported an error with one of the files. + * @method _handleManifestError + * @param {ErrorEvent} event + * @private + */ + p._handleManifestError = function (event) { + var newEvent = new createjs.Event("fileerror"); + newEvent.item = event.data; + this.dispatchEvent(newEvent); + }; + + createjs.ManifestLoader = createjs.promote(ManifestLoader, "AbstractLoader"); + +}()); diff --git a/src/preloadjs/loaders/SVGLoader.js b/src/preloadjs/loaders/SVGLoader.js new file mode 100644 index 00000000..83815a45 --- /dev/null +++ b/src/preloadjs/loaders/SVGLoader.js @@ -0,0 +1,114 @@ +/* + * SVGLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for SVG files. + * @class SVGLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @extends AbstractLoader + * @constructor + */ + function SVGLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.SVG); + + // public properties + this.resultFormatter = this._formatResult; + + // protected properties + this._tagSrcAttribute = "data"; + + if (preferXHR) { + this.setTag(createjs.Elements.svg()); + } else { + this.setTag(createjs.Elements.object()); + this.getTag().type = "image/svg+xml"; + } + }; + + var p = createjs.extend(SVGLoader, createjs.AbstractLoader); + var s = SVGLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/SVG:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.SVG; + }; + + // protected methods + /** + * The result formatter for SVG files. + * @method _formatResult + * @param {AbstractLoader} loader + * @returns {Object} + * @private + */ + p._formatResult = function (loader) { + // mime should be image/svg+xml, but Opera requires text/xml + var xml = createjs.DataUtils.parseXML(loader.getResult(true)); + var tag = loader.getTag(); + + if (!this._preferXHR && document.body.contains(tag)) { + document.body.removeChild(tag); + } + + if (xml.documentElement != null) { + var element = xml.documentElement; + // Support loading an SVG from a different domain in ID + if (document.importNode) { + element = document.importNode(element, true); + } + tag.appendChild(element); + return tag; + } else { // For browsers that don't support SVG, just give them the XML. (IE 9-8) + return xml; + } + }; + + createjs.SVGLoader = createjs.promote(SVGLoader, "AbstractLoader"); + +}()); diff --git a/src/preloadjs/loaders/SoundLoader.js b/src/preloadjs/loaders/SoundLoader.js new file mode 100644 index 00000000..ddf98bce --- /dev/null +++ b/src/preloadjs/loaders/SoundLoader.js @@ -0,0 +1,98 @@ +/* + * SoundLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // 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"); + +}()); diff --git a/src/preloadjs/loaders/SpriteSheetLoader.js b/src/preloadjs/loaders/SpriteSheetLoader.js new file mode 100644 index 00000000..e5cad14c --- /dev/null +++ b/src/preloadjs/loaders/SpriteSheetLoader.js @@ -0,0 +1,207 @@ +/* + * SpriteSheetLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for EaselJS SpriteSheets. Images inside the spritesheet definition are loaded before the loader + * completes. To load SpriteSheets using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} + * as part of the {{#crossLink "LoadItem"}}{{/crossLink}}. Note that the {{#crossLink "JSONLoader"}}{{/crossLink}} + * and {{#crossLink "JSONPLoader"}}{{/crossLink}} are higher priority loaders, so SpriteSheets must + * set the {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property + * to {{#crossLink "Types/SPRITESHEET:property"}}{{/crossLink}}. + * + * The {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/crossOrigin:property"}}{{/crossLink}} as well + * as the {{#crossLink "LoadQueue's"}}{{/crossLink}} `basePath` argument and {{#crossLink "LoadQueue/_preferXHR"}}{{/crossLink}} + * property supplied to the {{#crossLink "LoadQueue"}}{{/crossLink}} are passed on to the sub-manifest that loads + * the SpriteSheet images. + * + * Note that the SpriteSheet JSON does not respect the {{#crossLink "LoadQueue/_preferXHR:property"}}{{/crossLink}} + * property, which should instead be determined by the presence of a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} + * property on the SpriteSheet load item. This is because the JSON loaded will have a different format depending on + * if it is loaded as JSON, so just changing `preferXHR` is not enough to change how it is loaded. + * @class SpriteSheetLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function SpriteSheetLoader(loadItem, preferXHR) { + this.AbstractLoader_constructor(loadItem, preferXHR, createjs.Types.SPRITESHEET); + + // protected properties + /** + * An internal queue which loads the SpriteSheet's images. + * @method _manifestQueue + * @type {LoadQueue} + * @private + */ + this._manifestQueue = null; + } + + var p = createjs.extend(SpriteSheetLoader, createjs.AbstractLoader); + var s = SpriteSheetLoader; + + // static properties + /** + * The amount of progress that the manifest itself takes up. + * @property SPRITESHEET_PROGRESS + * @type {number} + * @default 0.25 (25%) + * @private + * @static + */ + s.SPRITESHEET_PROGRESS = 0.25; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/SPRITESHEET:property"}}{{/crossLink}} + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.SPRITESHEET; + }; + + // public methods + p.destroy = function() { + this.AbstractLoader_destroy(); + this._manifestQueue.close(); + }; + + // protected methods + p._createRequest = function() { + var callback = this._item.callback; + if (callback != null) { + this._request = new createjs.JSONPLoader(this._item); + } else { + this._request = new createjs.JSONLoader(this._item); + } + }; + + p.handleEvent = function (event) { + switch (event.type) { + case "complete": + this._rawResult = event.target.getResult(true); + this._result = event.target.getResult(); + this._sendProgress(s.SPRITESHEET_PROGRESS); + this._loadManifest(this._result); + return; + case "progress": + event.loaded *= s.SPRITESHEET_PROGRESS; + this.progress = event.loaded / event.total; + if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } + this._sendProgress(event); + return; + } + this.AbstractLoader_handleEvent(event); + }; + + /** + * Create and load the images once the SpriteSheet JSON has been loaded. + * @method _loadManifest + * @param {Object} json + * @private + */ + p._loadManifest = function (json) { + if (json && json.images) { + var queue = this._manifestQueue = new createjs.LoadQueue(this._preferXHR, this._item.path, this._item.crossOrigin); + queue.on("complete", this._handleManifestComplete, this, true); + queue.on("fileload", this._handleManifestFileLoad, this); + queue.on("progress", this._handleManifestProgress, this); + queue.on("error", this._handleManifestError, this, true); + queue.loadManifest(json.images); + } + }; + + /** + * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed. + * @method _handleManifestFileLoad + * @param {Event} event + * @private + */ + p._handleManifestFileLoad = function (event) { + var image = event.result; + if (image != null) { + var images = this.getResult().images; + var pos = images.indexOf(event.item.src); + images[pos] = image; + } + }; + + /** + * The images have completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} + * {{#crossLink "Event"}}{{/crossLink}} from the SpriteSheetLoader. + * @method _handleManifestComplete + * @param {Event} event + * @private + */ + p._handleManifestComplete = function (event) { + this._result = new createjs.SpriteSheet(this._result); + this._loadedItems = this._manifestQueue.getItems(true); + this._sendComplete(); + }; + + /** + * The images {{#crossLink "LoadQueue"}}{{/crossLink}} has reported progress. + * @method _handleManifestProgress + * @param {ProgressEvent} event + * @private + */ + p._handleManifestProgress = function (event) { + this.progress = event.progress * (1 - s.SPRITESHEET_PROGRESS) + s.SPRITESHEET_PROGRESS; + this._sendProgress(this.progress); + }; + + /** + * An image has reported an error. + * @method _handleManifestError + * @param {ErrorEvent} event + * @private + */ + p._handleManifestError = function (event) { + var newEvent = new createjs.Event("fileerror"); + newEvent.item = event.data; + this.dispatchEvent(newEvent); + }; + + createjs.SpriteSheetLoader = createjs.promote(SpriteSheetLoader, "AbstractLoader"); + +}()); diff --git a/src/preloadjs/loaders/TextLoader.js b/src/preloadjs/loaders/TextLoader.js new file mode 100644 index 00000000..dc4e5efb --- /dev/null +++ b/src/preloadjs/loaders/TextLoader.js @@ -0,0 +1,70 @@ +/* + * TextLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for Text files. + * @class TextLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function TextLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, true, createjs.Types.TEXT); + }; + + var p = createjs.extend(TextLoader, createjs.AbstractLoader); + var s = TextLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader loads items that are of type {{#crossLink "Types/TEXT:property"}}{{/crossLink}}, + * but is also the default loader if a file type can not be determined. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.TEXT; + }; + + createjs.TextLoader = createjs.promote(TextLoader, "AbstractLoader"); + +}()); diff --git a/src/preloadjs/loaders/VideoLoader.js b/src/preloadjs/loaders/VideoLoader.js new file mode 100644 index 00000000..daeb2c66 --- /dev/null +++ b/src/preloadjs/loaders/VideoLoader.js @@ -0,0 +1,90 @@ +/* + * VideoLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for video files. + * @class VideoLoader + * @param {LoadItem|Object} loadItem + * @param {Boolean} preferXHR + * @extends AbstractMediaLoader + * @constructor + */ + function VideoLoader(loadItem, preferXHR) { + this.AbstractMediaLoader_constructor(loadItem, preferXHR, createjs.Types.VIDEO); + + if (createjs.DomUtils.isVideoTag(loadItem) || createjs.DomUtils.isVideoTag(loadItem.src)) { + this.setTag(createjs.DomUtils.isVideoTag(loadItem)?loadItem:loadItem.src); + + // We can't use XHR for a tag that's passed in. + this._preferXHR = false; + } else { + this.setTag(this._createTag()); + } + }; + + var p = createjs.extend(VideoLoader, createjs.AbstractMediaLoader); + var s = VideoLoader; + + /** + * Create a new video tag + * + * @returns {HTMLElement} + * @private + */ + p._createTag = function () { + return createjs.Elements.video(); + }; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/VIDEO:property"}}{{/crossLink}}. + * @method canLoadItem + * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. + * @returns {Boolean} Whether the loader can load the item. + * @static + */ + s.canLoadItem = function (item) { + return item.type == createjs.Types.VIDEO; + }; + + createjs.VideoLoader = createjs.promote(VideoLoader, "AbstractMediaLoader"); + +}()); diff --git a/src/preloadjs/loaders/XMLLoader.js b/src/preloadjs/loaders/XMLLoader.js new file mode 100644 index 00000000..cf1fee2a --- /dev/null +++ b/src/preloadjs/loaders/XMLLoader.js @@ -0,0 +1,85 @@ +/* + * XMLLoader + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * A loader for CSS files. + * @class XMLLoader + * @param {LoadItem|Object} loadItem + * @extends AbstractLoader + * @constructor + */ + function XMLLoader(loadItem) { + this.AbstractLoader_constructor(loadItem, true, createjs.Types.XML); + + // public properties + this.resultFormatter = this._formatResult; + }; + + var p = createjs.extend(XMLLoader, createjs.AbstractLoader); + var s = XMLLoader; + + // static methods + /** + * Determines if the loader can load a specific item. This loader can only load items that are of type + * {{#crossLink "Types/XML: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.XML; + }; + + // protected methods + /** + * The result formatter for XML files. + * @method _formatResult + * @param {AbstractLoader} loader + * @returns {XMLDocument} + * @private + */ + p._formatResult = function (loader) { + return createjs.DataUtils.parseXML(loader.getResult(true)); + }; + + createjs.XMLLoader = createjs.promote(XMLLoader, "AbstractLoader"); + +}()); diff --git a/src/preloadjs/net/AbstractRequest.js b/src/preloadjs/net/AbstractRequest.js new file mode 100644 index 00000000..ccb10ae0 --- /dev/null +++ b/src/preloadjs/net/AbstractRequest.js @@ -0,0 +1,75 @@ +/* + * AbstractRequest + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + /** + * A base class for actual data requests, such as {{#crossLink "XHRRequest"}}{{/crossLink}}, {{#crossLink "TagRequest"}}{{/crossLink}}, + * and {{#crossLink "MediaRequest"}}{{/crossLink}}. PreloadJS loaders will typically use a data loader under the + * hood to get data. + * @class AbstractRequest + * @param {LoadItem} item + * @constructor + */ + var AbstractRequest = function (item) { + this._item = item; + }; + + 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"); + +}()); \ No newline at end of file diff --git a/src/preloadjs/net/MediaTagRequest.js b/src/preloadjs/net/MediaTagRequest.js new file mode 100644 index 00000000..39c0fe02 --- /dev/null +++ b/src/preloadjs/net/MediaTagRequest.js @@ -0,0 +1,121 @@ +/* + * MediaTagRequest + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // 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"); + +}()); diff --git a/src/preloadjs/net/TagRequest.js b/src/preloadjs/net/TagRequest.js new file mode 100644 index 00000000..dbdbed68 --- /dev/null +++ b/src/preloadjs/net/TagRequest.js @@ -0,0 +1,197 @@ +/* + * TagRequest + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + + // constructor + /** + * An {{#crossLink "AbstractRequest"}}{{/crossLink}} that loads HTML tags, such as images and scripts. + * @class TagRequest + * @param {LoadItem} loadItem + * @param {HTMLElement} tag + * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc. + */ + function TagRequest(loadItem, tag, srcAttribute) { + this.AbstractRequest_constructor(loadItem); + + // protected properties + /** + * The HTML tag instance that is used to load. + * @property _tag + * @type {HTMLElement} + * @protected + */ + this._tag = tag; + + /** + * The tag attribute that specifies the source, such as "src", "href", etc. + * @property _tagSrcAttribute + * @type {String} + * @protected + */ + this._tagSrcAttribute = srcAttribute; + + /** + * A method closure used for handling the tag load event. + * @property _loadedHandler + * @type {Function} + * @private + */ + this._loadedHandler = createjs.proxy(this._handleTagComplete, this); + + /** + * Determines if the element was added to the DOM automatically by PreloadJS, so it can be cleaned up after. + * @property _addedToDOM + * @type {Boolean} + * @private + */ + this._addedToDOM = false; + + }; + + 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"); + +}()); diff --git a/src/preloadjs/net/XHRRequest.js b/src/preloadjs/net/XHRRequest.js new file mode 100644 index 00000000..01df75d4 --- /dev/null +++ b/src/preloadjs/net/XHRRequest.js @@ -0,0 +1,572 @@ +/* + * XHRRequest + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +// namespace: +this.createjs = this.createjs || {}; + +(function () { + "use strict"; + +// constructor + /** + * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used + * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary. + * XHR requests load the content as text or binary data, provide progress and consistent completion events, and + * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for + * cross-domain loading. + * @class XHRRequest + * @constructor + * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} + * for an overview of supported file properties. + * @extends AbstractLoader + */ + function XHRRequest (item) { + this.AbstractRequest_constructor(item); + + // protected properties + /** + * A reference to the XHR request used to load the content. + * @property _request + * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP} + * @private + */ + this._request = null; + + /** + * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1, + * typically IE9). + * @property _loadTimeout + * @type {Number} + * @private + */ + this._loadTimeout = null; + + /** + * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect + * the version, so we use capabilities to make a best guess. + * @property _xhrLevel + * @type {Number} + * @default 1 + * @private + */ + this._xhrLevel = 1; + + /** + * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be + * null until the file is loaded. + * @property _response + * @type {mixed} + * @private + */ + this._response = null; + + /** + * The response of the loaded file before it is modified. In most cases, content is converted from raw text to + * an HTML tag or a formatted object which is set to the result property, but the developer may still + * want to access the raw content as it was loaded. + * @property _rawResponse + * @type {String|Object} + * @private + */ + this._rawResponse = null; + + this._canceled = false; + + // Setup our event handlers now. + this._handleLoadStartProxy = createjs.proxy(this._handleLoadStart, this); + this._handleProgressProxy = createjs.proxy(this._handleProgress, this); + this._handleAbortProxy = createjs.proxy(this._handleAbort, this); + this._handleErrorProxy = createjs.proxy(this._handleError, this); + this._handleTimeoutProxy = createjs.proxy(this._handleTimeout, this); + this._handleLoadProxy = createjs.proxy(this._handleLoad, this); + this._handleReadyStateChangeProxy = createjs.proxy(this._handleReadyStateChange, this); + + if (!this._createXHR(item)) { + //TODO: Throw error? + } + }; + + var p = createjs.extend(XHRRequest, createjs.AbstractRequest); + +// static properties + /** + * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE. + * @property ACTIVEX_VERSIONS + * @type {Array} + * @since 0.4.2 + * @private + */ + XHRRequest.ACTIVEX_VERSIONS = [ + "Msxml2.XMLHTTP.6.0", + "Msxml2.XMLHTTP.5.0", + "Msxml2.XMLHTTP.4.0", + "MSXML2.XMLHTTP.3.0", + "MSXML2.XMLHTTP", + "Microsoft.XMLHTTP" + ]; + +// Public methods + /** + * Look up the loaded result. + * @method getResult + * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content + * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be + * returned instead. + * @return {Object} A result object containing the content that was loaded, such as: + *
      + *
    • An image tag (<image />) for images
    • + *
    • A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the + * HTML head.
    • + *
    • A style tag for CSS (<style />)
    • + *
    • Raw text for TEXT
    • + *
    • A formatted JavaScript object defined by JSON
    • + *
    • An XML document
    • + *
    • An binary arraybuffer loaded by XHR
    • + *
    + * Note that if a raw result is requested, but not found, the result will be returned instead. + */ + p.getResult = function (raw) { + if (raw && this._rawResponse) { + return this._rawResponse; + } + return this._response; + }; + + // Overrides abstract method in AbstractRequest + p.cancel = function () { + this.canceled = true; + this._clean(); + this._request.abort(); + }; + + // Overrides abstract method in AbstractLoader + p.load = function () { + if (this._request == null) { + this._handleError(); + return; + } + + //Events + if (this._request.addEventListener != null) { + this._request.addEventListener("loadstart", this._handleLoadStartProxy, false); + this._request.addEventListener("progress", this._handleProgressProxy, false); + this._request.addEventListener("abort", this._handleAbortProxy, false); + this._request.addEventListener("error", this._handleErrorProxy, false); + this._request.addEventListener("timeout", this._handleTimeoutProxy, false); + + // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. + this._request.addEventListener("load", this._handleLoadProxy, false); + this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false); + } else { + // IE9 support + this._request.onloadstart = this._handleLoadStartProxy; + this._request.onprogress = this._handleProgressProxy; + this._request.onabort = this._handleAbortProxy; + this._request.onerror = this._handleErrorProxy; + this._request.ontimeout = this._handleTimeoutProxy; + + // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. + this._request.onload = this._handleLoadProxy; + this._request.onreadystatechange = this._handleReadyStateChangeProxy; + } + + // Set up a timeout if we don't have XHR2 + if (this._xhrLevel == 1) { + this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); + } + + // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome + try { + if (!this._item.values) { + this._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: + *
      + *
    • Status codes between 400 and 599 (HTTP error range)
    • + *
    • A status of 0, but *only when the application is running on a server*. If the application is running + * on `file:`, then it may incorrectly treat an error on local (or embedded applications) as a successful + * load.
    • + *
    + * @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"); + +}()); diff --git a/src/preloadjs/SamplePlugin.js b/src/preloadjs/plugins/SamplePlugin.js similarity index 51% rename from src/preloadjs/SamplePlugin.js rename to src/preloadjs/plugins/SamplePlugin.js index fb930049..461cd2b5 100644 --- a/src/preloadjs/SamplePlugin.js +++ b/src/preloadjs/plugins/SamplePlugin.js @@ -1,6 +1,39 @@ -/** @module PreloadJS */ +/* + * Types + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ -(function() { +/** + * @module PreloadJS + */ + +(function () { + + "use strict"; /** * A PreloadJS plugin provides a way to inject functionality into PreloadJS to load file types that are unsupported, @@ -12,11 +45,14 @@ * the {{#crossLink "LoadQueue"}}{{/crossLink}} class. Available load types are: *
      *
    • binary ({{#crossLink "LoadQueue/BINARY:property"}}{{/crossLink}})
    • + *
    • css ({{#crossLink "LoadQueue/CSS:property"}}{{/crossLink}})
    • *
    • image ({{#crossLink "LoadQueue/IMAGE:property"}}{{/crossLink}})
    • *
    • javascript ({{#crossLink "LoadQueue/JAVASCRIPT:property"}}{{/crossLink}})
    • *
    • json ({{#crossLink "LoadQueue/JSON:property"}}{{/crossLink}})
    • *
    • jsonp ({{#crossLink "LoadQueue/JSONP:property"}}{{/crossLink}})
    • + *
    • manifest ({{#crossLink "LoadQueue/MANIFEST:property"}}{{/crossLink}})
    • *
    • sound ({{#crossLink "LoadQueue/SOUND:property"}}{{/crossLink}})
    • + *
    • spriteSheet ({{#crossLink "LoadQueue/SPRITESHEET:property"}}{{/crossLink}})
    • *
    • svg ({{#crossLink "LoadQueue/SVG:property"}}{{/crossLink}})
    • *
    • text ({{#crossLink "LoadQueue/TEXT:property"}}{{/crossLink}})
    • *
    • xml ({{#crossLink "LoadQueue/XML:property"}}{{/crossLink}})
    • @@ -34,30 +70,29 @@ * * The {{#crossLink "SamplePlugin/getPreloadHandlers"}}{{/crossLink}} method can also return a `callback` * property, which is a function that will be invoked before each file is loaded. Check out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} - * for more information on how the callback works. - * - * For example, the SoundJS plugin allows PreloadJS to manage a download that - * happens in Flash + * for more information on how the callback works. For example, the SoundJS plugin allows PreloadJS to manage a + * download that uses the Flash Player. * * @class SamplePlugin * @static */ - var SamplePlugin = function() {} + var SamplePlugin = function () { + }; var s = SamplePlugin; /** * When a plugin is installed, this method will be called to let PreloadJS know when to invoke the plugin. * * PreloadJS expects this method to return an object containing: - *
        - *
      • callback: The function to call on the plugin class right before an item is loaded. Check + *
          + *
        • callback: The function to call on the plugin class right before an item is loaded. Check * out the {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}} method for more information. The callback * is automatically called in the scope of the plugin.
        • - *
        • types: An array of recognized PreloadJS load types to handle. Supported load types are + *
        • types: An array of recognized PreloadJS load types to handle. Supported load types are * "binary","image", "javascript", "json", "jsonp", "sound", "svg", "text", and "xml".
        • - *
        • extensions: An array of strings containing file extensions to handle, such as "jpg", + *
        • extensions: An array of strings containing file extensions to handle, such as "jpg", * "mp3", etc. This only fires if an applicable type handler is not found by the plugin.
        • - *
        + *
      * * Note that currently, PreloadJS only supports a single handler for each extension or file type. * @@ -78,7 +113,7 @@ * @method getPreloadHandlers * @return {Object} An object defining a callback, type handlers, and extension handlers (see description) */ - s.getPreloadHandlers = function() { + s.getPreloadHandlers = function () { return { callback: s.preloadHandler, // Proxy the method to maintain scope types: ["image"], @@ -89,72 +124,46 @@ /** * This is a sample method to show how to handle the callback specified in the {{#crossLink "LoadQueue/getPreloadHandlers"}}{{/crossLink}}. * Right before a file is loaded, if a plugin for the file type or extension is found, then the callback for that - * plugin will be invoked. The arguments provided match most of those specified in load items passed into {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}}: - *
        - *
      • src: The item source
      • - *
      • type: The item type
      • - *
      • id: The item id
      • - *
      • data: Arbitrary data attached to the item
      • - * - * Two additional arguments are appended: - *
          - *
        • basePath: A path that is prepended to all items loaded with PreloadJS. Note - * that basePath is deprecated, but is left in for backwards compatibility
        • - *
        • queue: The {{#crossLink "LoadQueue"}}{{/crossLink}} instance that is loading the - * item.
        • - *
        - * - * This gives the plugin an opportunity to modify the load item, or even cancel the load. The return value of the - * callback determines how PreloadJS will handle the file: + * plugin will be invoked. This gives the plugin an opportunity to modify the load item, or even cancel the load. + * The return value of the callback determines how PreloadJS will handle the file: *
          *
        • false: Skip the item. This allows plugins to determine if a file should be loaded or * not. For example,the plugin could determine if a file type is supported at all on the current system, and * skip those that do not.
        • *
        • true: Continue normally. The plugin will not affect the load.
        • + *
        • AbstractLoader instance: Used as the loader for the content. This is new in 0.6.0.
        • *
        * - * An object can also be returned which has properties that can override the existing load object. The return object - * can include modified `src` and `id` parameters, as well as "tag" and "completeHandler" properties: - *
          - *
        • tag: a JavaScript object that will handle the actual loading of the file. This is - * modeled after HTML image & audio tags, and must contain a load() method or a `src` setter, - * as well as and onload and onerror callback.
        • - *
        • completeHandler: A method to call on the plugin once the item has been loaded. This is - * useful to provide any necessary post-load functionality. Check out the {{#crossLink "SamplePlugin/fileLoadHandler"}}{{/crossLink}} - * for more information.
        • - *
        + * Since the {{#crossLink "LoadItem"}}{{/crossLink}} is passed by reference, a plugin can modify as needed, even + * appending additional data to it. Note that if the {{#crossLink "LoadItem/src:property"}}{{/crossLink}} is + * modified, PreloadJS will automatically update the {{#crossLink "LoadItem/ext:property"}}{{/crossLink}} property. * *

        Example

        * - * //Check out the SamplePlugin source for a more complete example. - * * // Cancel a load - * SamplePlugin.preloadHandler = function(src, type, id, data, basePath, queue) { - * if (id.indexOf("thumb") { return false; } // Don't load items like "image-thumb.png" + * SamplePlugin.preloadHandler = function(loadItem, queue) { + * if (loadItem.id.indexOf("thumb") { return false; } // Don't load items like "image-thumb.png" * return true; * } * * // Specify a completeHandler - * SamplePlugin.preloadHandler = function(src, type, id, data, basePath, queue) { - * return { - * completeHandler: SamplePlugin.fileLoadHandler - * }; + * SamplePlugin.preloadHandler = function(loadItem, queue) { + * item.completeHandler = SamplePlugin.fileLoadHandler; * } * + * // Check out the SamplePlugin source to see another example. + * + * Note: In 0.4.2 and earlier, instead of a {{#crossLink "LoadItem"}}{{/crossLink}}, arguments were passed in, + * and a modified object was returned to PreloadJS. This has been changed to passing a reference to the LoadItem, + * which can be directly modified. + * * @method preloadHandler - * @param src {String} The path to the file, as specified by the developer, without a base path. - * @param type {String} The file type, which is either passed in by the developer, or determined based on the - * extension. Supported load types are "binary","image", "javascript", "json", "jsonp", "sound", "svg", "text", and - * "xml". This value may be null if the extension is not recognized by PreloadJS. - * @param id {String} The string-based ID, which is optionally passed in by the user. - * @param data {*} Arbitrary data optionally attached to the load item by the user, which is maintained until the - * item is loaded and returned to the user from PreloadJS. - * @param basePath {String} A base path which is supplied to PreloadJS, which is prepended to the source of any - * load item. - * @param queue {LoadQueue} The {{#crossLink "LoadQueue"}}{{/crossLink}} instance that is preloading the item. - * @return {Boolean|Object} How PreloadJS should handle the load. See the main description for more info. + * @param {LoadItem|Object} loadItem The item that PreloadJS is going to load. This item is passes by reference, + * so it can be directly modified. + * @param {LoadQueue} queue The {{#crossLink "LoadQueue"}}{{/crossLink}} instance that is preloading the item. + * @return {Boolean|AbstractLoader} How PreloadJS should handle the load. See the main description for more info. */ - s.preloadHandler = function(src, type, id, data, basePath, queue) { + s.preloadHandler = function (loadItem, queue) { var options = {}; // Tell PreloadJS to skip this file @@ -163,28 +172,33 @@ // Tell PreloadJS to continue normally if (options.doNothing) { return true; } - // Return modified values, as well as additional instructions - return { - src: src, - id: id, - completeHandler: createjs.proxy(s.fileCompleteHandler, s), - tag: null - } + // Modify the LoadItem + loadItem.id = "newId"; + loadItem.completeHandler = createjs.proxy(s.fileCompleteHandler, s); + + // Return a new loader. This is an advanced usage, similar to what SoundJS does. + var loader = new createjs.ImageLoader(loadItem); + loader.on("complete", createjs.proxy(s.fileCompleteHandler, s)); + + return loader; }; /** * This is a sample method to show a `completeHandler`, which is optionally specified by the return object in the - * {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}}. This method is called after the item has completely - * loaded, but before the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is dispatched from the - * {{#crossLink "LoadQueue"}}{{/crossLink}}. + * {{#crossLink "SamplePlugin/preloadHandler"}}{{/crossLink}}. This sample provides a `completeHandler` to the + * {{#crossLink "LoadItem"}}{{/crossLink}}. This method is called after the item has completely loaded, but before + * the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is dispatched from the {{#crossLink "LoadQueue"}}{{/crossLink}}. + * + * The provided sample also listens for the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} + * event on the loader it returns to show a different usage. * * @method fileLoadHandler - * @param event {Object} A {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event. + * @param event {Event} A {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event. */ - s.fileLoadHandler = function(event) { + s.fileLoadHandler = function (event) { // Do something with the result. }; createjs.SamplePlugin = SamplePlugin; -}()); \ No newline at end of file +}()); diff --git a/src/preloadjs/utils/DataUtils.js b/src/preloadjs/utils/DataUtils.js new file mode 100644 index 00000000..9014c2f0 --- /dev/null +++ b/src/preloadjs/utils/DataUtils.js @@ -0,0 +1,99 @@ +/* + * DataUtils + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +(function () { + + /** + * A few data utilities for formatting different data types. + * @class DataUtils + */ + var s = {}; + + // static methods + /** + * Parse XML using the DOM. This is required when preloading XML or SVG. + * @method parseXML + * @param {String} text The raw text or XML that is loaded by XHR. + * @return {XML} An XML document + * @static + */ + s.parseXML = function (text) { + var xml = null; + // CocoonJS does not support XML parsing with either method. + + // Most browsers will use DOMParser + // IE fails on certain SVG files, so we have a fallback below. + try { + if (window.DOMParser) { + var parser = new DOMParser(); + xml = parser.parseFromString(text, "text/xml"); + } + } catch (e) { + } + + // Fallback for IE support. + if (!xml) { + try { + xml = new ActiveXObject("Microsoft.XMLDOM"); + xml.async = false; + xml.loadXML(text); + } catch (e) { + xml = null; + } + } + + return xml; + }; + + /** + * Parse a string into an Object. + * @method parseJSON + * @param {String} value The loaded JSON string + * @returns {Object} A JavaScript object. + */ + s.parseJSON = function (value) { + if (value == null) { + return null; + } + + try { + return JSON.parse(value); + } catch (e) { + // TODO; Handle this with a custom error? + throw e; + } + }; + + createjs.DataUtils = s; + +}()); diff --git a/src/preloadjs/utils/DomUtils.js b/src/preloadjs/utils/DomUtils.js new file mode 100644 index 00000000..9ddff92d --- /dev/null +++ b/src/preloadjs/utils/DomUtils.js @@ -0,0 +1,120 @@ +/* + * DomUtils + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +(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; + +}()); diff --git a/src/preloadjs/utils/Elements.js b/src/preloadjs/utils/Elements.js new file mode 100644 index 00000000..04877dda --- /dev/null +++ b/src/preloadjs/utils/Elements.js @@ -0,0 +1,94 @@ +/* + * Elements + * + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +(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; + +}()); diff --git a/src/preloadjs/utils/RequestUtils.js b/src/preloadjs/utils/RequestUtils.js new file mode 100644 index 00000000..87a2136f --- /dev/null +++ b/src/preloadjs/utils/RequestUtils.js @@ -0,0 +1,134 @@ +/* + * RequestUtils + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +(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": + case "aac": + 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; + +}()); diff --git a/src/preloadjs/utils/URLUtils.js b/src/preloadjs/utils/URLUtils.js new file mode 100644 index 00000000..9aba8b40 --- /dev/null +++ b/src/preloadjs/utils/URLUtils.js @@ -0,0 +1,219 @@ +/* + * URLUtils + * Visit http://createjs.com/ for documentation, updates and examples. + * + * + * Copyright (c) 2012 gskinner.com, inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @module PreloadJS + */ + +(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: + *
          + *
        • If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or + * `//networkPath`)
        • + *
        • If the path is relative. Relative paths start with `../` or `/path` (or similar)
        • + *
        • The file extension. This is determined by the filename with an extension. Query strings are dropped, and + * the file path is expected to follow the format `name.ext`.
        • + *
        + * + * @method parseURI + * @param {String} path + * @returns {Object} An Object with an `absolute` and `relative` Boolean values, + * 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; + +}()); diff --git a/src/preloadjs/utils/json3.js b/src/preloadjs/utils/json3.js new file mode 100644 index 00000000..4817c9e7 --- /dev/null +++ b/src/preloadjs/utils/json3.js @@ -0,0 +1,902 @@ +/*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */ +;(function () { + // Detect the `define` function exposed by asynchronous module loaders. The + // strict `define` check is necessary for compatibility with `r.js`. + var isLoader = typeof define === "function" && define.amd; + + // A set of types used to distinguish objects from primitives. + var objectTypes = { + "function": true, + "object": true + }; + + // Detect the `exports` object exposed by CommonJS implementations. + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + + // Use the `global` object exposed by Node (including Browserify via + // `insert-module-globals`), Narwhal, and Ringo as the default context, + // and the `window` object in browsers. Rhino exports a `global` function + // instead. + var root = objectTypes[typeof window] && window || this, + freeGlobal = freeExports && objectTypes[typeof module] && module && !module.nodeType && typeof global == "object" && global; + + if (freeGlobal && (freeGlobal["global"] === freeGlobal || freeGlobal["window"] === freeGlobal || freeGlobal["self"] === freeGlobal)) { + root = freeGlobal; + } + + // Public: Initializes JSON 3 using the given `context` object, attaching the + // `stringify` and `parse` functions to the specified `exports` object. + function runInContext(context, exports) { + context || (context = root["Object"]()); + exports || (exports = root["Object"]()); + + // Native constructor aliases. + var Number = context["Number"] || root["Number"], + String = context["String"] || root["String"], + Object = context["Object"] || root["Object"], + Date = context["Date"] || root["Date"], + SyntaxError = context["SyntaxError"] || root["SyntaxError"], + TypeError = context["TypeError"] || root["TypeError"], + Math = context["Math"] || root["Math"], + nativeJSON = context["JSON"] || root["JSON"]; + + // Delegate to the native `stringify` and `parse` implementations. + if (typeof nativeJSON == "object" && nativeJSON) { + exports.stringify = nativeJSON.stringify; + exports.parse = nativeJSON.parse; + } + + // Convenience aliases. + var objectProto = Object.prototype, + getClass = objectProto.toString, + isProperty, forEach, undef; + + // Test the `Date#getUTC*` methods. Based on work by @Yaffle. + var isExtended = new Date(-3509827334573292); + try { + // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical + // results for certain dates in Opera >= 10.53. + isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 && + // Safari < 2.0.2 stores the internal millisecond time value correctly, + // but clips the values returned by the date methods to the range of + // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]). + isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708; + } catch (exception) {} + + // Internal: Determines whether the native `JSON.stringify` and `parse` + // implementations are spec-compliant. Based on work by Ken Snyder. + function has(name) { + if (has[name] !== undef) { + // Return cached feature test result. + return has[name]; + } + var isSupported; + if (name == "bug-string-char-index") { + // IE <= 7 doesn't support accessing string characters using square + // bracket notation. IE 8 only supports this for primitives. + isSupported = "a"[0] != "a"; + } else if (name == "json") { + // Indicates whether both `JSON.stringify` and `JSON.parse` are + // supported. + isSupported = has("json-stringify") && has("json-parse"); + } else { + var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'; + // Test `JSON.stringify`. + if (name == "json-stringify") { + var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended; + if (stringifySupported) { + // A test function object with a custom `toJSON` method. + (value = function () { + return 1; + }).toJSON = value; + try { + stringifySupported = + // Firefox 3.1b1 and b2 serialize string, number, and boolean + // primitives as object literals. + stringify(0) === "0" && + // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object + // literals. + stringify(new Number()) === "0" && + stringify(new String()) == '""' && + // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or + // does not define a canonical JSON representation (this applies to + // objects with `toJSON` properties as well, *unless* they are nested + // within an object or array). + stringify(getClass) === undef && + // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and + // FF 3.1b3 pass this test. + stringify(undef) === undef && + // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s, + // respectively, if the value is omitted entirely. + stringify() === undef && + // FF 3.1b1, 2 throw an error if the given value is not a number, + // string, array, object, Boolean, or `null` literal. This applies to + // objects with custom `toJSON` methods as well, unless they are nested + // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON` + // methods entirely. + stringify(value) === "1" && + stringify([value]) == "[1]" && + // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of + // `"[null]"`. + stringify([undef]) == "[null]" && + // YUI 3.0.0b1 fails to serialize `null` literals. + stringify(null) == "null" && + // FF 3.1b1, 2 halts serialization if an array contains a function: + // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3 + // elides non-JSON values from objects and arrays, unless they + // define custom `toJSON` methods. + stringify([undef, getClass, null]) == "[null,null,null]" && + // Simple serialization test. FF 3.1b1 uses Unicode escape sequences + // where character escape codes are expected (e.g., `\b` => `\u0008`). + stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized && + // FF 3.1b1 and b2 ignore the `filter` and `width` arguments. + stringify(null, value) === "1" && + stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" && + // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly + // serialize extended years. + stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' && + // The milliseconds are optional in ES 5, but required in 5.1. + stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' && + // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative + // four-digit years instead of six-digit years. Credits: @Yaffle. + stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' && + // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond + // values less than 1000. Credits: @Yaffle. + stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"'; + } catch (exception) { + stringifySupported = false; + } + } + isSupported = stringifySupported; + } + // Test `JSON.parse`. + if (name == "json-parse") { + var parse = exports.parse; + if (typeof parse == "function") { + try { + // FF 3.1b1, b2 will throw an exception if a bare literal is provided. + // Conforming implementations should also coerce the initial argument to + // a string prior to parsing. + if (parse("0") === 0 && !parse(false)) { + // Simple parsing test. + value = parse(serialized); + var parseSupported = value["a"].length == 5 && value["a"][0] === 1; + if (parseSupported) { + try { + // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings. + parseSupported = !parse('"\t"'); + } catch (exception) {} + if (parseSupported) { + try { + // FF 4.0 and 4.0.1 allow leading `+` signs and leading + // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow + // certain octal literals. + parseSupported = parse("01") !== 1; + } catch (exception) {} + } + if (parseSupported) { + try { + // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal + // points. These environments, along with FF 3.1b1 and 2, + // also allow trailing commas in JSON objects and arrays. + parseSupported = parse("1.") !== 1; + } catch (exception) {} + } + } + } + } catch (exception) { + parseSupported = false; + } + } + isSupported = parseSupported; + } + } + return has[name] = !!isSupported; + } + + if (!has("json")) { + // Common `[[Class]]` name aliases. + var functionClass = "[object Function]", + dateClass = "[object Date]", + numberClass = "[object Number]", + stringClass = "[object String]", + arrayClass = "[object Array]", + booleanClass = "[object Boolean]"; + + // Detect incomplete support for accessing string characters by index. + var charIndexBuggy = has("bug-string-char-index"); + + // Define additional utility methods if the `Date` methods are buggy. + if (!isExtended) { + var floor = Math.floor; + // A mapping between the months of the year and the number of days between + // January 1st and the first of the respective month. + var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; + // Internal: Calculates the number of days between the Unix epoch and the + // first day of the given month. + var getDay = function (year, month) { + return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400); + }; + } + + // Internal: Determines if a property is a direct property of the given + // object. Delegates to the native `Object#hasOwnProperty` method. + if (!(isProperty = objectProto.hasOwnProperty)) { + isProperty = function (property) { + var members = {}, constructor; + if ((members.__proto__ = null, members.__proto__ = { + // The *proto* property cannot be set multiple times in recent + // versions of Firefox and SeaMonkey. + "toString": 1 + }, members).toString != getClass) { + // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but + // supports the mutable *proto* property. + isProperty = function (property) { + // Capture and break the object's prototype chain (see section 8.6.2 + // of the ES 5.1 spec). The parenthesized expression prevents an + // unsafe transformation by the Closure Compiler. + var original = this.__proto__, result = property in (this.__proto__ = null, this); + // Restore the original prototype chain. + this.__proto__ = original; + return result; + }; + } else { + // Capture a reference to the top-level `Object` constructor. + constructor = members.constructor; + // Use the `constructor` property to simulate `Object#hasOwnProperty` in + // other environments. + isProperty = function (property) { + var parent = (this.constructor || constructor).prototype; + return property in this && !(property in parent && this[property] === parent[property]); + }; + } + members = null; + return isProperty.call(this, property); + }; + } + + // Internal: Normalizes the `for...in` iteration algorithm across + // environments. Each enumerated key is yielded to a `callback` function. + forEach = function (object, callback) { + var size = 0, Properties, members, property; + + // Tests for bugs in the current environment's `for...in` algorithm. The + // `valueOf` property inherits the non-enumerable flag from + // `Object.prototype` in older versions of IE, Netscape, and Mozilla. + (Properties = function () { + this.valueOf = 0; + }).prototype.valueOf = 0; + + // Iterate over a new instance of the `Properties` class. + members = new Properties(); + for (property in members) { + // Ignore all properties inherited from `Object.prototype`. + if (isProperty.call(members, property)) { + size++; + } + } + Properties = members = null; + + // Normalize the iteration algorithm. + if (!size) { + // A list of non-enumerable properties inherited from `Object.prototype`. + members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"]; + // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable + // properties. + forEach = function (object, callback) { + var isFunction = getClass.call(object) == functionClass, property, length; + var hasProperty = !isFunction && typeof object.constructor != "function" && objectTypes[typeof object.hasOwnProperty] && object.hasOwnProperty || isProperty; + for (property in object) { + // Gecko <= 1.0 enumerates the `prototype` property of functions under + // certain conditions; IE does not. + if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) { + callback(property); + } + } + // Manually invoke the callback for each non-enumerable property. + for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property)); + }; + } else if (size == 2) { + // Safari <= 2.0.4 enumerates shadowed properties twice. + forEach = function (object, callback) { + // Create a set of iterated properties. + var members = {}, isFunction = getClass.call(object) == functionClass, property; + for (property in object) { + // Store each property name to prevent double enumeration. The + // `prototype` property of functions is not enumerated due to cross- + // environment inconsistencies. + if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) { + callback(property); + } + } + }; + } else { + // No bugs detected; use the standard `for...in` algorithm. + forEach = function (object, callback) { + var isFunction = getClass.call(object) == functionClass, property, isConstructor; + for (property in object) { + if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) { + callback(property); + } + } + // Manually invoke the callback for the `constructor` property due to + // cross-environment inconsistencies. + if (isConstructor || isProperty.call(object, (property = "constructor"))) { + callback(property); + } + }; + } + return forEach(object, callback); + }; + + // Public: Serializes a JavaScript `value` as a JSON string. The optional + // `filter` argument may specify either a function that alters how object and + // array members are serialized, or an array of strings and numbers that + // indicates which properties should be serialized. The optional `width` + // argument may be either a string or number that specifies the indentation + // level of the output. + if (!has("json-stringify")) { + // Internal: A map of control characters and their escaped equivalents. + var Escapes = { + 92: "\\\\", + 34: '\\"', + 8: "\\b", + 12: "\\f", + 10: "\\n", + 13: "\\r", + 9: "\\t" + }; + + // Internal: Converts `value` into a zero-padded string such that its + // length is at least equal to `width`. The `width` must be <= 6. + var leadingZeroes = "000000"; + var toPaddedString = function (width, value) { + // The `|| 0` expression is necessary to work around a bug in + // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`. + return (leadingZeroes + (value || 0)).slice(-width); + }; + + // Internal: Double-quotes a string `value`, replacing all ASCII control + // characters (characters with code unit values between 0 and 31) with + // their escaped equivalents. This is an implementation of the + // `Quote(value)` operation defined in ES 5.1 section 15.12.3. + var unicodePrefix = "\\u00"; + var quote = function (value) { + var result = '"', index = 0, length = value.length, useCharIndex = !charIndexBuggy || length > 10; + var symbols = useCharIndex && (charIndexBuggy ? value.split("") : value); + for (; index < length; index++) { + var charCode = value.charCodeAt(index); + // If the character is a control character, append its Unicode or + // shorthand escape sequence; otherwise, append the character as-is. + switch (charCode) { + case 8: case 9: case 10: case 12: case 13: case 34: case 92: + result += Escapes[charCode]; + break; + default: + if (charCode < 32) { + result += unicodePrefix + toPaddedString(2, charCode.toString(16)); + break; + } + result += useCharIndex ? symbols[index] : value.charAt(index); + } + } + return result + '"'; + }; + + // Internal: Recursively serializes an object. Implements the + // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations. + var serialize = function (property, object, callback, properties, whitespace, indentation, stack) { + var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result; + try { + // Necessary for host object support. + value = object[property]; + } catch (exception) {} + if (typeof value == "object" && value) { + className = getClass.call(value); + if (className == dateClass && !isProperty.call(value, "toJSON")) { + if (value > -1 / 0 && value < 1 / 0) { + // Dates are serialized according to the `Date#toJSON` method + // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15 + // for the ISO 8601 date time string format. + if (getDay) { + // Manually compute the year, month, date, hours, minutes, + // seconds, and milliseconds if the `getUTC*` methods are + // buggy. Adapted from @Yaffle's `date-shim` project. + date = floor(value / 864e5); + for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++); + for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++); + date = 1 + date - getDay(year, month); + // The `time` value specifies the time within the day (see ES + // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used + // to compute `A modulo B`, as the `%` operator does not + // correspond to the `modulo` operation for negative numbers. + time = (value % 864e5 + 864e5) % 864e5; + // The hours, minutes, seconds, and milliseconds are obtained by + // decomposing the time within the day. See section 15.9.1.10. + hours = floor(time / 36e5) % 24; + minutes = floor(time / 6e4) % 60; + seconds = floor(time / 1e3) % 60; + milliseconds = time % 1e3; + } else { + year = value.getUTCFullYear(); + month = value.getUTCMonth(); + date = value.getUTCDate(); + hours = value.getUTCHours(); + minutes = value.getUTCMinutes(); + seconds = value.getUTCSeconds(); + milliseconds = value.getUTCMilliseconds(); + } + // Serialize extended years correctly. + value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) + + "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) + + // Months, dates, hours, minutes, and seconds should have two + // digits; milliseconds should have three. + "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) + + // Milliseconds are optional in ES 5.0, but required in 5.1. + "." + toPaddedString(3, milliseconds) + "Z"; + } else { + value = null; + } + } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) { + // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the + // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3 + // ignores all `toJSON` methods on these objects unless they are + // defined directly on an instance. + value = value.toJSON(property); + } + } + if (callback) { + // If a replacement function was provided, call it to obtain the value + // for serialization. + value = callback.call(object, property, value); + } + if (value === null) { + return "null"; + } + className = getClass.call(value); + if (className == booleanClass) { + // Booleans are represented literally. + return "" + value; + } else if (className == numberClass) { + // JSON numbers must be finite. `Infinity` and `NaN` are serialized as + // `"null"`. + return value > -1 / 0 && value < 1 / 0 ? "" + value : "null"; + } else if (className == stringClass) { + // Strings are double-quoted and escaped. + return quote("" + value); + } + // Recursively serialize objects and arrays. + if (typeof value == "object") { + // Check for cyclic structures. This is a linear search; performance + // is inversely proportional to the number of unique nested objects. + for (length = stack.length; length--;) { + if (stack[length] === value) { + // Cyclic structures cannot be serialized by `JSON.stringify`. + throw TypeError(); + } + } + // Add the object to the stack of traversed objects. + stack.push(value); + results = []; + // Save the current indentation level and indent one additional level. + prefix = indentation; + indentation += whitespace; + if (className == arrayClass) { + // Recursively serialize array elements. + for (index = 0, length = value.length; index < length; index++) { + element = serialize(index, value, callback, properties, whitespace, indentation, stack); + results.push(element === undef ? "null" : element); + } + result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]"; + } else { + // Recursively serialize object members. Members are selected from + // either a user-specified list of property names, or the object + // itself. + forEach(properties || value, function (property) { + var element = serialize(property, value, callback, properties, whitespace, indentation, stack); + if (element !== undef) { + // According to ES 5.1 section 15.12.3: "If `gap` {whitespace} + // is not the empty string, let `member` {quote(property) + ":"} + // be the concatenation of `member` and the `space` character." + // The "`space` character" refers to the literal space + // character, not the `space` {width} argument provided to + // `JSON.stringify`. + results.push(quote(property) + ":" + (whitespace ? " " : "") + element); + } + }); + result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}"; + } + // Remove the object from the traversed object stack. + stack.pop(); + return result; + } + }; + + // Public: `JSON.stringify`. See ES 5.1 section 15.12.3. + exports.stringify = function (source, filter, width) { + var whitespace, callback, properties, className; + if (objectTypes[typeof filter] && filter) { + if ((className = getClass.call(filter)) == functionClass) { + callback = filter; + } else if (className == arrayClass) { + // Convert the property names array into a makeshift set. + properties = {}; + for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1)); + } + } + if (width) { + if ((className = getClass.call(width)) == numberClass) { + // Convert the `width` to an integer and create a string containing + // `width` number of space characters. + if ((width -= width % 1) > 0) { + for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " "); + } + } else if (className == stringClass) { + whitespace = width.length <= 10 ? width : width.slice(0, 10); + } + } + // Opera <= 7.54u2 discards the values associated with empty string keys + // (`""`) only if they are used directly within an object member list + // (e.g., `!("" in { "": 1})`). + return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []); + }; + } + + // Public: Parses a JSON source string. + if (!has("json-parse")) { + var fromCharCode = String.fromCharCode; + + // Internal: A map of escaped control characters and their unescaped + // equivalents. + var Unescapes = { + 92: "\\", + 34: '"', + 47: "/", + 98: "\b", + 116: "\t", + 110: "\n", + 102: "\f", + 114: "\r" + }; + + // Internal: Stores the parser state. + var Index, Source; + + // Internal: Resets the parser state and throws a `SyntaxError`. + var abort = function () { + Index = Source = null; + throw SyntaxError(); + }; + + // Internal: Returns the next token, or `"$"` if the parser has reached + // the end of the source string. A token may be a string, number, `null` + // literal, or Boolean literal. + var lex = function () { + var source = Source, length = source.length, value, begin, position, isSigned, charCode; + while (Index < length) { + charCode = source.charCodeAt(Index); + switch (charCode) { + case 9: case 10: case 13: case 32: + // Skip whitespace tokens, including tabs, carriage returns, line + // feeds, and space characters. + Index++; + break; + case 123: case 125: case 91: case 93: case 58: case 44: + // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at + // the current position. + value = charIndexBuggy ? source.charAt(Index) : source[Index]; + Index++; + return value; + case 34: + // `"` delimits a JSON string; advance to the next character and + // begin parsing the string. String tokens are prefixed with the + // sentinel `@` character to distinguish them from punctuators and + // end-of-string tokens. + for (value = "@", Index++; Index < length;) { + charCode = source.charCodeAt(Index); + if (charCode < 32) { + // Unescaped ASCII control characters (those with a code unit + // less than the space character) are not permitted. + abort(); + } else if (charCode == 92) { + // A reverse solidus (`\`) marks the beginning of an escaped + // control character (including `"`, `\`, and `/`) or Unicode + // escape sequence. + charCode = source.charCodeAt(++Index); + switch (charCode) { + case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114: + // Revive escaped control characters. + value += Unescapes[charCode]; + Index++; + break; + case 117: + // `\u` marks the beginning of a Unicode escape sequence. + // Advance to the first character and validate the + // four-digit code point. + begin = ++Index; + for (position = Index + 4; Index < position; Index++) { + charCode = source.charCodeAt(Index); + // A valid sequence comprises four hexdigits (case- + // insensitive) that form a single hexadecimal value. + if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) { + // Invalid Unicode escape sequence. + abort(); + } + } + // Revive the escaped character. + value += fromCharCode("0x" + source.slice(begin, Index)); + break; + default: + // Invalid escape sequence. + abort(); + } + } else { + if (charCode == 34) { + // An unescaped double-quote character marks the end of the + // string. + break; + } + charCode = source.charCodeAt(Index); + begin = Index; + // Optimize for the common case where a string is valid. + while (charCode >= 32 && charCode != 92 && charCode != 34) { + charCode = source.charCodeAt(++Index); + } + // Append the string as-is. + value += source.slice(begin, Index); + } + } + if (source.charCodeAt(Index) == 34) { + // Advance to the next character and return the revived string. + Index++; + return value; + } + // Unterminated string. + abort(); + default: + // Parse numbers and literals. + begin = Index; + // Advance past the negative sign, if one is specified. + if (charCode == 45) { + isSigned = true; + charCode = source.charCodeAt(++Index); + } + // Parse an integer or floating-point value. + if (charCode >= 48 && charCode <= 57) { + // Leading zeroes are interpreted as octal literals. + if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) { + // Illegal octal literal. + abort(); + } + isSigned = false; + // Parse the integer component. + for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++); + // Floats cannot contain a leading decimal point; however, this + // case is already accounted for by the parser. + if (source.charCodeAt(Index) == 46) { + position = ++Index; + // Parse the decimal component. + for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); + if (position == Index) { + // Illegal trailing decimal. + abort(); + } + Index = position; + } + // Parse exponents. The `e` denoting the exponent is + // case-insensitive. + charCode = source.charCodeAt(Index); + if (charCode == 101 || charCode == 69) { + charCode = source.charCodeAt(++Index); + // Skip past the sign following the exponent, if one is + // specified. + if (charCode == 43 || charCode == 45) { + Index++; + } + // Parse the exponential component. + for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); + if (position == Index) { + // Illegal empty exponent. + abort(); + } + Index = position; + } + // Coerce the parsed value to a JavaScript number. + return +source.slice(begin, Index); + } + // A negative sign may only precede numbers. + if (isSigned) { + abort(); + } + // `true`, `false`, and `null` literals. + if (source.slice(Index, Index + 4) == "true") { + Index += 4; + return true; + } else if (source.slice(Index, Index + 5) == "false") { + Index += 5; + return false; + } else if (source.slice(Index, Index + 4) == "null") { + Index += 4; + return null; + } + // Unrecognized token. + abort(); + } + } + // Return the sentinel `$` character if the parser has reached the end + // of the source string. + return "$"; + }; + + // Internal: Parses a JSON `value` token. + var get = function (value) { + var results, hasMembers; + if (value == "$") { + // Unexpected end of input. + abort(); + } + if (typeof value == "string") { + if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") { + // Remove the sentinel `@` character. + return value.slice(1); + } + // Parse object and array literals. + if (value == "[") { + // Parses a JSON array, returning a new JavaScript array. + results = []; + for (;; hasMembers || (hasMembers = true)) { + value = lex(); + // A closing square bracket marks the end of the array literal. + if (value == "]") { + break; + } + // If the array literal contains elements, the current token + // should be a comma separating the previous element from the + // next. + if (hasMembers) { + if (value == ",") { + value = lex(); + if (value == "]") { + // Unexpected trailing `,` in array literal. + abort(); + } + } else { + // A `,` must separate each array element. + abort(); + } + } + // Elisions and leading commas are not permitted. + if (value == ",") { + abort(); + } + results.push(get(value)); + } + return results; + } else if (value == "{") { + // Parses a JSON object, returning a new JavaScript object. + results = {}; + for (;; hasMembers || (hasMembers = true)) { + value = lex(); + // A closing curly brace marks the end of the object literal. + if (value == "}") { + break; + } + // If the object literal contains members, the current token + // should be a comma separator. + if (hasMembers) { + if (value == ",") { + value = lex(); + if (value == "}") { + // Unexpected trailing `,` in object literal. + abort(); + } + } else { + // A `,` must separate each object member. + abort(); + } + } + // Leading commas are not permitted, object property names must be + // double-quoted strings, and a `:` must separate each property + // name and value. + if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") { + abort(); + } + results[value.slice(1)] = get(lex()); + } + return results; + } + // Unexpected token encountered. + abort(); + } + return value; + }; + + // Internal: Updates a traversed object member. + var update = function (source, property, callback) { + var element = walk(source, property, callback); + if (element === undef) { + delete source[property]; + } else { + source[property] = element; + } + }; + + // Internal: Recursively traverses a parsed JSON object, invoking the + // `callback` function for each value. This is an implementation of the + // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2. + var walk = function (source, property, callback) { + var value = source[property], length; + if (typeof value == "object" && value) { + // `forEach` can't be used to traverse an array in Opera <= 8.54 + // because its `Object#hasOwnProperty` implementation returns `false` + // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`). + if (getClass.call(value) == arrayClass) { + for (length = value.length; length--;) { + update(value, length, callback); + } + } else { + forEach(value, function (property) { + update(value, property, callback); + }); + } + } + return callback.call(source, property, value); + }; + + // Public: `JSON.parse`. See ES 5.1 section 15.12.2. + exports.parse = function (source, callback) { + var result, value; + Index = 0; + Source = "" + source; + result = get(lex()); + // If a JSON string contains multiple tokens, it is invalid. + if (lex() != "$") { + abort(); + } + // Reset the parser state. + Index = Source = null; + return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result; + }; + } + } + + exports["runInContext"] = runInContext; + return exports; + } + + if (freeExports && !isLoader) { + // Export for CommonJS environments. + runInContext(root, freeExports); + } else { + // Export for web browsers and JavaScript engines. + var nativeJSON = root.JSON, + previousJSON = root["JSON3"], + isRestored = false; + + var JSON3 = runInContext(root, (root["JSON3"] = { + // Public: Restores the original value of the global `JSON` object and + // returns a reference to the `JSON3` object. + "noConflict": function () { + if (!isRestored) { + isRestored = true; + root.JSON = nativeJSON; + root["JSON3"] = previousJSON; + nativeJSON = previousJSON = null; + } + return JSON3; + } + })); + + root.JSON = { + "parse": JSON3.parse, + "stringify": JSON3.stringify + }; + } + + // Export for asynchronous module loaders. + if (isLoader) { + define(function () { + return JSON3; + }); + } +}).call(this); diff --git a/src/preloadjs/version.js b/src/preloadjs/version.js index 83a3bb71..93bc8779 100644 --- a/src/preloadjs/version.js +++ b/src/preloadjs/version.js @@ -1,14 +1,10 @@ -this.createjs = this.createjs||{}; +this.createjs = this.createjs || {}; -(function() { +(function () { "use strict"; /** - * Static class holding library specific information such as the version and buildDate of - * the library. - * - * The old PreloadJS class has been renamed to LoadQueue. Please see the {{#crossLink "LoadQueue"}}{{/crossLink}} - * class for information on loading files. + * Static class holding library specific information such as the version and buildDate of the library. * @class PreloadJS **/ var s = createjs.PreloadJS = createjs.PreloadJS || {}; @@ -16,17 +12,17 @@ this.createjs = this.createjs||{}; /** * The version string for this release. * @property version - * @type String + * @type {String} * @static **/ - s.version = /*version*/"NEXT"; // injected by build process + s.version = /*=version*/""; // injected by build process /** * The build date for this release in UTC format. * @property buildDate - * @type String + * @type {String} * @static **/ - s.buildDate = /*date*/"Wed, 02 Apr 2014 17:54:19 GMT"; // injected by build process + s.buildDate = /*=date*/""; // injected by build process })(); diff --git a/tests/Gruntfile.js b/tests/Gruntfile.js new file mode 100644 index 00000000..5d120b52 --- /dev/null +++ b/tests/Gruntfile.js @@ -0,0 +1,94 @@ +var url = require('url'); + +module.exports = function (grunt) { + grunt.initConfig( + { + pkg: grunt.file.readJSON('package.json'), + + jasmine: { + run: { + src: [ + '../lib/preloadjs-NEXT.js' + ], + + options: { + specs: 'spec/*Spec.js', + helpers: [ + 'spec/Helpers.js' + ], + vendor: [ + '../_assets/libs/easeljs-NEXT.min.js' + ], + host: 'http://127.0.0.1:<%=connect.serve.options.port%>/' + } + } + }, + + connect: { + serve: { + options: { + keepalive: true, + base: [ + { + path: __dirname, + options: { + index: '_SpecRunner.html' + } + }, '..', '../_assets/', '../lib/', './' + ], + useAvailablePort: true, + port: 8000, + open: true, + // Used to test the POST / GET functionality, it just echo's back what data was sent. + middleware: function (connect, options, middlewares) { + middlewares.unshift(function (req, res, next) { + if (req.method == "POST") { + res.end(JSON.stringify(req.body)); + } else if(req.method == "GET") { + var url_parts = url.parse(req.originalUrl, true); + if (url_parts.query.foo != null) { + res.end(JSON.stringify(url_parts.query)); + } else { + next(); + } + } else { + next(); + } + }); + + var bodyParser = require('body-parser') + middlewares.unshift(bodyParser.json()); + middlewares.unshift(bodyParser.urlencoded({extended: false})); + + return middlewares; + }, + } + } + }, + + listips: { + run: { + options: { + label: "Normal" + } + } + } + } + ); + + grunt.registerTask('configureConnectHeadless', function () { + grunt.config('connect.serve.options.keepalive', false); + grunt.config('connect.serve.options.open', false); + }); + + // Load all the tasks we need + grunt.loadNpmTasks('grunt-contrib-jasmine'); + grunt.loadNpmTasks('grunt-contrib-connect'); + grunt.loadTasks('tasks/'); + + grunt.registerTask("default", "Launches browser-based tests", "serve"); + grunt.registerTask("serve", "Launches browser-based tests", ["jasmine:run:build", "listips", "connect"]); + + grunt.registerTask("headless", "phantom"); + grunt.registerTask("phantom", "Launches phantom-based tests", ["configureConnectHeadless", "connect", "jasmine"]); +}; diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..eb00b38e --- /dev/null +++ b/tests/README.md @@ -0,0 +1,6 @@ +## Setup and run tests ## +* Run via Grunt + * Install dependencies; npm install; + * Run tests in browser: grunt; + * Run headless: grunt jasmine; + diff --git a/tests/lib/jasmine-2.0.2/MIT.LICENSE b/tests/lib/jasmine-2.0.2/MIT.LICENSE new file mode 100644 index 00000000..aff8ed47 --- /dev/null +++ b/tests/lib/jasmine-2.0.2/MIT.LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008-2014 Pivotal Labs + +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. diff --git a/tests/lib/jasmine-2.0.2/boot.js b/tests/lib/jasmine-2.0.2/boot.js new file mode 100755 index 00000000..406145ef --- /dev/null +++ b/tests/lib/jasmine-2.0.2/boot.js @@ -0,0 +1,120 @@ +/** + Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. + + If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms. + + The location of `boot.js` can be specified and/or overridden in `jasmine.yml`. + + [jasmine-gem]: http://github.com/pivotal/jasmine-gem + */ + +(function() { + + /** + * ## Require & Instantiate + * + * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. + */ + window.jasmine = jasmineRequire.core(jasmineRequire); + + /** + * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. + */ + jasmineRequire.html(jasmine); + + /** + * Create the Jasmine environment. This is used to run all specs in a project. + */ + var env = jasmine.getEnv(); + + /** + * ## The Global Interface + * + * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. + */ + var jasmineInterface = jasmineRequire.interface(jasmine, env); + + /** + * Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. + */ + if (typeof window == "undefined" && typeof exports == "object") { + extend(exports, jasmineInterface); + } else { + extend(window, jasmineInterface); + } + + /** + * ## Runner Parameters + * + * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface. + */ + + var queryString = new jasmine.QueryString({ + getWindowLocation: function() { return window.location; } + }); + + var catchingExceptions = queryString.getParam("catch"); + env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); + + /** + * ## Reporters + * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any). + */ + var htmlReporter = new jasmine.HtmlReporter({ + env: env, + onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); }, + getContainer: function() { return document.body; }, + createElement: function() { return document.createElement.apply(document, arguments); }, + createTextNode: function() { return document.createTextNode.apply(document, arguments); }, + timer: new jasmine.Timer() + }); + + /** + * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript. + */ + env.addReporter(jasmineInterface.jsApiReporter); + env.addReporter(htmlReporter); + + /** + * Filter which specs will be run by matching the start of the full name against the `spec` query param. + */ + var specFilter = new jasmine.HtmlSpecFilter({ + filterString: function() { return queryString.getParam("spec"); } + }); + + env.specFilter = function(spec) { + return specFilter.matches(spec.getFullName()); + }; + + /** + * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack. + */ + window.setTimeout = window.setTimeout; + window.setInterval = window.setInterval; + window.clearTimeout = window.clearTimeout; + window.clearInterval = window.clearInterval; + + /** + * ## Execution + * + * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. + */ + var currentWindowOnload = window.onload; + + window.onload = function() { + if (currentWindowOnload) { + currentWindowOnload(); + } + htmlReporter.initialize(); + env.execute(); + }; + + /** + * Helper function for readability above. + */ + function extend(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; + } + +}()); diff --git a/tests/lib/jasmine-2.0.2/console.js b/tests/lib/jasmine-2.0.2/console.js new file mode 100755 index 00000000..78b56150 --- /dev/null +++ b/tests/lib/jasmine-2.0.2/console.js @@ -0,0 +1,166 @@ +/* +Copyright (c) 2008-2014 Pivotal Labs + +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. +*/ +function getJasmineRequireObj() { + if (typeof module !== 'undefined' && module.exports) { + return exports; + } else { + window.jasmineRequire = window.jasmineRequire || {}; + return window.jasmineRequire; + } +} + +getJasmineRequireObj().console = function(jRequire, j$) { + j$.ConsoleReporter = jRequire.ConsoleReporter(); +}; + +getJasmineRequireObj().ConsoleReporter = function() { + + var noopTimer = { + start: function(){}, + elapsed: function(){ return 0; } + }; + + function ConsoleReporter(options) { + var print = options.print, + showColors = options.showColors || false, + onComplete = options.onComplete || function() {}, + timer = options.timer || noopTimer, + specCount, + failureCount, + failedSpecs = [], + pendingCount, + ansi = { + green: '\x1B[32m', + red: '\x1B[31m', + yellow: '\x1B[33m', + none: '\x1B[0m' + }; + + this.jasmineStarted = function() { + specCount = 0; + failureCount = 0; + pendingCount = 0; + print('Started'); + printNewline(); + timer.start(); + }; + + this.jasmineDone = function() { + printNewline(); + for (var i = 0; i < failedSpecs.length; i++) { + specFailureDetails(failedSpecs[i]); + } + + if(specCount > 0) { + printNewline(); + + var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' + + failureCount + ' ' + plural('failure', failureCount); + + if (pendingCount) { + specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount); + } + + print(specCounts); + } else { + print('No specs found'); + } + + printNewline(); + var seconds = timer.elapsed() / 1000; + print('Finished in ' + seconds + ' ' + plural('second', seconds)); + + printNewline(); + + onComplete(failureCount === 0); + }; + + this.specDone = function(result) { + specCount++; + + if (result.status == 'pending') { + pendingCount++; + print(colored('yellow', '*')); + return; + } + + if (result.status == 'passed') { + print(colored('green', '.')); + return; + } + + if (result.status == 'failed') { + failureCount++; + failedSpecs.push(result); + print(colored('red', 'F')); + } + }; + + return this; + + function printNewline() { + print('\n'); + } + + function colored(color, str) { + return showColors ? (ansi[color] + str + ansi.none) : str; + } + + function plural(str, count) { + return count == 1 ? str : str + 's'; + } + + function repeat(thing, times) { + var arr = []; + for (var i = 0; i < times; i++) { + arr.push(thing); + } + return arr; + } + + function indent(str, spaces) { + var lines = (str || '').split('\n'); + var newArr = []; + for (var i = 0; i < lines.length; i++) { + newArr.push(repeat(' ', spaces).join('') + lines[i]); + } + return newArr.join('\n'); + } + + function specFailureDetails(result) { + printNewline(); + print(result.fullName); + + for (var i = 0; i < result.failedExpectations.length; i++) { + var failedExpectation = result.failedExpectations[i]; + printNewline(); + print(indent(failedExpectation.message, 2)); + print(indent(failedExpectation.stack, 2)); + } + + printNewline(); + } + } + + return ConsoleReporter; +}; diff --git a/tests/lib/jasmine-2.0.2/jasmine-html.js b/tests/lib/jasmine-2.0.2/jasmine-html.js new file mode 100755 index 00000000..9d959032 --- /dev/null +++ b/tests/lib/jasmine-2.0.2/jasmine-html.js @@ -0,0 +1,390 @@ +/* +Copyright (c) 2008-2014 Pivotal Labs + +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. +*/ +jasmineRequire.html = function(j$) { + j$.ResultsNode = jasmineRequire.ResultsNode(); + j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); + j$.QueryString = jasmineRequire.QueryString(); + j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); +}; + +jasmineRequire.HtmlReporter = function(j$) { + + var noopTimer = { + start: function() {}, + elapsed: function() { return 0; } + }; + + function HtmlReporter(options) { + var env = options.env || {}, + getContainer = options.getContainer, + createElement = options.createElement, + createTextNode = options.createTextNode, + onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {}, + timer = options.timer || noopTimer, + results = [], + specsExecuted = 0, + failureCount = 0, + pendingSpecCount = 0, + htmlReporterMain, + symbols; + + this.initialize = function() { + clearPrior(); + htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'}, + createDom('div', {className: 'banner'}, + createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}), + createDom('span', {className: 'version'}, j$.version) + ), + createDom('ul', {className: 'symbol-summary'}), + createDom('div', {className: 'alert'}), + createDom('div', {className: 'results'}, + createDom('div', {className: 'failures'}) + ) + ); + getContainer().appendChild(htmlReporterMain); + + symbols = find('.symbol-summary'); + }; + + var totalSpecsDefined; + this.jasmineStarted = function(options) { + totalSpecsDefined = options.totalSpecsDefined || 0; + timer.start(); + }; + + var summary = createDom('div', {className: 'summary'}); + + var topResults = new j$.ResultsNode({}, '', null), + currentParent = topResults; + + this.suiteStarted = function(result) { + currentParent.addChild(result, 'suite'); + currentParent = currentParent.last(); + }; + + this.suiteDone = function(result) { + if (currentParent == topResults) { + return; + } + + currentParent = currentParent.parent; + }; + + this.specStarted = function(result) { + currentParent.addChild(result, 'spec'); + }; + + var failures = []; + this.specDone = function(result) { + if(noExpectations(result) && console && console.error) { + console.error('Spec \'' + result.fullName + '\' has no expectations.'); + } + + if (result.status != 'disabled') { + specsExecuted++; + } + + symbols.appendChild(createDom('li', { + className: noExpectations(result) ? 'empty' : result.status, + id: 'spec_' + result.id, + title: result.fullName + } + )); + + if (result.status == 'failed') { + failureCount++; + + var failure = + createDom('div', {className: 'spec-detail failed'}, + createDom('div', {className: 'description'}, + createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) + ), + createDom('div', {className: 'messages'}) + ); + var messages = failure.childNodes[1]; + + for (var i = 0; i < result.failedExpectations.length; i++) { + var expectation = result.failedExpectations[i]; + messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message)); + messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack)); + } + + failures.push(failure); + } + + if (result.status == 'pending') { + pendingSpecCount++; + } + }; + + this.jasmineDone = function() { + var banner = find('.banner'); + banner.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); + + var alert = find('.alert'); + + alert.appendChild(createDom('span', { className: 'exceptions' }, + createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions'), + createDom('input', { + className: 'raise', + id: 'raise-exceptions', + type: 'checkbox' + }) + )); + var checkbox = find('#raise-exceptions'); + + checkbox.checked = !env.catchingExceptions(); + checkbox.onclick = onRaiseExceptionsClick; + + if (specsExecuted < totalSpecsDefined) { + var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; + alert.appendChild( + createDom('span', {className: 'bar skipped'}, + createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage) + ) + ); + } + var statusBarMessage = ''; + var statusBarClassName = 'bar '; + + if (totalSpecsDefined > 0) { + statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); + if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } + statusBarClassName += (failureCount > 0) ? 'failed' : 'passed'; + } else { + statusBarClassName += 'skipped'; + statusBarMessage += 'No specs found'; + } + + alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage)); + + var results = find('.results'); + results.appendChild(summary); + + summaryList(topResults, summary); + + function summaryList(resultsTree, domParent) { + var specListNode; + for (var i = 0; i < resultsTree.children.length; i++) { + var resultNode = resultsTree.children[i]; + if (resultNode.type == 'suite') { + var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id}, + createDom('li', {className: 'suite-detail'}, + createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) + ) + ); + + summaryList(resultNode, suiteListNode); + domParent.appendChild(suiteListNode); + } + if (resultNode.type == 'spec') { + if (domParent.getAttribute('class') != 'specs') { + specListNode = createDom('ul', {className: 'specs'}); + domParent.appendChild(specListNode); + } + var specDescription = resultNode.result.description; + if(noExpectations(resultNode.result)) { + specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; + } + specListNode.appendChild( + createDom('li', { + className: resultNode.result.status, + id: 'spec-' + resultNode.result.id + }, + createDom('a', {href: specHref(resultNode.result)}, specDescription) + ) + ); + } + } + } + + if (failures.length) { + alert.appendChild( + createDom('span', {className: 'menu bar spec-list'}, + createDom('span', {}, 'Spec List | '), + createDom('a', {className: 'failures-menu', href: '#'}, 'Failures'))); + alert.appendChild( + createDom('span', {className: 'menu bar failure-list'}, + createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'), + createDom('span', {}, ' | Failures '))); + + find('.failures-menu').onclick = function() { + setMenuModeTo('failure-list'); + }; + find('.spec-list-menu').onclick = function() { + setMenuModeTo('spec-list'); + }; + + setMenuModeTo('failure-list'); + + var failureNode = find('.failures'); + for (var i = 0; i < failures.length; i++) { + failureNode.appendChild(failures[i]); + } + } + }; + + return this; + + function find(selector) { + return getContainer().querySelector('.jasmine_html-reporter ' + selector); + } + + function clearPrior() { + // return the reporter + var oldReporter = find(''); + + if(oldReporter) { + getContainer().removeChild(oldReporter); + } + } + + function createDom(type, attrs, childrenVarArgs) { + var el = createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(createTextNode(child)); + } else { + if (child) { + el.appendChild(child); + } + } + } + + for (var attr in attrs) { + if (attr == 'className') { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; + } + + function pluralize(singular, count) { + var word = (count == 1 ? singular : singular + 's'); + + return '' + count + ' ' + word; + } + + function specHref(result) { + return '?spec=' + encodeURIComponent(result.fullName); + } + + function setMenuModeTo(mode) { + htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode); + } + + function noExpectations(result) { + return (result.failedExpectations.length + result.passedExpectations.length) === 0 && + result.status === 'passed'; + } + } + + return HtmlReporter; +}; + +jasmineRequire.HtmlSpecFilter = function() { + function HtmlSpecFilter(options) { + var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); + var filterPattern = new RegExp(filterString); + + this.matches = function(specName) { + return filterPattern.test(specName); + }; + } + + return HtmlSpecFilter; +}; + +jasmineRequire.ResultsNode = function() { + function ResultsNode(result, type, parent) { + this.result = result; + this.type = type; + this.parent = parent; + + this.children = []; + + this.addChild = function(result, type) { + this.children.push(new ResultsNode(result, type, this)); + }; + + this.last = function() { + return this.children[this.children.length - 1]; + }; + } + + return ResultsNode; +}; + +jasmineRequire.QueryString = function() { + function QueryString(options) { + + this.setParam = function(key, value) { + var paramMap = queryStringToParamMap(); + paramMap[key] = value; + options.getWindowLocation().search = toQueryString(paramMap); + }; + + this.getParam = function(key) { + return queryStringToParamMap()[key]; + }; + + return this; + + function toQueryString(paramMap) { + var qStrPairs = []; + for (var prop in paramMap) { + qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); + } + return '?' + qStrPairs.join('&'); + } + + function queryStringToParamMap() { + var paramStr = options.getWindowLocation().search.substring(1), + params = [], + paramMap = {}; + + if (paramStr.length > 0) { + params = paramStr.split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + var value = decodeURIComponent(p[1]); + if (value === 'true' || value === 'false') { + value = JSON.parse(value); + } + paramMap[decodeURIComponent(p[0])] = value; + } + } + + return paramMap; + } + + } + + return QueryString; +}; diff --git a/tests/lib/jasmine-2.0.2/jasmine.css b/tests/lib/jasmine-2.0.2/jasmine.css new file mode 100755 index 00000000..fb2afd13 --- /dev/null +++ b/tests/lib/jasmine-2.0.2/jasmine.css @@ -0,0 +1,61 @@ +body { overflow-y: scroll; } + +.jasmine_html-reporter { background-color: #eeeeee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } +.jasmine_html-reporter a { text-decoration: none; } +.jasmine_html-reporter a:hover { text-decoration: underline; } +.jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; } +.jasmine_html-reporter .banner, .jasmine_html-reporter .symbol-summary, .jasmine_html-reporter .summary, .jasmine_html-reporter .result-message, .jasmine_html-reporter .spec .description, .jasmine_html-reporter .spec-detail .description, .jasmine_html-reporter .alert .bar, .jasmine_html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; } +.jasmine_html-reporter .banner { position: relative; } +.jasmine_html-reporter .banner .title { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAZCAMAAACGusnyAAACdlBMVEX/////AP+AgICqVaqAQICZM5mAVYCSSZKAQICOOY6ATYCLRouAQICJO4mSSYCIRIiPQICHPIeOR4CGQ4aMQICGPYaLRoCFQ4WKQICPPYWJRYCOQoSJQICNPoSIRICMQoSHQICHRICKQoOHQICKPoOJO4OJQYOMQICMQ4CIQYKLQICIPoKLQ4CKQICNPoKJQISMQ4KJQoSLQYKJQISLQ4KIQoSKQYKIQICIQISMQoSKQYKLQIOLQoOJQYGLQIOKQIOMQoGKQYOLQYGKQIOLQoGJQYOJQIOKQYGJQIOKQoGKQIGLQIKLQ4KKQoGLQYKJQIGKQYKJQIGKQIKJQoGKQYKLQIGKQYKLQIOJQoKKQoOJQYKKQIOJQoKKQoOKQIOLQoKKQYOLQYKJQIOKQoKKQYKKQoKJQYOKQYKLQIOKQoKLQYOKQYKLQIOJQoGKQYKJQYGJQoGKQYKLQoGLQYGKQoGJQYKKQYGJQIKKQoGJQYKLQIKKQYGLQYKKQYGKQYGKQYKJQYOKQoKJQYOKQYKLQYOLQYOKQYKLQYOKQoKKQYKKQYOKQYOJQYKKQYKLQYKKQIKKQoKKQYKKQYKKQoKJQIKKQYKLQYKKQYKKQIKKQYKKQYKKQYKKQIKKQYKJQYGLQYGKQYKKQYKKQYGKQIKKQYGKQYOJQoKKQYOLQYKKQYOKQoKKQYKKQoKKQYKKQYKJQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKJQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKmIDpEAAAA0XRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAiIyQlJycoKissLS4wMTQ1Njc4OTo7PDw+P0BCQ0RISUpLTE1OUFNUVVdYWFlaW15fYGFiY2ZnaGlqa2xtb3BxcnN0dnh5ent8fX5/gIGChIWIioyNjo+QkZOUlZaYmZqbnJ2eoKGio6WmqKmsra6vsLGztre4ubq7vL2+wMHDxMjJysvNzs/Q0dLU1tfY2dvc3t/g4eLj5ebn6Onq6+zt7u/w8vP09fb3+Pn6+/z9/vkVQXAAAAMaSURBVHhe5dXxV1N1GMfxz2ABbDgIAm5VDJOyVDIJLUMaVpBWUZUaGbmqoGpZRSiGiRWp6KoZ5AB0ZY50RImZQIlahKkMYXv/R90dBvET/rJfOr3Ouc8v99zPec59zvf56j+vYKlViSf7250X4Mr3O29Tgq08BdGB4DhcekEJ5YkQKFsgWZdtj9JpV+I8xPjLFqkrsEIqO8PHSpis36jWazcqjEsfJjkvRssVU37SdIOu4XCf5vEJPsnwJpnRNU9JmxhMk8l1gehIrq7hTFjzOD+Vf88629qKMJVNltInFeRexRQyJlNeqd1iGDlSzrIUIyXbyFfm3RYprcQRe7lqtWyGYbfc6dT0R2vmdOOkX3u55C1rP37ftiH+tDby4r/RBT0w8TyEkr+epB9XgPDmSYYWbrhCuFYaIyw3fDQAXTnSkh+ANofiHmWf9l+FY1I90FdQTetstO00o23novzVsJ7uB3/C5TkbjRwZ5JerwV4iRWq9HFbFMaK/d0TYqayRiQPuIxxS3Bu8JWU90/60tKi7vkhaznez0a/TbVOKj5CaOZh6fWG6/Lyv9B/ZLR1gw/S/fpbeVD3MCW1li6SvWDOn65tr99/uvWtBS0XDm4s1t+sOHpG0kpBKx/l77wOSnxLpcx6TXmXLTPQOKYOf9Q1dfr8/SJ2mFdCvl1Yl93DiHUZvXeLJbGSzYu5gVJ2slbSakOR8dxCq5adQ2oFLqsE9Ex3L4qQO0eOPeU5x56bypXp4onSEb5OkICX6lDat55TeoztNKQcJaakrz9KCb95oD69IKq+yKW4XPjknaS52V0TZqE2cTtXjcHSCRmUO88e+85hj3EP74i9p8pylw7lxgMDyyl6OV7ZejnjNMfatu87LxRbH0IS35gt2a4ZjmGpVBdKK3Wr6INk8jWWSGqbA55CKgjBRC6E9w78ydTg3ABS3AFV1QN0Y4Aa2pgEjWnQURj9L0ayK6R2ysEqxHUKzYnLvvyU+i9KM2JHJzE4vyZOyDcOwOsySajeLPc8sNvPJkFlyJd20wpqAzZeAfZ3oWybxd+P/3j+SG3uSBdf2VQAAAABJRU5ErkJggg==') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -webkit-background-size: 100%; -moz-background-size: 100%; -o-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } +.jasmine_html-reporter .banner .version { margin-left: 14px; position: relative; top: 6px; } +.jasmine_html-reporter .banner .duration { position: absolute; right: 14px; top: 6px; } +.jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; } +.jasmine_html-reporter .version { color: #aaaaaa; } +.jasmine_html-reporter .banner { margin-top: 14px; } +.jasmine_html-reporter .duration { color: #aaaaaa; float: right; } +.jasmine_html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } +.jasmine_html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; } +.jasmine_html-reporter .symbol-summary li.passed { font-size: 14px; } +.jasmine_html-reporter .symbol-summary li.passed:before { color: #007069; content: "\02022"; } +.jasmine_html-reporter .symbol-summary li.failed { line-height: 9px; } +.jasmine_html-reporter .symbol-summary li.failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } +.jasmine_html-reporter .symbol-summary li.disabled { font-size: 14px; } +.jasmine_html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; } +.jasmine_html-reporter .symbol-summary li.pending { line-height: 17px; } +.jasmine_html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; } +.jasmine_html-reporter .symbol-summary li.empty { font-size: 14px; } +.jasmine_html-reporter .symbol-summary li.empty:before { color: #ba9d37; content: "\02022"; } +.jasmine_html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } +.jasmine_html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } +.jasmine_html-reporter .bar.failed { background-color: #ca3a11; } +.jasmine_html-reporter .bar.passed { background-color: #007069; } +.jasmine_html-reporter .bar.skipped { background-color: #bababa; } +.jasmine_html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; } +.jasmine_html-reporter .bar.menu a { color: #333333; } +.jasmine_html-reporter .bar a { color: white; } +.jasmine_html-reporter.spec-list .bar.menu.failure-list, .jasmine_html-reporter.spec-list .results .failures { display: none; } +.jasmine_html-reporter.failure-list .bar.menu.spec-list, .jasmine_html-reporter.failure-list .summary { display: none; } +.jasmine_html-reporter .running-alert { background-color: #666666; } +.jasmine_html-reporter .results { margin-top: 14px; } +.jasmine_html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } +.jasmine_html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } +.jasmine_html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } +.jasmine_html-reporter.showDetails .summary { display: none; } +.jasmine_html-reporter.showDetails #details { display: block; } +.jasmine_html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } +.jasmine_html-reporter .summary { margin-top: 14px; } +.jasmine_html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } +.jasmine_html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; } +.jasmine_html-reporter .summary li.passed a { color: #007069; } +.jasmine_html-reporter .summary li.failed a { color: #ca3a11; } +.jasmine_html-reporter .summary li.empty a { color: #ba9d37; } +.jasmine_html-reporter .summary li.pending a { color: #ba9d37; } +.jasmine_html-reporter .description + .suite { margin-top: 0; } +.jasmine_html-reporter .suite { margin-top: 14px; } +.jasmine_html-reporter .suite a { color: #333333; } +.jasmine_html-reporter .failures .spec-detail { margin-bottom: 28px; } +.jasmine_html-reporter .failures .spec-detail .description { background-color: #ca3a11; } +.jasmine_html-reporter .failures .spec-detail .description a { color: white; } +.jasmine_html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; } +.jasmine_html-reporter .result-message span.result { display: block; } +.jasmine_html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } diff --git a/tests/lib/jasmine-2.0.2/jasmine.js b/tests/lib/jasmine-2.0.2/jasmine.js new file mode 100755 index 00000000..ffe97570 --- /dev/null +++ b/tests/lib/jasmine-2.0.2/jasmine.js @@ -0,0 +1,2593 @@ +/* +Copyright (c) 2008-2014 Pivotal Labs + +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. +*/ +function getJasmineRequireObj() { + if (typeof module !== 'undefined' && module.exports) { + return exports; + } else { + window.jasmineRequire = window.jasmineRequire || {}; + return window.jasmineRequire; + } +} + +getJasmineRequireObj().core = function(jRequire) { + var j$ = {}; + + jRequire.base(j$); + j$.util = jRequire.util(); + j$.Any = jRequire.Any(); + j$.CallTracker = jRequire.CallTracker(); + j$.MockDate = jRequire.MockDate(); + j$.Clock = jRequire.Clock(); + j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); + j$.Env = jRequire.Env(j$); + j$.ExceptionFormatter = jRequire.ExceptionFormatter(); + j$.Expectation = jRequire.Expectation(); + j$.buildExpectationResult = jRequire.buildExpectationResult(); + j$.JsApiReporter = jRequire.JsApiReporter(); + j$.matchersUtil = jRequire.matchersUtil(j$); + j$.ObjectContaining = jRequire.ObjectContaining(j$); + j$.pp = jRequire.pp(j$); + j$.QueueRunner = jRequire.QueueRunner(j$); + j$.ReportDispatcher = jRequire.ReportDispatcher(); + j$.Spec = jRequire.Spec(j$); + j$.SpyStrategy = jRequire.SpyStrategy(); + j$.Suite = jRequire.Suite(); + j$.Timer = jRequire.Timer(); + j$.version = jRequire.version(); + + j$.matchers = jRequire.requireMatchers(jRequire, j$); + + return j$; +}; + +getJasmineRequireObj().requireMatchers = function(jRequire, j$) { + var availableMatchers = [ + 'toBe', + 'toBeCloseTo', + 'toBeDefined', + 'toBeFalsy', + 'toBeGreaterThan', + 'toBeLessThan', + 'toBeNaN', + 'toBeNull', + 'toBeTruthy', + 'toBeUndefined', + 'toContain', + 'toEqual', + 'toHaveBeenCalled', + 'toHaveBeenCalledWith', + 'toMatch', + 'toThrow', + 'toThrowError' + ], + matchers = {}; + + for (var i = 0; i < availableMatchers.length; i++) { + var name = availableMatchers[i]; + matchers[name] = jRequire[name](j$); + } + + return matchers; +}; + +getJasmineRequireObj().base = (function (jasmineGlobal) { + if (typeof module !== 'undefined' && module.exports) { + jasmineGlobal = global; + } + + return function(j$) { + j$.unimplementedMethod_ = function() { + throw new Error('unimplemented method'); + }; + + j$.MAX_PRETTY_PRINT_DEPTH = 40; + j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; + j$.DEFAULT_TIMEOUT_INTERVAL = 5000; + + j$.getGlobal = function() { + return jasmineGlobal; + }; + + j$.getEnv = function(options) { + var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); + //jasmine. singletons in here (setTimeout blah blah). + return env; + }; + + j$.isArray_ = function(value) { + return j$.isA_('Array', value); + }; + + j$.isString_ = function(value) { + return j$.isA_('String', value); + }; + + j$.isNumber_ = function(value) { + return j$.isA_('Number', value); + }; + + j$.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; + }; + + j$.isDomNode = function(obj) { + return obj.nodeType > 0; + }; + + j$.any = function(clazz) { + return new j$.Any(clazz); + }; + + j$.objectContaining = function(sample) { + return new j$.ObjectContaining(sample); + }; + + j$.createSpy = function(name, originalFn) { + + var spyStrategy = new j$.SpyStrategy({ + name: name, + fn: originalFn, + getSpy: function() { return spy; } + }), + callTracker = new j$.CallTracker(), + spy = function() { + callTracker.track({ + object: this, + args: Array.prototype.slice.apply(arguments) + }); + return spyStrategy.exec.apply(this, arguments); + }; + + for (var prop in originalFn) { + if (prop === 'and' || prop === 'calls') { + throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon'); + } + + spy[prop] = originalFn[prop]; + } + + spy.and = spyStrategy; + spy.calls = callTracker; + + return spy; + }; + + j$.isSpy = function(putativeSpy) { + if (!putativeSpy) { + return false; + } + return putativeSpy.and instanceof j$.SpyStrategy && + putativeSpy.calls instanceof j$.CallTracker; + }; + + j$.createSpyObj = function(baseName, methodNames) { + if (!j$.isArray_(methodNames) || methodNames.length === 0) { + throw 'createSpyObj requires a non-empty array of method names to create spies for'; + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); + } + return obj; + }; + }; +})(this); + +getJasmineRequireObj().util = function() { + + var util = {}; + + util.inherit = function(childClass, parentClass) { + var Subclass = function() { + }; + Subclass.prototype = parentClass.prototype; + childClass.prototype = new Subclass(); + }; + + util.htmlEscape = function(str) { + if (!str) { + return str; + } + return str.replace(/&/g, '&') + .replace(//g, '>'); + }; + + util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) { + arrayOfArgs.push(args[i]); + } + return arrayOfArgs; + }; + + util.isUndefined = function(obj) { + return obj === void 0; + }; + + util.arrayContains = function(array, search) { + var i = array.length; + while (i--) { + if (array[i] == search) { + return true; + } + } + return false; + }; + + return util; +}; + +getJasmineRequireObj().Spec = function(j$) { + function Spec(attrs) { + this.expectationFactory = attrs.expectationFactory; + this.resultCallback = attrs.resultCallback || function() {}; + this.id = attrs.id; + this.description = attrs.description || ''; + this.fn = attrs.fn; + this.beforeFns = attrs.beforeFns || function() { return []; }; + this.afterFns = attrs.afterFns || function() { return []; }; + this.onStart = attrs.onStart || function() {}; + this.exceptionFormatter = attrs.exceptionFormatter || function() {}; + this.getSpecName = attrs.getSpecName || function() { return ''; }; + this.expectationResultFactory = attrs.expectationResultFactory || function() { }; + this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; + this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; + + if (!this.fn) { + this.pend(); + } + + this.result = { + id: this.id, + description: this.description, + fullName: this.getFullName(), + failedExpectations: [], + passedExpectations: [] + }; + } + + Spec.prototype.addExpectationResult = function(passed, data) { + var expectationResult = this.expectationResultFactory(data); + if (passed) { + this.result.passedExpectations.push(expectationResult); + } else { + this.result.failedExpectations.push(expectationResult); + } + }; + + Spec.prototype.expect = function(actual) { + return this.expectationFactory(actual, this); + }; + + Spec.prototype.execute = function(onComplete) { + var self = this; + + this.onStart(this); + + if (this.markedPending || this.disabled) { + complete(); + return; + } + + var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()); + + this.queueRunnerFactory({ + fns: allFns, + onException: onException, + onComplete: complete, + enforceTimeout: function() { return true; } + }); + + function onException(e) { + if (Spec.isPendingSpecException(e)) { + self.pend(); + return; + } + + self.addExpectationResult(false, { + matcherName: '', + passed: false, + expected: '', + actual: '', + error: e + }); + } + + function complete() { + self.result.status = self.status(); + self.resultCallback(self.result); + + if (onComplete) { + onComplete(); + } + } + }; + + Spec.prototype.disable = function() { + this.disabled = true; + }; + + Spec.prototype.pend = function() { + this.markedPending = true; + }; + + Spec.prototype.status = function() { + if (this.disabled) { + return 'disabled'; + } + + if (this.markedPending) { + return 'pending'; + } + + if (this.result.failedExpectations.length > 0) { + return 'failed'; + } else { + return 'passed'; + } + }; + + Spec.prototype.getFullName = function() { + return this.getSpecName(this); + }; + + Spec.pendingSpecExceptionMessage = '=> marked Pending'; + + Spec.isPendingSpecException = function(e) { + return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1); + }; + + return Spec; +}; + +if (typeof window == void 0 && typeof exports == 'object') { + exports.Spec = jasmineRequire.Spec; +} + +getJasmineRequireObj().Env = function(j$) { + function Env(options) { + options = options || {}; + + var self = this; + var global = options.global || j$.getGlobal(); + + var totalSpecsDefined = 0; + + var catchExceptions = true; + + var realSetTimeout = j$.getGlobal().setTimeout; + var realClearTimeout = j$.getGlobal().clearTimeout; + this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler(), new j$.MockDate(global)); + + var runnableLookupTable = {}; + + var spies = []; + + var currentSpec = null; + var currentSuite = null; + + var reporter = new j$.ReportDispatcher([ + 'jasmineStarted', + 'jasmineDone', + 'suiteStarted', + 'suiteDone', + 'specStarted', + 'specDone' + ]); + + this.specFilter = function() { + return true; + }; + + var equalityTesters = []; + + var customEqualityTesters = []; + this.addCustomEqualityTester = function(tester) { + customEqualityTesters.push(tester); + }; + + j$.Expectation.addCoreMatchers(j$.matchers); + + var nextSpecId = 0; + var getNextSpecId = function() { + return 'spec' + nextSpecId++; + }; + + var nextSuiteId = 0; + var getNextSuiteId = function() { + return 'suite' + nextSuiteId++; + }; + + var expectationFactory = function(actual, spec) { + return j$.Expectation.Factory({ + util: j$.matchersUtil, + customEqualityTesters: customEqualityTesters, + actual: actual, + addExpectationResult: addExpectationResult + }); + + function addExpectationResult(passed, result) { + return spec.addExpectationResult(passed, result); + } + }; + + var specStarted = function(spec) { + currentSpec = spec; + reporter.specStarted(spec.result); + }; + + var beforeFns = function(suite) { + return function() { + var befores = []; + while(suite) { + befores = befores.concat(suite.beforeFns); + suite = suite.parentSuite; + } + return befores.reverse(); + }; + }; + + var afterFns = function(suite) { + return function() { + var afters = []; + while(suite) { + afters = afters.concat(suite.afterFns); + suite = suite.parentSuite; + } + return afters; + }; + }; + + var getSpecName = function(spec, suite) { + return suite.getFullName() + ' ' + spec.description; + }; + + // TODO: we may just be able to pass in the fn instead of wrapping here + var buildExpectationResult = j$.buildExpectationResult, + exceptionFormatter = new j$.ExceptionFormatter(), + expectationResultFactory = function(attrs) { + attrs.messageFormatter = exceptionFormatter.message; + attrs.stackFormatter = exceptionFormatter.stack; + + return buildExpectationResult(attrs); + }; + + // TODO: fix this naming, and here's where the value comes in + this.catchExceptions = function(value) { + catchExceptions = !!value; + return catchExceptions; + }; + + this.catchingExceptions = function() { + return catchExceptions; + }; + + var maximumSpecCallbackDepth = 20; + var currentSpecCallbackDepth = 0; + + function clearStack(fn) { + currentSpecCallbackDepth++; + if (currentSpecCallbackDepth >= maximumSpecCallbackDepth) { + currentSpecCallbackDepth = 0; + realSetTimeout(fn, 0); + } else { + fn(); + } + } + + var catchException = function(e) { + return j$.Spec.isPendingSpecException(e) || catchExceptions; + }; + + var queueRunnerFactory = function(options) { + options.catchException = catchException; + options.clearStack = options.clearStack || clearStack; + options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; + + new j$.QueueRunner(options).execute(); + }; + + var topSuite = new j$.Suite({ + env: this, + id: getNextSuiteId(), + description: 'Jasmine__TopLevel__Suite', + queueRunner: queueRunnerFactory, + resultCallback: function() {} // TODO - hook this up + }); + runnableLookupTable[topSuite.id] = topSuite; + currentSuite = topSuite; + + this.topSuite = function() { + return topSuite; + }; + + this.execute = function(runnablesToRun) { + runnablesToRun = runnablesToRun || [topSuite.id]; + + var allFns = []; + for(var i = 0; i < runnablesToRun.length; i++) { + var runnable = runnableLookupTable[runnablesToRun[i]]; + allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable)); + } + + reporter.jasmineStarted({ + totalSpecsDefined: totalSpecsDefined + }); + + queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone}); + }; + + this.addReporter = function(reporterToAdd) { + reporter.addReporter(reporterToAdd); + }; + + this.addMatchers = function(matchersToAdd) { + j$.Expectation.addMatchers(matchersToAdd); + }; + + this.spyOn = function(obj, methodName) { + if (j$.util.isUndefined(obj)) { + throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()'); + } + + if (j$.util.isUndefined(obj[methodName])) { + throw new Error(methodName + '() method does not exist'); + } + + if (obj[methodName] && j$.isSpy(obj[methodName])) { + //TODO?: should this return the current spy? Downside: may cause user confusion about spy state + throw new Error(methodName + ' has already been spied upon'); + } + + var spy = j$.createSpy(methodName, obj[methodName]); + + spies.push({ + spy: spy, + baseObj: obj, + methodName: methodName, + originalValue: obj[methodName] + }); + + obj[methodName] = spy; + + return spy; + }; + + var suiteFactory = function(description) { + var suite = new j$.Suite({ + env: self, + id: getNextSuiteId(), + description: description, + parentSuite: currentSuite, + queueRunner: queueRunnerFactory, + onStart: suiteStarted, + resultCallback: function(attrs) { + reporter.suiteDone(attrs); + } + }); + + runnableLookupTable[suite.id] = suite; + return suite; + }; + + this.describe = function(description, specDefinitions) { + var suite = suiteFactory(description); + + var parentSuite = currentSuite; + parentSuite.addChild(suite); + currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch (e) { + declarationError = e; + } + + if (declarationError) { + this.it('encountered a declaration exception', function() { + throw declarationError; + }); + } + + currentSuite = parentSuite; + + return suite; + }; + + this.xdescribe = function(description, specDefinitions) { + var suite = this.describe(description, specDefinitions); + suite.disable(); + return suite; + }; + + var specFactory = function(description, fn, suite) { + totalSpecsDefined++; + + var spec = new j$.Spec({ + id: getNextSpecId(), + beforeFns: beforeFns(suite), + afterFns: afterFns(suite), + expectationFactory: expectationFactory, + exceptionFormatter: exceptionFormatter, + resultCallback: specResultCallback, + getSpecName: function(spec) { + return getSpecName(spec, suite); + }, + onStart: specStarted, + description: description, + expectationResultFactory: expectationResultFactory, + queueRunnerFactory: queueRunnerFactory, + fn: fn + }); + + runnableLookupTable[spec.id] = spec; + + if (!self.specFilter(spec)) { + spec.disable(); + } + + return spec; + + function removeAllSpies() { + for (var i = 0; i < spies.length; i++) { + var spyEntry = spies[i]; + spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue; + } + spies = []; + } + + function specResultCallback(result) { + removeAllSpies(); + j$.Expectation.resetMatchers(); + customEqualityTesters = []; + currentSpec = null; + reporter.specDone(result); + } + }; + + var suiteStarted = function(suite) { + reporter.suiteStarted(suite.result); + }; + + this.it = function(description, fn) { + var spec = specFactory(description, fn, currentSuite); + currentSuite.addChild(spec); + return spec; + }; + + this.xit = function(description, fn) { + var spec = this.it(description, fn); + spec.pend(); + return spec; + }; + + this.expect = function(actual) { + if (!currentSpec) { + throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out'); + } + + return currentSpec.expect(actual); + }; + + this.beforeEach = function(beforeEachFunction) { + currentSuite.beforeEach(beforeEachFunction); + }; + + this.afterEach = function(afterEachFunction) { + currentSuite.afterEach(afterEachFunction); + }; + + this.pending = function() { + throw j$.Spec.pendingSpecExceptionMessage; + }; + } + + return Env; +}; + +getJasmineRequireObj().JsApiReporter = function() { + + var noopTimer = { + start: function(){}, + elapsed: function(){ return 0; } + }; + + function JsApiReporter(options) { + var timer = options.timer || noopTimer, + status = 'loaded'; + + this.started = false; + this.finished = false; + + this.jasmineStarted = function() { + this.started = true; + status = 'started'; + timer.start(); + }; + + var executionTime; + + this.jasmineDone = function() { + this.finished = true; + executionTime = timer.elapsed(); + status = 'done'; + }; + + this.status = function() { + return status; + }; + + var suites = {}; + + this.suiteStarted = function(result) { + storeSuite(result); + }; + + this.suiteDone = function(result) { + storeSuite(result); + }; + + function storeSuite(result) { + suites[result.id] = result; + } + + this.suites = function() { + return suites; + }; + + var specs = []; + this.specStarted = function(result) { }; + + this.specDone = function(result) { + specs.push(result); + }; + + this.specResults = function(index, length) { + return specs.slice(index, index + length); + }; + + this.specs = function() { + return specs; + }; + + this.executionTime = function() { + return executionTime; + }; + + } + + return JsApiReporter; +}; + +getJasmineRequireObj().Any = function() { + + function Any(expectedObject) { + this.expectedObject = expectedObject; + } + + Any.prototype.jasmineMatches = function(other) { + if (this.expectedObject == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedObject == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedObject == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedObject == Object) { + return typeof other == 'object'; + } + + if (this.expectedObject == Boolean) { + return typeof other == 'boolean'; + } + + return other instanceof this.expectedObject; + }; + + Any.prototype.jasmineToString = function() { + return ''; + }; + + return Any; +}; + +getJasmineRequireObj().CallTracker = function() { + + function CallTracker() { + var calls = []; + + this.track = function(context) { + calls.push(context); + }; + + this.any = function() { + return !!calls.length; + }; + + this.count = function() { + return calls.length; + }; + + this.argsFor = function(index) { + var call = calls[index]; + return call ? call.args : []; + }; + + this.all = function() { + return calls; + }; + + this.allArgs = function() { + var callArgs = []; + for(var i = 0; i < calls.length; i++){ + callArgs.push(calls[i].args); + } + + return callArgs; + }; + + this.first = function() { + return calls[0]; + }; + + this.mostRecent = function() { + return calls[calls.length - 1]; + }; + + this.reset = function() { + calls = []; + }; + } + + return CallTracker; +}; + +getJasmineRequireObj().Clock = function() { + function Clock(global, delayedFunctionScheduler, mockDate) { + var self = this, + realTimingFunctions = { + setTimeout: global.setTimeout, + clearTimeout: global.clearTimeout, + setInterval: global.setInterval, + clearInterval: global.clearInterval + }, + fakeTimingFunctions = { + setTimeout: setTimeout, + clearTimeout: clearTimeout, + setInterval: setInterval, + clearInterval: clearInterval + }, + installed = false, + timer; + + + self.install = function() { + replace(global, fakeTimingFunctions); + timer = fakeTimingFunctions; + installed = true; + + return self; + }; + + self.uninstall = function() { + delayedFunctionScheduler.reset(); + mockDate.uninstall(); + replace(global, realTimingFunctions); + + timer = realTimingFunctions; + installed = false; + }; + + self.mockDate = function(initialDate) { + mockDate.install(initialDate); + }; + + self.setTimeout = function(fn, delay, params) { + if (legacyIE()) { + if (arguments.length > 2) { + throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill'); + } + return timer.setTimeout(fn, delay); + } + return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]); + }; + + self.setInterval = function(fn, delay, params) { + if (legacyIE()) { + if (arguments.length > 2) { + throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill'); + } + return timer.setInterval(fn, delay); + } + return Function.prototype.apply.apply(timer.setInterval, [global, arguments]); + }; + + self.clearTimeout = function(id) { + return Function.prototype.call.apply(timer.clearTimeout, [global, id]); + }; + + self.clearInterval = function(id) { + return Function.prototype.call.apply(timer.clearInterval, [global, id]); + }; + + self.tick = function(millis) { + if (installed) { + mockDate.tick(millis); + delayedFunctionScheduler.tick(millis); + } else { + throw new Error('Mock clock is not installed, use jasmine.clock().install()'); + } + }; + + return self; + + function legacyIE() { + //if these methods are polyfilled, apply will be present + return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; + } + + function replace(dest, source) { + for (var prop in source) { + dest[prop] = source[prop]; + } + } + + function setTimeout(fn, delay) { + return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2)); + } + + function clearTimeout(id) { + return delayedFunctionScheduler.removeFunctionWithId(id); + } + + function setInterval(fn, interval) { + return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true); + } + + function clearInterval(id) { + return delayedFunctionScheduler.removeFunctionWithId(id); + } + + function argSlice(argsObj, n) { + return Array.prototype.slice.call(argsObj, n); + } + } + + return Clock; +}; + +getJasmineRequireObj().DelayedFunctionScheduler = function() { + function DelayedFunctionScheduler() { + var self = this; + var scheduledLookup = []; + var scheduledFunctions = {}; + var currentTime = 0; + var delayedFnCount = 0; + + self.tick = function(millis) { + millis = millis || 0; + var endTime = currentTime + millis; + + runScheduledFunctions(endTime); + currentTime = endTime; + }; + + self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) { + var f; + if (typeof(funcToCall) === 'string') { + /* jshint evil: true */ + f = function() { return eval(funcToCall); }; + /* jshint evil: false */ + } else { + f = funcToCall; + } + + millis = millis || 0; + timeoutKey = timeoutKey || ++delayedFnCount; + runAtMillis = runAtMillis || (currentTime + millis); + + var funcToSchedule = { + runAtMillis: runAtMillis, + funcToCall: f, + recurring: recurring, + params: params, + timeoutKey: timeoutKey, + millis: millis + }; + + if (runAtMillis in scheduledFunctions) { + scheduledFunctions[runAtMillis].push(funcToSchedule); + } else { + scheduledFunctions[runAtMillis] = [funcToSchedule]; + scheduledLookup.push(runAtMillis); + scheduledLookup.sort(function (a, b) { + return a - b; + }); + } + + return timeoutKey; + }; + + self.removeFunctionWithId = function(timeoutKey) { + for (var runAtMillis in scheduledFunctions) { + var funcs = scheduledFunctions[runAtMillis]; + var i = indexOfFirstToPass(funcs, function (func) { + return func.timeoutKey === timeoutKey; + }); + + if (i > -1) { + if (funcs.length === 1) { + delete scheduledFunctions[runAtMillis]; + deleteFromLookup(runAtMillis); + } else { + funcs.splice(i, 1); + } + + // intervals get rescheduled when executed, so there's never more + // than a single scheduled function with a given timeoutKey + break; + } + } + }; + + self.reset = function() { + currentTime = 0; + scheduledLookup = []; + scheduledFunctions = {}; + delayedFnCount = 0; + }; + + return self; + + function indexOfFirstToPass(array, testFn) { + var index = -1; + + for (var i = 0; i < array.length; ++i) { + if (testFn(array[i])) { + index = i; + break; + } + } + + return index; + } + + function deleteFromLookup(key) { + var value = Number(key); + var i = indexOfFirstToPass(scheduledLookup, function (millis) { + return millis === value; + }); + + if (i > -1) { + scheduledLookup.splice(i, 1); + } + } + + function reschedule(scheduledFn) { + self.scheduleFunction(scheduledFn.funcToCall, + scheduledFn.millis, + scheduledFn.params, + true, + scheduledFn.timeoutKey, + scheduledFn.runAtMillis + scheduledFn.millis); + } + + function runScheduledFunctions(endTime) { + if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) { + return; + } + + do { + currentTime = scheduledLookup.shift(); + + var funcsToRun = scheduledFunctions[currentTime]; + delete scheduledFunctions[currentTime]; + + for (var i = 0; i < funcsToRun.length; ++i) { + var funcToRun = funcsToRun[i]; + funcToRun.funcToCall.apply(null, funcToRun.params || []); + + if (funcToRun.recurring) { + reschedule(funcToRun); + } + } + } while (scheduledLookup.length > 0 && + // checking first if we're out of time prevents setTimeout(0) + // scheduled in a funcToRun from forcing an extra iteration + currentTime !== endTime && + scheduledLookup[0] <= endTime); + } + } + + return DelayedFunctionScheduler; +}; + +getJasmineRequireObj().ExceptionFormatter = function() { + function ExceptionFormatter() { + this.message = function(error) { + var message = ''; + + if (error.name && error.message) { + message += error.name + ': ' + error.message; + } else { + message += error.toString() + ' thrown'; + } + + if (error.fileName || error.sourceURL) { + message += ' in ' + (error.fileName || error.sourceURL); + } + + if (error.line || error.lineNumber) { + message += ' (line ' + (error.line || error.lineNumber) + ')'; + } + + return message; + }; + + this.stack = function(error) { + return error ? error.stack : null; + }; + } + + return ExceptionFormatter; +}; + +getJasmineRequireObj().Expectation = function() { + + var matchers = {}; + + function Expectation(options) { + this.util = options.util || { buildFailureMessage: function() {} }; + this.customEqualityTesters = options.customEqualityTesters || []; + this.actual = options.actual; + this.addExpectationResult = options.addExpectationResult || function(){}; + this.isNot = options.isNot; + + for (var matcherName in matchers) { + this[matcherName] = matchers[matcherName]; + } + } + + Expectation.prototype.wrapCompare = function(name, matcherFactory) { + return function() { + var args = Array.prototype.slice.call(arguments, 0), + expected = args.slice(0), + message = ''; + + args.unshift(this.actual); + + var matcher = matcherFactory(this.util, this.customEqualityTesters), + matcherCompare = matcher.compare; + + function defaultNegativeCompare() { + var result = matcher.compare.apply(null, args); + result.pass = !result.pass; + return result; + } + + if (this.isNot) { + matcherCompare = matcher.negativeCompare || defaultNegativeCompare; + } + + var result = matcherCompare.apply(null, args); + + if (!result.pass) { + if (!result.message) { + args.unshift(this.isNot); + args.unshift(name); + message = this.util.buildFailureMessage.apply(null, args); + } else { + if (Object.prototype.toString.apply(result.message) === '[object Function]') { + message = result.message(); + } else { + message = result.message; + } + } + } + + if (expected.length == 1) { + expected = expected[0]; + } + + // TODO: how many of these params are needed? + this.addExpectationResult( + result.pass, + { + matcherName: name, + passed: result.pass, + message: message, + actual: this.actual, + expected: expected // TODO: this may need to be arrayified/sliced + } + ); + }; + }; + + Expectation.addCoreMatchers = function(matchers) { + var prototype = Expectation.prototype; + for (var matcherName in matchers) { + var matcher = matchers[matcherName]; + prototype[matcherName] = prototype.wrapCompare(matcherName, matcher); + } + }; + + Expectation.addMatchers = function(matchersToAdd) { + for (var name in matchersToAdd) { + var matcher = matchersToAdd[name]; + matchers[name] = Expectation.prototype.wrapCompare(name, matcher); + } + }; + + Expectation.resetMatchers = function() { + for (var name in matchers) { + delete matchers[name]; + } + }; + + Expectation.Factory = function(options) { + options = options || {}; + + var expect = new Expectation(options); + + // TODO: this would be nice as its own Object - NegativeExpectation + // TODO: copy instead of mutate options + options.isNot = true; + expect.not = new Expectation(options); + + return expect; + }; + + return Expectation; +}; + +//TODO: expectation result may make more sense as a presentation of an expectation. +getJasmineRequireObj().buildExpectationResult = function() { + function buildExpectationResult(options) { + var messageFormatter = options.messageFormatter || function() {}, + stackFormatter = options.stackFormatter || function() {}; + + return { + matcherName: options.matcherName, + expected: options.expected, + actual: options.actual, + message: message(), + stack: stack(), + passed: options.passed + }; + + function message() { + if (options.passed) { + return 'Passed.'; + } else if (options.message) { + return options.message; + } else if (options.error) { + return messageFormatter(options.error); + } + return ''; + } + + function stack() { + if (options.passed) { + return ''; + } + + var error = options.error; + if (!error) { + try { + throw new Error(message()); + } catch (e) { + error = e; + } + } + return stackFormatter(error); + } + } + + return buildExpectationResult; +}; + +getJasmineRequireObj().MockDate = function() { + function MockDate(global) { + var self = this; + var currentTime = 0; + + if (!global || !global.Date) { + self.install = function() {}; + self.tick = function() {}; + self.uninstall = function() {}; + return self; + } + + var GlobalDate = global.Date; + + self.install = function(mockDate) { + if (mockDate instanceof GlobalDate) { + currentTime = mockDate.getTime(); + } else { + currentTime = new GlobalDate().getTime(); + } + + global.Date = FakeDate; + }; + + self.tick = function(millis) { + millis = millis || 0; + currentTime = currentTime + millis; + }; + + self.uninstall = function() { + currentTime = 0; + global.Date = GlobalDate; + }; + + createDateProperties(); + + return self; + + function FakeDate() { + switch(arguments.length) { + case 0: + return new GlobalDate(currentTime); + case 1: + return new GlobalDate(arguments[0]); + case 2: + return new GlobalDate(arguments[0], arguments[1]); + case 3: + return new GlobalDate(arguments[0], arguments[1], arguments[2]); + case 4: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3]); + case 5: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], + arguments[4]); + case 6: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], + arguments[4], arguments[5]); + case 7: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], + arguments[4], arguments[5], arguments[6]); + } + } + + function createDateProperties() { + + FakeDate.now = function() { + if (GlobalDate.now) { + return currentTime; + } else { + throw new Error('Browser does not support Date.now()'); + } + }; + + FakeDate.toSource = GlobalDate.toSource; + FakeDate.toString = GlobalDate.toString; + FakeDate.parse = GlobalDate.parse; + FakeDate.UTC = GlobalDate.UTC; + } + } + + return MockDate; +}; + +getJasmineRequireObj().ObjectContaining = function(j$) { + + function ObjectContaining(sample) { + this.sample = sample; + } + + ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { + if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); } + + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + var hasKey = function(obj, keyName) { + return obj !== null && !j$.util.isUndefined(obj[keyName]); + }; + + for (var property in this.sample) { + if (!hasKey(other, property) && hasKey(this.sample, property)) { + mismatchKeys.push('expected has key \'' + property + '\', but missing from actual.'); + } + else if (!j$.matchersUtil.equals(other[property], this.sample[property])) { + mismatchValues.push('\'' + property + '\' was \'' + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + '\' in actual, but was \'' + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + '\' in expected.'); + } + } + + return (mismatchKeys.length === 0 && mismatchValues.length === 0); + }; + + ObjectContaining.prototype.jasmineToString = function() { + return ''; + }; + + return ObjectContaining; +}; + +getJasmineRequireObj().pp = function(j$) { + + function PrettyPrinter() { + this.ppNestLevel_ = 0; + this.seen = []; + } + + PrettyPrinter.prototype.format = function(value) { + this.ppNestLevel_++; + try { + if (j$.util.isUndefined(value)) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === 0 && 1/value === -Infinity) { + this.emitScalar('-0'); + } else if (value === j$.getGlobal()) { + this.emitScalar(''); + } else if (value.jasmineToString) { + this.emitScalar(value.jasmineToString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (j$.isSpy(value)) { + this.emitScalar('spy on ' + value.and.identity()); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (j$.util.arrayContains(this.seen, value)) { + this.emitScalar(''); + } else if (j$.isArray_(value) || j$.isA_('Object', value)) { + this.seen.push(value); + if (j$.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + this.seen.pop(); + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } + }; + + PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } + fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && + obj.__lookupGetter__(property) !== null) : false); + } + }; + + PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitString = j$.unimplementedMethod_; + + function StringPrettyPrinter() { + PrettyPrinter.call(this); + + this.string = ''; + } + + j$.util.inherit(StringPrettyPrinter, PrettyPrinter); + + StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); + }; + + StringPrettyPrinter.prototype.emitString = function(value) { + this.append('\'' + value + '\''); + }; + + StringPrettyPrinter.prototype.emitArray = function(array) { + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + this.append('Array'); + return; + } + var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); + this.append('[ '); + for (var i = 0; i < length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + if(array.length > length){ + this.append(', ...'); + } + this.append(' ]'); + }; + + StringPrettyPrinter.prototype.emitObject = function(obj) { + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + this.append('Object'); + return; + } + + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(': '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); + }; + + StringPrettyPrinter.prototype.append = function(value) { + this.string += value; + }; + + return function(value) { + var stringPrettyPrinter = new StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; + }; +}; + +getJasmineRequireObj().QueueRunner = function(j$) { + + function once(fn) { + var called = false; + return function() { + if (!called) { + called = true; + fn(); + } + }; + } + + function QueueRunner(attrs) { + this.fns = attrs.fns || []; + this.onComplete = attrs.onComplete || function() {}; + this.clearStack = attrs.clearStack || function(fn) {fn();}; + this.onException = attrs.onException || function() {}; + this.catchException = attrs.catchException || function() { return true; }; + this.enforceTimeout = attrs.enforceTimeout || function() { return false; }; + this.userContext = {}; + this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; + } + + QueueRunner.prototype.execute = function() { + this.run(this.fns, 0); + }; + + QueueRunner.prototype.run = function(fns, recursiveIndex) { + var length = fns.length, + self = this, + iterativeIndex; + + for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { + var fn = fns[iterativeIndex]; + if (fn.length > 0) { + return attemptAsync(fn); + } else { + attemptSync(fn); + } + } + + var runnerDone = iterativeIndex >= length; + + if (runnerDone) { + this.clearStack(this.onComplete); + } + + function attemptSync(fn) { + try { + fn.call(self.userContext); + } catch (e) { + handleException(e); + } + } + + function attemptAsync(fn) { + var clearTimeout = function () { + Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]); + }, + next = once(function () { + clearTimeout(timeoutId); + self.run(fns, iterativeIndex + 1); + }), + timeoutId; + + if (self.enforceTimeout()) { + timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { + self.onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.')); + next(); + }, j$.DEFAULT_TIMEOUT_INTERVAL]]); + } + + try { + fn.call(self.userContext, next); + } catch (e) { + handleException(e); + next(); + } + } + + function handleException(e) { + self.onException(e); + if (!self.catchException(e)) { + //TODO: set a var when we catch an exception and + //use a finally block to close the loop in a nice way.. + throw e; + } + } + }; + + return QueueRunner; +}; + +getJasmineRequireObj().ReportDispatcher = function() { + function ReportDispatcher(methods) { + + var dispatchedMethods = methods || []; + + for (var i = 0; i < dispatchedMethods.length; i++) { + var method = dispatchedMethods[i]; + this[method] = (function(m) { + return function() { + dispatch(m, arguments); + }; + }(method)); + } + + var reporters = []; + + this.addReporter = function(reporter) { + reporters.push(reporter); + }; + + return this; + + function dispatch(method, args) { + for (var i = 0; i < reporters.length; i++) { + var reporter = reporters[i]; + if (reporter[method]) { + reporter[method].apply(reporter, args); + } + } + } + } + + return ReportDispatcher; +}; + + +getJasmineRequireObj().SpyStrategy = function() { + + function SpyStrategy(options) { + options = options || {}; + + var identity = options.name || 'unknown', + originalFn = options.fn || function() {}, + getSpy = options.getSpy || function() {}, + plan = function() {}; + + this.identity = function() { + return identity; + }; + + this.exec = function() { + return plan.apply(this, arguments); + }; + + this.callThrough = function() { + plan = originalFn; + return getSpy(); + }; + + this.returnValue = function(value) { + plan = function() { + return value; + }; + return getSpy(); + }; + + this.throwError = function(something) { + var error = (something instanceof Error) ? something : new Error(something); + plan = function() { + throw error; + }; + return getSpy(); + }; + + this.callFake = function(fn) { + plan = fn; + return getSpy(); + }; + + this.stub = function(fn) { + plan = function() {}; + return getSpy(); + }; + } + + return SpyStrategy; +}; + +getJasmineRequireObj().Suite = function() { + function Suite(attrs) { + this.env = attrs.env; + this.id = attrs.id; + this.parentSuite = attrs.parentSuite; + this.description = attrs.description; + this.onStart = attrs.onStart || function() {}; + this.resultCallback = attrs.resultCallback || function() {}; + this.clearStack = attrs.clearStack || function(fn) {fn();}; + + this.beforeFns = []; + this.afterFns = []; + this.queueRunner = attrs.queueRunner || function() {}; + this.disabled = false; + + this.children = []; + + this.result = { + id: this.id, + status: this.disabled ? 'disabled' : '', + description: this.description, + fullName: this.getFullName() + }; + } + + Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + if (parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + } + return fullName; + }; + + Suite.prototype.disable = function() { + this.disabled = true; + this.result.status = 'disabled'; + }; + + Suite.prototype.beforeEach = function(fn) { + this.beforeFns.unshift(fn); + }; + + Suite.prototype.afterEach = function(fn) { + this.afterFns.unshift(fn); + }; + + Suite.prototype.addChild = function(child) { + this.children.push(child); + }; + + Suite.prototype.execute = function(onComplete) { + var self = this; + + this.onStart(this); + + if (this.disabled) { + complete(); + return; + } + + var allFns = []; + + for (var i = 0; i < this.children.length; i++) { + allFns.push(wrapChildAsAsync(this.children[i])); + } + + this.queueRunner({ + fns: allFns, + onComplete: complete + }); + + function complete() { + self.resultCallback(self.result); + + if (onComplete) { + onComplete(); + } + } + + function wrapChildAsAsync(child) { + return function(done) { child.execute(done); }; + } + }; + + return Suite; +}; + +if (typeof window == void 0 && typeof exports == 'object') { + exports.Suite = jasmineRequire.Suite; +} + +getJasmineRequireObj().Timer = function() { + var defaultNow = (function(Date) { + return function() { return new Date().getTime(); }; + })(Date); + + function Timer(options) { + options = options || {}; + + var now = options.now || defaultNow, + startTime; + + this.start = function() { + startTime = now(); + }; + + this.elapsed = function() { + return now() - startTime; + }; + } + + return Timer; +}; + +getJasmineRequireObj().matchersUtil = function(j$) { + // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter? + + return { + equals: function(a, b, customTesters) { + customTesters = customTesters || []; + + return eq(a, b, [], [], customTesters); + }, + + contains: function(haystack, needle, customTesters) { + customTesters = customTesters || []; + + if (Object.prototype.toString.apply(haystack) === '[object Array]') { + for (var i = 0; i < haystack.length; i++) { + if (eq(haystack[i], needle, [], [], customTesters)) { + return true; + } + } + return false; + } + return !!haystack && haystack.indexOf(needle) >= 0; + }, + + buildFailureMessage: function() { + var args = Array.prototype.slice.call(arguments, 0), + matcherName = args[0], + isNot = args[1], + actual = args[2], + expected = args.slice(3), + englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + + var message = 'Expected ' + + j$.pp(actual) + + (isNot ? ' not ' : ' ') + + englishyPredicate; + + if (expected.length > 0) { + for (var i = 0; i < expected.length; i++) { + if (i > 0) { + message += ','; + } + message += ' ' + j$.pp(expected[i]); + } + } + + return message + '.'; + } + }; + + // Equality function lovingly adapted from isEqual in + // [Underscore](http://underscorejs.org) + function eq(a, b, aStack, bStack, customTesters) { + var result = true; + + for (var i = 0; i < customTesters.length; i++) { + var customTesterResult = customTesters[i](a, b); + if (!j$.util.isUndefined(customTesterResult)) { + return customTesterResult; + } + } + + if (a instanceof j$.Any) { + result = a.jasmineMatches(b); + if (result) { + return true; + } + } + + if (b instanceof j$.Any) { + result = b.jasmineMatches(a); + if (result) { + return true; + } + } + + if (b instanceof j$.ObjectContaining) { + result = b.jasmineMatches(a); + if (result) { + return true; + } + } + + if (a instanceof Error && b instanceof Error) { + return a.message == b.message; + } + + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) { return a !== 0 || 1 / a == 1 / b; } + // A strict comparison is necessary because `null == undefined`. + if (a === null || b === null) { return a === b; } + var className = Object.prototype.toString.call(a); + if (className != Object.prototype.toString.call(b)) { return false; } + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') { return false; } + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) { return bStack[length] == b; } + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; } + } + } + } else { + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) && + isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } + // Deep compare objects. + for (var key in a) { + if (has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; } + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (has(b, key) && !(size--)) { break; } + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + + return result; + + function has(obj, key) { + return obj.hasOwnProperty(key); + } + + function isFunction(obj) { + return typeof obj === 'function'; + } + } +}; + +getJasmineRequireObj().toBe = function() { + function toBe() { + return { + compare: function(actual, expected) { + return { + pass: actual === expected + }; + } + }; + } + + return toBe; +}; + +getJasmineRequireObj().toBeCloseTo = function() { + + function toBeCloseTo() { + return { + compare: function(actual, expected, precision) { + if (precision !== 0) { + precision = precision || 2; + } + + return { + pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) + }; + } + }; + } + + return toBeCloseTo; +}; + +getJasmineRequireObj().toBeDefined = function() { + function toBeDefined() { + return { + compare: function(actual) { + return { + pass: (void 0 !== actual) + }; + } + }; + } + + return toBeDefined; +}; + +getJasmineRequireObj().toBeFalsy = function() { + function toBeFalsy() { + return { + compare: function(actual) { + return { + pass: !!!actual + }; + } + }; + } + + return toBeFalsy; +}; + +getJasmineRequireObj().toBeGreaterThan = function() { + + function toBeGreaterThan() { + return { + compare: function(actual, expected) { + return { + pass: actual > expected + }; + } + }; + } + + return toBeGreaterThan; +}; + + +getJasmineRequireObj().toBeLessThan = function() { + function toBeLessThan() { + return { + + compare: function(actual, expected) { + return { + pass: actual < expected + }; + } + }; + } + + return toBeLessThan; +}; +getJasmineRequireObj().toBeNaN = function(j$) { + + function toBeNaN() { + return { + compare: function(actual) { + var result = { + pass: (actual !== actual) + }; + + if (result.pass) { + result.message = 'Expected actual not to be NaN.'; + } else { + result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; }; + } + + return result; + } + }; + } + + return toBeNaN; +}; + +getJasmineRequireObj().toBeNull = function() { + + function toBeNull() { + return { + compare: function(actual) { + return { + pass: actual === null + }; + } + }; + } + + return toBeNull; +}; + +getJasmineRequireObj().toBeTruthy = function() { + + function toBeTruthy() { + return { + compare: function(actual) { + return { + pass: !!actual + }; + } + }; + } + + return toBeTruthy; +}; + +getJasmineRequireObj().toBeUndefined = function() { + + function toBeUndefined() { + return { + compare: function(actual) { + return { + pass: void 0 === actual + }; + } + }; + } + + return toBeUndefined; +}; + +getJasmineRequireObj().toContain = function() { + function toContain(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; + + return { + compare: function(actual, expected) { + + return { + pass: util.contains(actual, expected, customEqualityTesters) + }; + } + }; + } + + return toContain; +}; + +getJasmineRequireObj().toEqual = function() { + + function toEqual(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; + + return { + compare: function(actual, expected) { + var result = { + pass: false + }; + + result.pass = util.equals(actual, expected, customEqualityTesters); + + return result; + } + }; + } + + return toEqual; +}; + +getJasmineRequireObj().toHaveBeenCalled = function(j$) { + + function toHaveBeenCalled() { + return { + compare: function(actual) { + var result = {}; + + if (!j$.isSpy(actual)) { + throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); + } + + if (arguments.length > 1) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + result.pass = actual.calls.any(); + + result.message = result.pass ? + 'Expected spy ' + actual.and.identity() + ' not to have been called.' : + 'Expected spy ' + actual.and.identity() + ' to have been called.'; + + return result; + } + }; + } + + return toHaveBeenCalled; +}; + +getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { + + function toHaveBeenCalledWith(util, customEqualityTesters) { + return { + compare: function() { + var args = Array.prototype.slice.call(arguments, 0), + actual = args[0], + expectedArgs = args.slice(1), + result = { pass: false }; + + if (!j$.isSpy(actual)) { + throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); + } + + if (!actual.calls.any()) { + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; }; + return result; + } + + if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { + result.pass = true; + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; }; + } else { + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; }; + } + + return result; + } + }; + } + + return toHaveBeenCalledWith; +}; + +getJasmineRequireObj().toMatch = function() { + + function toMatch() { + return { + compare: function(actual, expected) { + var regexp = new RegExp(expected); + + return { + pass: regexp.test(actual) + }; + } + }; + } + + return toMatch; +}; + +getJasmineRequireObj().toThrow = function(j$) { + + function toThrow(util) { + return { + compare: function(actual, expected) { + var result = { pass: false }, + threw = false, + thrown; + + if (typeof actual != 'function') { + throw new Error('Actual is not a Function'); + } + + try { + actual(); + } catch (e) { + threw = true; + thrown = e; + } + + if (!threw) { + result.message = 'Expected function to throw an exception.'; + return result; + } + + if (arguments.length == 1) { + result.pass = true; + result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; }; + + return result; + } + + if (util.equals(thrown, expected)) { + result.pass = true; + result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; }; + } else { + result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' + j$.pp(thrown) + '.'; }; + } + + return result; + } + }; + } + + return toThrow; +}; + +getJasmineRequireObj().toThrowError = function(j$) { + function toThrowError (util) { + return { + compare: function(actual) { + var threw = false, + pass = {pass: true}, + fail = {pass: false}, + thrown, + errorType, + message, + regexp, + name, + constructorName; + + if (typeof actual != 'function') { + throw new Error('Actual is not a Function'); + } + + extractExpectedParams.apply(null, arguments); + + try { + actual(); + } catch (e) { + threw = true; + thrown = e; + } + + if (!threw) { + fail.message = 'Expected function to throw an Error.'; + return fail; + } + + if (!(thrown instanceof Error)) { + fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; + return fail; + } + + if (arguments.length == 1) { + pass.message = 'Expected function not to throw an Error, but it threw ' + fnNameFor(thrown) + '.'; + return pass; + } + + if (errorType) { + name = fnNameFor(errorType); + constructorName = fnNameFor(thrown.constructor); + } + + if (errorType && message) { + if (thrown.constructor == errorType && util.equals(thrown.message, message)) { + pass.message = function() { return 'Expected function not to throw ' + name + ' with message ' + j$.pp(message) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw ' + name + ' with message ' + j$.pp(message) + + ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } + + if (errorType && regexp) { + if (thrown.constructor == errorType && regexp.test(thrown.message)) { + pass.message = function() { return 'Expected function not to throw ' + name + ' with message matching ' + j$.pp(regexp) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw ' + name + ' with message matching ' + j$.pp(regexp) + + ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } + + if (errorType) { + if (thrown.constructor == errorType) { + pass.message = 'Expected function not to throw ' + name + '.'; + return pass; + } else { + fail.message = 'Expected function to throw ' + name + ', but it threw ' + constructorName + '.'; + return fail; + } + } + + if (message) { + if (thrown.message == message) { + pass.message = function() { return 'Expected function not to throw an exception with message ' + j$.pp(message) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw an exception with message ' + j$.pp(message) + + ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } + + if (regexp) { + if (regexp.test(thrown.message)) { + pass.message = function() { return 'Expected function not to throw an exception with a message matching ' + j$.pp(regexp) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw an exception with a message matching ' + j$.pp(regexp) + + ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } + + function fnNameFor(func) { + return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1]; + } + + function extractExpectedParams() { + if (arguments.length == 1) { + return; + } + + if (arguments.length == 2) { + var expected = arguments[1]; + + if (expected instanceof RegExp) { + regexp = expected; + } else if (typeof expected == 'string') { + message = expected; + } else if (checkForAnErrorType(expected)) { + errorType = expected; + } + + if (!(errorType || message || regexp)) { + throw new Error('Expected is not an Error, string, or RegExp.'); + } + } else { + if (checkForAnErrorType(arguments[1])) { + errorType = arguments[1]; + } else { + throw new Error('Expected error type is not an Error.'); + } + + if (arguments[2] instanceof RegExp) { + regexp = arguments[2]; + } else if (typeof arguments[2] == 'string') { + message = arguments[2]; + } else { + throw new Error('Expected error message is not a string or RegExp.'); + } + } + } + + function checkForAnErrorType(type) { + if (typeof type !== 'function') { + return false; + } + + var Surrogate = function() {}; + Surrogate.prototype = type.prototype; + return (new Surrogate()) instanceof Error; + } + } + }; + } + + return toThrowError; +}; + +getJasmineRequireObj().interface = function(jasmine, env) { + var jasmineInterface = { + describe: function(description, specDefinitions) { + return env.describe(description, specDefinitions); + }, + + xdescribe: function(description, specDefinitions) { + return env.xdescribe(description, specDefinitions); + }, + + it: function(desc, func) { + return env.it(desc, func); + }, + + xit: function(desc, func) { + return env.xit(desc, func); + }, + + beforeEach: function(beforeEachFunction) { + return env.beforeEach(beforeEachFunction); + }, + + afterEach: function(afterEachFunction) { + return env.afterEach(afterEachFunction); + }, + + expect: function(actual) { + return env.expect(actual); + }, + + pending: function() { + return env.pending(); + }, + + spyOn: function(obj, methodName) { + return env.spyOn(obj, methodName); + }, + + jsApiReporter: new jasmine.JsApiReporter({ + timer: new jasmine.Timer() + }), + + jasmine: jasmine + }; + + jasmine.addCustomEqualityTester = function(tester) { + env.addCustomEqualityTester(tester); + }; + + jasmine.addMatchers = function(matchers) { + return env.addMatchers(matchers); + }; + + jasmine.clock = function() { + return env.clock; + }; + + return jasmineInterface; +}; + +getJasmineRequireObj().version = function() { + return '2.0.2'; +}; diff --git a/tests/lib/jasmine-2.0.2/jasmine_favicon.png b/tests/lib/jasmine-2.0.2/jasmine_favicon.png new file mode 100755 index 00000000..3b84583b Binary files /dev/null and b/tests/lib/jasmine-2.0.2/jasmine_favicon.png differ diff --git a/tests/package.json b/tests/package.json new file mode 100644 index 00000000..40fd9673 --- /dev/null +++ b/tests/package.json @@ -0,0 +1,17 @@ +{ + "name": "PreloadJS-UnitTests", + "version": "0.0.1", + "description": "PreloadJS unit testing.", + "url": "http://www.createjs.com/#!/PreloadJS", + "logo": "assets/docs-icon-PreloadJS.png", + "devDependencies": { + "body-parser": "^1.9.2", + "grunt": "~0.4.5", + "grunt-contrib-connect": "^0.9.0", + "grunt-contrib-jasmine": "^0.8.2" + }, + "scripts": { + "next":"cd ../build/ && grunt nextlib && cd ../tests && grunt" + }, + "engine": "node >= 0.10.22" +} diff --git a/tests/spec/Helpers.js b/tests/spec/Helpers.js new file mode 100644 index 00000000..4bbbd257 --- /dev/null +++ b/tests/spec/Helpers.js @@ -0,0 +1,40 @@ +beforeEach(function () { + this.baseAssetsPath = "../_assets/"; + + this.getFilePath = function (fileObj) { + var path = ""; + if (typeof fileObj == "string") { + return this._formatFilePath(fileObj); + } else if (fileObj.src instanceof Array) { + for (var i=0;i= 0; i--) { + var cssRules = document.styleSheets[i].cssRules || + document.styleSheets[i].rules || []; // IE support + for (var c = 0; c < cssRules.length; c++) { + if (cssRules[c].selectorText === selector) { + return true; + } + } + } + return false; + } +}); diff --git a/tests/spec/LoadQueueSpec.js b/tests/spec/LoadQueueSpec.js new file mode 100644 index 00000000..317bea92 --- /dev/null +++ b/tests/spec/LoadQueueSpec.js @@ -0,0 +1,645 @@ +describe("PreloadJS.LoadQueue", function () { + + beforeEach(function () { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 2000; + + this.queue = new createjs.LoadQueue(); + + var _this = this; + this.loadFile = function (fileObj, preferXHR) { + if (preferXHR === false || preferXHR === true) { + _this.queue.preferXHR = preferXHR; + } + + if (typeof fileObj == "string"|| fileObj.src instanceof Array) { + _this.queue.loadFile(this.getFilePath(fileObj)); + } else { + fileObj.src = this.getFilePath(fileObj.src); + _this.queue.loadFile(fileObj); + } + } + }); + + describe("Tag Loading", function () { + beforeEach(function () { + this.queue.setPreferXHR(false); + jasmine.DEFAULT_TIMEOUT_INTERVAL = 9000; + }); + + it("should load JSONp", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toEqual(jasmine.any(Object)); + done(); + }); + this.loadFile({ + src: "static/jsonpSample.json", + callback: "x", + type: createjs.LoadQueue.JSONP + }, false); + }); + + it("should load and execute Javascript (tag)", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(window.foo).toBe(true); + + delete window.foo; + done(); + }); + this.loadFile("static/scriptExample.js", false); + }); + + it("should load and execute Javascript (tag) when maintainScriptOrder is false", function (done) { + + this.queue.addEventListener("fileload", function (evt) { + expect(window.foo).toBe(true); + + delete window.foo; + done(); + }); + + this.queue.maintainScriptOrder = false; + + this.loadFile("static/scriptExample.js", false); + }); + + it("should load svg", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result instanceof Object).toBeTruthy(); + done(); + }); + this.loadFile("art/gbot.svg", false); + }); + + it("should load sounds", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toEqual(jasmine.any(HTMLMediaElement)); + done(); + }); + + this.loadFile({ + src: "audio/Thunder.mp3", + type: createjs.AbstractLoader.SOUND + }); + }); + + it("should load video", function (done) { + this.queue.addEventListener("fileload", function (evt) { + evt.result.addEventListener("playing", function() { + expect(evt.result).toEqual(jasmine.any(HTMLMediaElement)); + done(); + }); + evt.result.play(); + }); + + this.loadFile({ + src: "static/video.mp4", + type: createjs.AbstractLoader.VIDEO + }, false); + }); + + it("should load an existing video tag", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toEqual(tag); + done(); + }); + + var tag = document.createElement("video"); + tag.src = "static/video.mp4"; + + this.queue.loadFile(tag); + }); + + it("should load an existing sound tag", function (done) { + this.queue.addEventListener("fileload", function (evt) { + evt.result.addEventListener("playing", function() { + expect(evt.result).toEqual(tag); + done(); + }) + + evt.result.play(); + }); + + var tag = document.createElement("audio"); + tag.src = "audio/Thunder.mp3"; + this.queue.loadFile(tag); + }); + + it("tag sound loading send progress events.", function (done) { + var _this = this; + + var func = { + progress: function () { } + }; + spyOn(func, 'progress'); + + var completeCallback = function (evt) { + expect(func.progress).toHaveBeenCalled(); + sound.removeEventListener("progress", func.progress); + done(); + }; + + var sound = new createjs.SoundLoader({ + src: "audio/Thunder.mp3", + type: createjs.LoadQueue.SOUND + }); + + sound.addEventListener("progress", func.progress); + sound.addEventListener("complete", completeCallback); + + sound.load(); + }); + + it("should load images (tag)", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toEqual(jasmine.any(HTMLImageElement)); + done(); + }); + this.loadFile("art/image0.jpg", false); + }); + + it("should load an existing image tag", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toEqual(tag); + done(); + }); + + var tag = document.createElement("img"); + tag.src = "art/image0.jpg"; + this.queue.loadFile(tag); + }); + + it("jsonP should error on a 404", function (done) { + this.queue.addEventListener("error", function (evt) { + expect(true).toBe(true); + done(); + }); + this.loadFile({ + src: "static/no_jsonp_here.json", + callback: "x", + type: createjs.LoadQueue.JSONP + }, false); + }); + }); + + describe("XHR Loading", function () { + it("should load XML", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toEqual(jasmine.any(Document)); + done(); + }); + this.loadFile("static/grant.xml"); + }); + + it("should load JSON", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toEqual(jasmine.any(Object)); + done(); + }); + this.loadFile("static/grant.json"); + }); + + it("should load and execute Javascript (xhr)", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(window.foo).toBe(true); + + delete window.foo; + done(); + }); + this.loadFile("static/scriptExample.js", true); + }); + + it("should load and execute Javascript (xhr) when maintainScriptOrder is false", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(window.foo).toBe(true); + + delete window.foo; + done(); + }); + + this.queue.maintainScriptOrder = false; + + this.loadFile("static/scriptExample.js", true); + }); + + it("should load css", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toEqual(jasmine.any(HTMLElement)); + done(); + }); + this.loadFile("static/font.css"); + }); + + it("should load images (xhr)", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toEqual(jasmine.any(HTMLImageElement)); + done(); + }); + this.loadFile("art/Autumn.png", true); + }); + + it("should load binary data", function (done) { + if (window['ArrayBuffer']) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toEqual(jasmine.any(ArrayBuffer)); + done(); + }); + this.loadFile({ + src: "audio/Thunder.mp3", + type: createjs.AbstractLoader.BINARY + }); + } else { + expect("IE 9").toBe("not working"); + done(); + } + }); + + it("should load svg (xhr)", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(typeof evt.result).toBe("object"); + done(); + }); + this.loadFile("art/gbot.svg", true); + }); + + it("should load text", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(typeof evt.result).toBe("string"); + done(); + }); + this.loadFile({src: "art/gbot.svg", type: createjs.LoadQueue.TEXT}); + }); + + describe("MediaElement Loading", function() { + it("should load sounds (xhr)", function (done) { + this.queue.addEventListener("fileload", function (evt) { + evt.result.addEventListener("playing", function() { + expect(evt.result).toEqual(jasmine.any(HTMLMediaElement)); + done(); + }); + evt.result.play(); + }); + + this.loadFile({ + src: "audio/Thunder.mp3", + type: createjs.AbstractLoader.SOUND + }, true); + }); + + it("should load video (xhr)", function (done) { + this.queue.addEventListener("fileload", function (evt) { + evt.result.addEventListener("playing", function() { + expect(evt.result).toEqual(jasmine.any(HTMLMediaElement)); + done(); + }); + evt.result.play(); + }); + + this.loadFile({ + src: "static/video.mp4", + type: createjs.AbstractLoader.VIDEO + }, true); + }); + }); + }); + + // This fails in Opera and IE (expected, as crossOrigin is not supported) + it("images should allow crossOrigin access", function (done) { + this.queue.addEventListener("fileload", function (evt) { + var canvas = document.createElement("canvas"); + var stage = new createjs.Stage(canvas); + var bmp = new createjs.Bitmap(evt.result); + + stage.addChild(bmp); + stage.update(); + + expect(stage.hitTest(35, 25)).toBe(true); + done(); + }); + + this.queue.loadFile({ + src: "http://dev.gskinner.com/createjs/cors/daisy.png", + crossOrigin: true + }); + }); + + it("should load a manifest and its children", function (done) { + var func = { + fileload: function () { + } + }; + + spyOn(func, "fileload"); + + this.queue.addEventListener("fileload", func.fileload); + + this.queue.addEventListener("complete", function (evt) { + expect(func.fileload.calls.count()).toBe(5); + done(); + }); + this.loadFile({ + src: "static/manifest.json", + type: createjs.LoadQueue.MANIFEST + }); + }); + + it("a SpriteSheetLoader should load a SpriteSheet uinsg JSON", function(done) { + var _this = this; + this.queue.addEventListener("complete", function (evt) { + expect(_this.queue.getResult("foo")).toEqual(jasmine.any(createjs.SpriteSheet)); + done(); + }); + this.loadFile({ + id:"foo", + src: "static/grant.json", + type: createjs.AbstractLoader.SPRITESHEET + }); + }); + + it("a SpriteSheetLoader should load a SpriteSheet using JSONp", function(done) { + var _this = this; + this.queue.addEventListener("complete", function (evt) { + expect(_this.queue.getResult("foo")).toEqual(jasmine.any(createjs.SpriteSheet)); + done(); + }); + this.loadFile({ + id:"foo", + src: "static/grantp.json", + callback:"grantp", + type: createjs.AbstractLoader.SPRITESHEET + }); + }); + + it("should send progress events.", function (done) { + var _this = this; + + var func = { + progress: function () { } + }; + spyOn(func, 'progress'); + + var completeCallback = function (evt) { + expect(func.progress).toHaveBeenCalled(); + _this.queue.removeEventListener("progress", func.progress); + done(); + }; + this.queue.addEventListener("progress", func.progress); + this.queue.addEventListener("complete", completeCallback); + + this.loadFile({ + src: "audio/Thunder.mp3", + type: createjs.LoadQueue.SOUND + }); + }); + + it("XHR should error on a 404", function (done) { + this.queue.addEventListener("error", function (evt) { + expect(evt.title).toBe("FILE_LOAD_ERROR"); + done(); + }); + this.loadFile("This_file_does_not_EXIST_.no"); + }); + + it("should pass data through to the complete handler", function (done) { + this.queue.addEventListener("fileload", function (evt) { + expect(evt.item.data).toBe("foo"); + done(); + }); + this.loadFile({ + src: "art/gbot.svg", + type: createjs.LoadQueue.TEXT, + data: "foo" + }); + }); + + it("should have custom plugins", function (done) { + var SamplePlugin = function () { + } + var s = SamplePlugin; + s.getPreloadHandlers = function () { + return { + callback: s.preloadHandler, // Proxy the method to maintain scope + types: [createjs.LoadQueue.JSON], + extensions: ["json"] + } + }; + + s.preloadHandler = function (loadItem) { + var options = {}; + + // Tell PreloadJS to skip this file + if (options.stopDownload) { + return false; + } + + // Tell PreloadJS to continue normally + if (options.doNothing) { + return true; + } + + loadItem.id = "foo"; + loadItem.data = "foo"; + + return true; // Allow the loader to load this. + }; + + this.queue.installPlugin(SamplePlugin); + + this.queue.addEventListener("fileload", function (evt) { + expect(evt.item.id).toBe("foo"); + expect(evt.item.data).toBe("foo"); + done(); + }); + this.loadFile("static/grant.json"); + }); + + it("should POST data.", function (done) { + var value = {foo: "bar"}; + this.queue.addEventListener("fileload", function (evt) { + expect(evt.result).toBe(JSON.stringify(value)); + done(); + }); + + // the grunt server will echo back whatever we send it. + this.loadFile({ + src: "", + method: createjs.LoadQueue.POST, + values: value + }); + }); + + it("should GET data.", function (done) { + // !!! If you change value.foo to something else teh Gruntfile connect.middleware function needs to be updated. + var value = {foo: "bar", bar: "foo"}; + + var q = new createjs.LoadQueue(); + + q.addEventListener("fileload", function (evt) { + expect(evt.result).toBe(JSON.stringify(value)); + done(); + }); + + // the grunt server will echo back whatever we send it. + q.loadFile({ + src: "/", + method: createjs.LoadQueue.GET, + values: value + }); + }); + + it("destroy() should remove all references in a LoadQueue", function () { + this.queue.addEventListener("fileload", function (evt) { + }); + this.loadFile({ + src: "art/gbot.svg", + type: createjs.LoadQueue.TEXT, + data: "foo" + }); + + this.queue.destroy(); + expect(this.queue.hasEventListener("fileload")).toBe(false); + expect(this.queue.getItem()).not.toBeDefined(); + expect(this.queue.getItem(true)).not.toBeDefined(); + }); + + it("removeAll() should remove all the items in a LoadQueue", function () { + this.queue.loadFile("foo.baz", false); + this.queue.loadFile("baz.foo", false); + expect(this.queue._numItems).toBe(2); + + this.queue.removeAll(); + + this.queue.load(); + + expect(this.queue._numItems).toBe(0); + }); + + it("remove by src should remove foo from the LoadQueue", function (done) { + var _this = this; + + this.queue.addEventListener("complete", function (evt) { + expect(_this.queue.getItem("foo")).toBeDefined(); + _this.queue.remove(_this.getFilePath("art/gbot.svg")); + expect(_this.queue.getItem("foo")).not.toBeDefined(); + done(); + }); + + this.loadFile({ + src: "art/gbot.svg", + id: "foo", + type: createjs.LoadQueue.TEXT, + data: "foo" + }); + }); + + it("remove by id should remove foo from the LoadQueue", function (done) { + var _this = this; + + this.queue.addEventListener("complete", function (evt) { + expect(_this.queue.getItem("foo")).toBeDefined(); + _this.queue.remove("foo"); + expect(_this.queue.getItem("foo")).not.toBeDefined(); + done(); + }); + + this.loadFile({ + src: "art/gbot.svg", + id: "foo", + type: createjs.LoadQueue.TEXT, + data: "foo" + }); + }); + + it("stopOnError should suppress events", function (done) { + var _this = this; + + var func = { + complete: function () { + + } + }; + + spyOn(func, 'complete'); + + setTimeout(function () { + expect(func.complete).not.toHaveBeenCalled(); + done(); + }, 750); + + this.queue.addEventListener("complete", func.complete); + this.queue.stopOnError = true; + this.queue.setMaxConnections(2); + this.queue.loadManifest(['static/manifest.json', "FileWill404.html", "static/grant.xml", "static/grant.json"], true); + + }); + + + describe("Font Loading", function () { + + it ("should load fonts by src", function(done) { + var func = { + fileload: function () { + } + }; + + spyOn(func, "fileload"); + + this.queue.addEventListener("fileload", func.fileload); + + this.queue.addEventListener("complete", function (evt) { + expect(func.fileload.calls.count()).toBe(1); + done(); + }); + + this.loadFile({ + src: "fonts/regul-bold.woff", + type: createjs.LoadQueue.FONT + }); + }); + + it ("should load fonts by array", function(done) { + var func = { + fileload: function () { + } + }; + + spyOn(func, "fileload"); + + this.queue.addEventListener("fileload", func.fileload); + + this.queue.addEventListener("complete", function (evt) { + expect(func.fileload.calls.count()).toBe(1); + done(); + }); + + this.loadFile({ + src: [ + "fonts/regul-book.woff", + "fonts/regul-bold.woff" + ], + type: createjs.LoadQueue.FONT + }); + }); + + it ("should load google fonts", function(done) { + var func = { + fileload: function () { + } + }; + + spyOn(func, "fileload"); + + this.queue.addEventListener("fileload", func.fileload); + + this.queue.addEventListener("complete", function (evt) { + expect(func.fileload.calls.count()).toBe(1); + done(); + }); + + this.loadFile({ + src: "https://fonts.googleapis.com/css?family=Roboto:400,700,400italic,700italic", + type: createjs.LoadQueue.FONTCSS + }); + }); + }); + +}); diff --git a/tests/tasks/findopenport.js b/tests/tasks/findopenport.js new file mode 100644 index 00000000..521c766d --- /dev/null +++ b/tests/tasks/findopenport.js @@ -0,0 +1,74 @@ +/* +* Copyright (c) 2014 gskinner.com, inc. +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following +* conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +*/ + +module.exports = function (grunt) { + var net = require('net'); + var _callback; + var _ports; + var _opts; + var _done; + + grunt.registerMultiTask('findopenport', 'Prints a list of active ips.', function() { + _opts = this.options(); + + _done = this.async(); + _ports = _opts['ports'] || [80, 8888, 9000, 9999, 9001]; + checkNext(); + }); + + function checkNext() { + if (!_ports.length) { + grunt.option(_portName, -1); + _done(); + return; + } + + check(_ports.shift(), function(success, port) { + if (!success) { + checkNext(); + } else { + //grunt.option(_portName, port); + var configNames = Array.isArray(_opts.configName)?_opts.configName:[_opts.configName]; + + configNames.forEach(function(item) { + grunt.config.set(item, port); + }); + _done(); + } + }); + } + + function check(port, callback) { + var server = net.createServer(); + server.on('error', function(e) { + callback(false, port); + }); + + server.listen(port, function() { + callback(true, port); + server.close(); + }); + } +}; diff --git a/tests/tasks/listips.js b/tests/tasks/listips.js new file mode 100644 index 00000000..7f9eb45a --- /dev/null +++ b/tests/tasks/listips.js @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2014 gskinner.com, inc. +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following +* conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +*/ + +module.exports = function (grunt) { + var os = require('os'); + + grunt.registerMultiTask('listips', 'Prints a list of active ips.', function() { + var opts = this.options({"port": 80}); + + var port = opts.port; + var label = opts.label?'('+opts.label+') ':''; + + if (port == 80) { + port = ''; + } else { + port = ':'+port; + } + + var interfaces = os.networkInterfaces(); + var addresses = []; + for (var n in interfaces) { + for (var n2 in interfaces[n]) { + var address = interfaces[n][n2]; + if (address.family == 'IPv4' && !address.internal) { + addresses.push('http://'+address.address+port); + } + } + } + + addresses.push('http://localhost'+port); + grunt.log.subhead('\n'+label+'Listening on:\n\t', addresses.join('\n\t ')); + }); +}