diff --git a/LICENCE b/LICENCE index 4acf216c70..4921a6055a 100644 --- a/LICENCE +++ b/LICENCE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2017 Sergey Rybalkin +Copyright (c) 2016-2018 Sergey Rybalkin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index ac8d226979..eb2a18210c 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,11 @@ [![Build Status](https://travis-ci.org/rybalkinsd/atom.png?branch=master)](https://travis-ci.org/rybalkinsd/atom) +[![](http://icons.iconarchive.com/icons/dakirby309/simply-styled/32/YouTube-icon.png) Youtube channel](https://www.youtube.com/playlist?list=PLrCZzMib1e9pnFbVV3u4s7ki5NTnm7WgT) - watch course videos -[![](http://icons.iconarchive.com/icons/alecive/flatwoken/32/Apps-Telegram-icon.png) Join chat](https://t.me/joinchat/AAAAAEF63F9PvqE4JDzYdQ) - feel free to contact us -[![](http://icons.iconarchive.com/icons/dakirby309/simply-styled/32/YouTube-icon.png) Youtube channel](https://www.youtube.com/playlist?list=PLrCZzMib1e9pnFbVV3u4s7ki5NTnm7WgT) +[![](http://icons.iconarchive.com/icons/alecive/flatwoken/32/Apps-Telegram-icon.png) Join chat](https://t.me/joinchat/AAISfEF63F8pPTObTsrR9w) - feel free to contact us Course repository. All course lectures/sources/homeworks are available here. - - -[![Course announcement](https://img.youtube.com/vi/12Ur1brHHz8/0.jpg)](https://www.youtube.com/watch?v=12Ur1brHHz8&feature=youtu.be "Course announcement") ## Lectures list: [Lecture 1. Basics, git](https://gitpitch.com/rybalkinsd/atom/lecture01?grs=github&t=white&p=lecture01%2Fpresentation#/) diff --git a/bomberman/.DS_Store b/bomberman/.DS_Store deleted file mode 100644 index 2b8883c189..0000000000 Binary files a/bomberman/.DS_Store and /dev/null differ diff --git a/bomberman/frontend/.DS_Store b/bomberman/frontend/.DS_Store deleted file mode 100644 index 81229e8d26..0000000000 Binary files a/bomberman/frontend/.DS_Store and /dev/null differ diff --git a/bomberman/frontend/Dockerfile b/bomberman/frontend/Dockerfile deleted file mode 100644 index ae387ba8c4..0000000000 --- a/bomberman/frontend/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM jetty:9.4.5-alpine -MAINTAINER Alex Pomosov -ADD ./build/libs/bomberman/*.war /var/lib/jetty/webapps/ROOT.war -EXPOSE 8080 \ No newline at end of file diff --git a/bomberman/frontend/build.gradle b/bomberman/frontend/build.gradle deleted file mode 100644 index d3b21134c0..0000000000 --- a/bomberman/frontend/build.gradle +++ /dev/null @@ -1 +0,0 @@ -apply plugin: 'war' diff --git a/bomberman/frontend/build/libs/bomberman/frontend-1.0-SNAPSHOT.war b/bomberman/frontend/build/libs/bomberman/frontend-1.0-SNAPSHOT.war deleted file mode 100644 index 6355eaa29b..0000000000 Binary files a/bomberman/frontend/build/libs/bomberman/frontend-1.0-SNAPSHOT.war and /dev/null differ diff --git a/bomberman/frontend/build/tmp/war/MANIFEST.MF b/bomberman/frontend/build/tmp/war/MANIFEST.MF deleted file mode 100644 index 58630c02ef..0000000000 --- a/bomberman/frontend/build/tmp/war/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 - diff --git a/bomberman/frontend/src/.DS_Store b/bomberman/frontend/src/.DS_Store deleted file mode 100644 index 254fc3aa65..0000000000 Binary files a/bomberman/frontend/src/.DS_Store and /dev/null differ diff --git a/bomberman/frontend/src/main/.DS_Store b/bomberman/frontend/src/main/.DS_Store deleted file mode 100644 index ec10f69338..0000000000 Binary files a/bomberman/frontend/src/main/.DS_Store and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/README.md b/bomberman/frontend/src/main/webapp/README.md deleted file mode 100644 index 529b54b080..0000000000 --- a/bomberman/frontend/src/main/webapp/README.md +++ /dev/null @@ -1,5 +0,0 @@ -This frontend is developed by: -- One-hand frontend developer -- QA specialist with mental dysfunction - -Enjoy, your [gojava](http://gojava.com) team. \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/css/bootstrap.css b/bomberman/frontend/src/main/webapp/css/bootstrap.css deleted file mode 100644 index 6167622cec..0000000000 --- a/bomberman/frontend/src/main/webapp/css/bootstrap.css +++ /dev/null @@ -1,6757 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ -html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -body { - margin: 0; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -menu, -nav, -section, -summary { - display: block; -} -audio, -canvas, -progress, -video { - display: inline-block; - vertical-align: baseline; -} -audio:not([controls]) { - display: none; - height: 0; -} -[hidden], -template { - display: none; -} -a { - background-color: transparent; -} -a:active, -a:hover { - outline: 0; -} -abbr[title] { - border-bottom: 1px dotted; -} -b, -strong { - font-weight: bold; -} -dfn { - font-style: italic; -} -h1 { - margin: .67em 0; - font-size: 2em; -} -mark { - color: #000; - background: #ff0; -} -small { - font-size: 80%; -} -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} -sup { - top: -.5em; -} -sub { - bottom: -.25em; -} -img { - border: 0; -} -svg:not(:root) { - overflow: hidden; -} -figure { - margin: 1em 40px; -} -hr { - height: 0; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -pre { - overflow: auto; -} -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} -button, -input, -optgroup, -select, -textarea { - margin: 0; - font: inherit; - color: inherit; -} -button { - overflow: visible; -} -button, -select { - text-transform: none; -} -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; - cursor: pointer; -} -button[disabled], -html input[disabled] { - cursor: default; -} -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} -input { - line-height: normal; -} -input[type="checkbox"], -input[type="radio"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0; -} -input[type="number"]::-webkit-inner-spin-button, -input[type="number"]::-webkit-outer-spin-button { - height: auto; -} -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} -fieldset { - padding: .35em .625em .75em; - margin: 0 2px; - border: 1px solid #c0c0c0; -} -legend { - padding: 0; - border: 0; -} -textarea { - overflow: auto; -} -optgroup { - font-weight: bold; -} -table { - border-spacing: 0; - border-collapse: collapse; -} -td, -th { - padding: 0; -} -/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ -@media print { - *, - *:before, - *:after { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - a[href^="#"]:after, - a[href^="javascript:"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } - .navbar { - display: none; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table td, - .table th { - background-color: #fff !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } -} -@font-face { - font-family: 'Glyphicons Halflings'; - - src: url('../fonts/glyphicons-halflings-regular.eot'); - src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); -} -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: normal; - line-height: 1; - - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.glyphicon-asterisk:before { - content: "\002a"; -} -.glyphicon-plus:before { - content: "\002b"; -} -.glyphicon-euro:before, -.glyphicon-eur:before { - content: "\20ac"; -} -.glyphicon-minus:before { - content: "\2212"; -} -.glyphicon-cloud:before { - content: "\2601"; -} -.glyphicon-envelope:before { - content: "\2709"; -} -.glyphicon-pencil:before { - content: "\270f"; -} -.glyphicon-glass:before { - content: "\e001"; -} -.glyphicon-music:before { - content: "\e002"; -} -.glyphicon-search:before { - content: "\e003"; -} -.glyphicon-heart:before { - content: "\e005"; -} -.glyphicon-star:before { - content: "\e006"; -} -.glyphicon-star-empty:before { - content: "\e007"; -} -.glyphicon-user:before { - content: "\e008"; -} -.glyphicon-film:before { - content: "\e009"; -} -.glyphicon-th-large:before { - content: "\e010"; -} -.glyphicon-th:before { - content: "\e011"; -} -.glyphicon-th-list:before { - content: "\e012"; -} -.glyphicon-ok:before { - content: "\e013"; -} -.glyphicon-remove:before { - content: "\e014"; -} -.glyphicon-zoom-in:before { - content: "\e015"; -} -.glyphicon-zoom-out:before { - content: "\e016"; -} -.glyphicon-off:before { - content: "\e017"; -} -.glyphicon-signal:before { - content: "\e018"; -} -.glyphicon-cog:before { - content: "\e019"; -} -.glyphicon-trash:before { - content: "\e020"; -} -.glyphicon-home:before { - content: "\e021"; -} -.glyphicon-file:before { - content: "\e022"; -} -.glyphicon-time:before { - content: "\e023"; -} -.glyphicon-road:before { - content: "\e024"; -} -.glyphicon-download-alt:before { - content: "\e025"; -} -.glyphicon-download:before { - content: "\e026"; -} -.glyphicon-upload:before { - content: "\e027"; -} -.glyphicon-inbox:before { - content: "\e028"; -} -.glyphicon-play-circle:before { - content: "\e029"; -} -.glyphicon-repeat:before { - content: "\e030"; -} -.glyphicon-refresh:before { - content: "\e031"; -} -.glyphicon-list-alt:before { - content: "\e032"; -} -.glyphicon-lock:before { - content: "\e033"; -} -.glyphicon-flag:before { - content: "\e034"; -} -.glyphicon-headphones:before { - content: "\e035"; -} -.glyphicon-volume-off:before { - content: "\e036"; -} -.glyphicon-volume-down:before { - content: "\e037"; -} -.glyphicon-volume-up:before { - content: "\e038"; -} -.glyphicon-qrcode:before { - content: "\e039"; -} -.glyphicon-barcode:before { - content: "\e040"; -} -.glyphicon-tag:before { - content: "\e041"; -} -.glyphicon-tags:before { - content: "\e042"; -} -.glyphicon-book:before { - content: "\e043"; -} -.glyphicon-bookmark:before { - content: "\e044"; -} -.glyphicon-print:before { - content: "\e045"; -} -.glyphicon-camera:before { - content: "\e046"; -} -.glyphicon-font:before { - content: "\e047"; -} -.glyphicon-bold:before { - content: "\e048"; -} -.glyphicon-italic:before { - content: "\e049"; -} -.glyphicon-text-height:before { - content: "\e050"; -} -.glyphicon-text-width:before { - content: "\e051"; -} -.glyphicon-align-left:before { - content: "\e052"; -} -.glyphicon-align-center:before { - content: "\e053"; -} -.glyphicon-align-right:before { - content: "\e054"; -} -.glyphicon-align-justify:before { - content: "\e055"; -} -.glyphicon-list:before { - content: "\e056"; -} -.glyphicon-indent-left:before { - content: "\e057"; -} -.glyphicon-indent-right:before { - content: "\e058"; -} -.glyphicon-facetime-video:before { - content: "\e059"; -} -.glyphicon-picture:before { - content: "\e060"; -} -.glyphicon-map-marker:before { - content: "\e062"; -} -.glyphicon-adjust:before { - content: "\e063"; -} -.glyphicon-tint:before { - content: "\e064"; -} -.glyphicon-edit:before { - content: "\e065"; -} -.glyphicon-share:before { - content: "\e066"; -} -.glyphicon-check:before { - content: "\e067"; -} -.glyphicon-move:before { - content: "\e068"; -} -.glyphicon-step-backward:before { - content: "\e069"; -} -.glyphicon-fast-backward:before { - content: "\e070"; -} -.glyphicon-backward:before { - content: "\e071"; -} -.glyphicon-play:before { - content: "\e072"; -} -.glyphicon-pause:before { - content: "\e073"; -} -.glyphicon-stop:before { - content: "\e074"; -} -.glyphicon-forward:before { - content: "\e075"; -} -.glyphicon-fast-forward:before { - content: "\e076"; -} -.glyphicon-step-forward:before { - content: "\e077"; -} -.glyphicon-eject:before { - content: "\e078"; -} -.glyphicon-chevron-left:before { - content: "\e079"; -} -.glyphicon-chevron-right:before { - content: "\e080"; -} -.glyphicon-plus-sign:before { - content: "\e081"; -} -.glyphicon-minus-sign:before { - content: "\e082"; -} -.glyphicon-remove-sign:before { - content: "\e083"; -} -.glyphicon-ok-sign:before { - content: "\e084"; -} -.glyphicon-question-sign:before { - content: "\e085"; -} -.glyphicon-info-sign:before { - content: "\e086"; -} -.glyphicon-screenshot:before { - content: "\e087"; -} -.glyphicon-remove-circle:before { - content: "\e088"; -} -.glyphicon-ok-circle:before { - content: "\e089"; -} -.glyphicon-ban-circle:before { - content: "\e090"; -} -.glyphicon-arrow-left:before { - content: "\e091"; -} -.glyphicon-arrow-right:before { - content: "\e092"; -} -.glyphicon-arrow-up:before { - content: "\e093"; -} -.glyphicon-arrow-down:before { - content: "\e094"; -} -.glyphicon-share-alt:before { - content: "\e095"; -} -.glyphicon-resize-full:before { - content: "\e096"; -} -.glyphicon-resize-small:before { - content: "\e097"; -} -.glyphicon-exclamation-sign:before { - content: "\e101"; -} -.glyphicon-gift:before { - content: "\e102"; -} -.glyphicon-leaf:before { - content: "\e103"; -} -.glyphicon-fire:before { - content: "\e104"; -} -.glyphicon-eye-open:before { - content: "\e105"; -} -.glyphicon-eye-close:before { - content: "\e106"; -} -.glyphicon-warning-sign:before { - content: "\e107"; -} -.glyphicon-plane:before { - content: "\e108"; -} -.glyphicon-calendar:before { - content: "\e109"; -} -.glyphicon-random:before { - content: "\e110"; -} -.glyphicon-comment:before { - content: "\e111"; -} -.glyphicon-magnet:before { - content: "\e112"; -} -.glyphicon-chevron-up:before { - content: "\e113"; -} -.glyphicon-chevron-down:before { - content: "\e114"; -} -.glyphicon-retweet:before { - content: "\e115"; -} -.glyphicon-shopping-cart:before { - content: "\e116"; -} -.glyphicon-folder-close:before { - content: "\e117"; -} -.glyphicon-folder-open:before { - content: "\e118"; -} -.glyphicon-resize-vertical:before { - content: "\e119"; -} -.glyphicon-resize-horizontal:before { - content: "\e120"; -} -.glyphicon-hdd:before { - content: "\e121"; -} -.glyphicon-bullhorn:before { - content: "\e122"; -} -.glyphicon-bell:before { - content: "\e123"; -} -.glyphicon-certificate:before { - content: "\e124"; -} -.glyphicon-thumbs-up:before { - content: "\e125"; -} -.glyphicon-thumbs-down:before { - content: "\e126"; -} -.glyphicon-hand-right:before { - content: "\e127"; -} -.glyphicon-hand-left:before { - content: "\e128"; -} -.glyphicon-hand-up:before { - content: "\e129"; -} -.glyphicon-hand-down:before { - content: "\e130"; -} -.glyphicon-circle-arrow-right:before { - content: "\e131"; -} -.glyphicon-circle-arrow-left:before { - content: "\e132"; -} -.glyphicon-circle-arrow-up:before { - content: "\e133"; -} -.glyphicon-circle-arrow-down:before { - content: "\e134"; -} -.glyphicon-globe:before { - content: "\e135"; -} -.glyphicon-wrench:before { - content: "\e136"; -} -.glyphicon-tasks:before { - content: "\e137"; -} -.glyphicon-filter:before { - content: "\e138"; -} -.glyphicon-briefcase:before { - content: "\e139"; -} -.glyphicon-fullscreen:before { - content: "\e140"; -} -.glyphicon-dashboard:before { - content: "\e141"; -} -.glyphicon-paperclip:before { - content: "\e142"; -} -.glyphicon-heart-empty:before { - content: "\e143"; -} -.glyphicon-link:before { - content: "\e144"; -} -.glyphicon-phone:before { - content: "\e145"; -} -.glyphicon-pushpin:before { - content: "\e146"; -} -.glyphicon-usd:before { - content: "\e148"; -} -.glyphicon-gbp:before { - content: "\e149"; -} -.glyphicon-sort:before { - content: "\e150"; -} -.glyphicon-sort-by-alphabet:before { - content: "\e151"; -} -.glyphicon-sort-by-alphabet-alt:before { - content: "\e152"; -} -.glyphicon-sort-by-order:before { - content: "\e153"; -} -.glyphicon-sort-by-order-alt:before { - content: "\e154"; -} -.glyphicon-sort-by-attributes:before { - content: "\e155"; -} -.glyphicon-sort-by-attributes-alt:before { - content: "\e156"; -} -.glyphicon-unchecked:before { - content: "\e157"; -} -.glyphicon-expand:before { - content: "\e158"; -} -.glyphicon-collapse-down:before { - content: "\e159"; -} -.glyphicon-collapse-up:before { - content: "\e160"; -} -.glyphicon-log-in:before { - content: "\e161"; -} -.glyphicon-flash:before { - content: "\e162"; -} -.glyphicon-log-out:before { - content: "\e163"; -} -.glyphicon-new-window:before { - content: "\e164"; -} -.glyphicon-record:before { - content: "\e165"; -} -.glyphicon-save:before { - content: "\e166"; -} -.glyphicon-open:before { - content: "\e167"; -} -.glyphicon-saved:before { - content: "\e168"; -} -.glyphicon-import:before { - content: "\e169"; -} -.glyphicon-export:before { - content: "\e170"; -} -.glyphicon-send:before { - content: "\e171"; -} -.glyphicon-floppy-disk:before { - content: "\e172"; -} -.glyphicon-floppy-saved:before { - content: "\e173"; -} -.glyphicon-floppy-remove:before { - content: "\e174"; -} -.glyphicon-floppy-save:before { - content: "\e175"; -} -.glyphicon-floppy-open:before { - content: "\e176"; -} -.glyphicon-credit-card:before { - content: "\e177"; -} -.glyphicon-transfer:before { - content: "\e178"; -} -.glyphicon-cutlery:before { - content: "\e179"; -} -.glyphicon-header:before { - content: "\e180"; -} -.glyphicon-compressed:before { - content: "\e181"; -} -.glyphicon-earphone:before { - content: "\e182"; -} -.glyphicon-phone-alt:before { - content: "\e183"; -} -.glyphicon-tower:before { - content: "\e184"; -} -.glyphicon-stats:before { - content: "\e185"; -} -.glyphicon-sd-video:before { - content: "\e186"; -} -.glyphicon-hd-video:before { - content: "\e187"; -} -.glyphicon-subtitles:before { - content: "\e188"; -} -.glyphicon-sound-stereo:before { - content: "\e189"; -} -.glyphicon-sound-dolby:before { - content: "\e190"; -} -.glyphicon-sound-5-1:before { - content: "\e191"; -} -.glyphicon-sound-6-1:before { - content: "\e192"; -} -.glyphicon-sound-7-1:before { - content: "\e193"; -} -.glyphicon-copyright-mark:before { - content: "\e194"; -} -.glyphicon-registration-mark:before { - content: "\e195"; -} -.glyphicon-cloud-download:before { - content: "\e197"; -} -.glyphicon-cloud-upload:before { - content: "\e198"; -} -.glyphicon-tree-conifer:before { - content: "\e199"; -} -.glyphicon-tree-deciduous:before { - content: "\e200"; -} -.glyphicon-cd:before { - content: "\e201"; -} -.glyphicon-save-file:before { - content: "\e202"; -} -.glyphicon-open-file:before { - content: "\e203"; -} -.glyphicon-level-up:before { - content: "\e204"; -} -.glyphicon-copy:before { - content: "\e205"; -} -.glyphicon-paste:before { - content: "\e206"; -} -.glyphicon-alert:before { - content: "\e209"; -} -.glyphicon-equalizer:before { - content: "\e210"; -} -.glyphicon-king:before { - content: "\e211"; -} -.glyphicon-queen:before { - content: "\e212"; -} -.glyphicon-pawn:before { - content: "\e213"; -} -.glyphicon-bishop:before { - content: "\e214"; -} -.glyphicon-knight:before { - content: "\e215"; -} -.glyphicon-baby-formula:before { - content: "\e216"; -} -.glyphicon-tent:before { - content: "\26fa"; -} -.glyphicon-blackboard:before { - content: "\e218"; -} -.glyphicon-bed:before { - content: "\e219"; -} -.glyphicon-apple:before { - content: "\f8ff"; -} -.glyphicon-erase:before { - content: "\e221"; -} -.glyphicon-hourglass:before { - content: "\231b"; -} -.glyphicon-lamp:before { - content: "\e223"; -} -.glyphicon-duplicate:before { - content: "\e224"; -} -.glyphicon-piggy-bank:before { - content: "\e225"; -} -.glyphicon-scissors:before { - content: "\e226"; -} -.glyphicon-bitcoin:before { - content: "\e227"; -} -.glyphicon-btc:before { - content: "\e227"; -} -.glyphicon-xbt:before { - content: "\e227"; -} -.glyphicon-yen:before { - content: "\00a5"; -} -.glyphicon-jpy:before { - content: "\00a5"; -} -.glyphicon-ruble:before { - content: "\20bd"; -} -.glyphicon-rub:before { - content: "\20bd"; -} -.glyphicon-scale:before { - content: "\e230"; -} -.glyphicon-ice-lolly:before { - content: "\e231"; -} -.glyphicon-ice-lolly-tasted:before { - content: "\e232"; -} -.glyphicon-education:before { - content: "\e233"; -} -.glyphicon-option-horizontal:before { - content: "\e234"; -} -.glyphicon-option-vertical:before { - content: "\e235"; -} -.glyphicon-menu-hamburger:before { - content: "\e236"; -} -.glyphicon-modal-window:before { - content: "\e237"; -} -.glyphicon-oil:before { - content: "\e238"; -} -.glyphicon-grain:before { - content: "\e239"; -} -.glyphicon-sunglasses:before { - content: "\e240"; -} -.glyphicon-text-size:before { - content: "\e241"; -} -.glyphicon-text-color:before { - content: "\e242"; -} -.glyphicon-text-background:before { - content: "\e243"; -} -.glyphicon-object-align-top:before { - content: "\e244"; -} -.glyphicon-object-align-bottom:before { - content: "\e245"; -} -.glyphicon-object-align-horizontal:before { - content: "\e246"; -} -.glyphicon-object-align-left:before { - content: "\e247"; -} -.glyphicon-object-align-vertical:before { - content: "\e248"; -} -.glyphicon-object-align-right:before { - content: "\e249"; -} -.glyphicon-triangle-right:before { - content: "\e250"; -} -.glyphicon-triangle-left:before { - content: "\e251"; -} -.glyphicon-triangle-bottom:before { - content: "\e252"; -} -.glyphicon-triangle-top:before { - content: "\e253"; -} -.glyphicon-console:before { - content: "\e254"; -} -.glyphicon-superscript:before { - content: "\e255"; -} -.glyphicon-subscript:before { - content: "\e256"; -} -.glyphicon-menu-left:before { - content: "\e257"; -} -.glyphicon-menu-right:before { - content: "\e258"; -} -.glyphicon-menu-down:before { - content: "\e259"; -} -.glyphicon-menu-up:before { - content: "\e260"; -} -* { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -*:before, -*:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -html { - font-size: 10px; - - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - color: #333; - background-color: #fff; -} -input, -button, -select, -textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; -} -a { - color: #337ab7; - text-decoration: none; -} -a:hover, -a:focus { - color: #23527c; - text-decoration: underline; -} -a:focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -figure { - margin: 0; -} -img { - vertical-align: middle; -} -.img-responsive, -.thumbnail > img, -.thumbnail a > img, -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - max-width: 100%; - height: auto; -} -.img-rounded { - border-radius: 6px; -} -.img-thumbnail { - display: inline-block; - max-width: 100%; - height: auto; - padding: 4px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - -o-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; -} -.img-circle { - border-radius: 50%; -} -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eee; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} -[role="button"] { - cursor: pointer; -} -h1, -h2, -h3, -h4, -h5, -h6, -.h1, -.h2, -.h3, -.h4, -.h5, -.h6 { - font-family: inherit; - font-weight: 500; - line-height: 1.1; - color: inherit; -} -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small, -.h1 small, -.h2 small, -.h3 small, -.h4 small, -.h5 small, -.h6 small, -h1 .small, -h2 .small, -h3 .small, -h4 .small, -h5 .small, -h6 .small, -.h1 .small, -.h2 .small, -.h3 .small, -.h4 .small, -.h5 .small, -.h6 .small { - font-weight: normal; - line-height: 1; - color: #777; -} -h1, -.h1, -h2, -.h2, -h3, -.h3 { - margin-top: 20px; - margin-bottom: 10px; -} -h1 small, -.h1 small, -h2 small, -.h2 small, -h3 small, -.h3 small, -h1 .small, -.h1 .small, -h2 .small, -.h2 .small, -h3 .small, -.h3 .small { - font-size: 65%; -} -h4, -.h4, -h5, -.h5, -h6, -.h6 { - margin-top: 10px; - margin-bottom: 10px; -} -h4 small, -.h4 small, -h5 small, -.h5 small, -h6 small, -.h6 small, -h4 .small, -.h4 .small, -h5 .small, -.h5 .small, -h6 .small, -.h6 .small { - font-size: 75%; -} -h1, -.h1 { - font-size: 36px; -} -h2, -.h2 { - font-size: 30px; -} -h3, -.h3 { - font-size: 24px; -} -h4, -.h4 { - font-size: 18px; -} -h5, -.h5 { - font-size: 14px; -} -h6, -.h6 { - font-size: 12px; -} -p { - margin: 0 0 10px; -} -.lead { - margin-bottom: 20px; - font-size: 16px; - font-weight: 300; - line-height: 1.4; -} -@media (min-width: 768px) { - .lead { - font-size: 21px; - } -} -small, -.small { - font-size: 85%; -} -mark, -.mark { - padding: .2em; - background-color: #fcf8e3; -} -.text-left { - text-align: left; -} -.text-right { - text-align: right; -} -.text-center { - text-align: center; -} -.text-justify { - text-align: justify; -} -.text-nowrap { - white-space: nowrap; -} -.text-lowercase { - text-transform: lowercase; -} -.text-uppercase { - text-transform: uppercase; -} -.text-capitalize { - text-transform: capitalize; -} -.text-muted { - color: #777; -} -.text-primary { - color: #337ab7; -} -a.text-primary:hover, -a.text-primary:focus { - color: #286090; -} -.text-success { - color: #3c763d; -} -a.text-success:hover, -a.text-success:focus { - color: #2b542c; -} -.text-info { - color: #31708f; -} -a.text-info:hover, -a.text-info:focus { - color: #245269; -} -.text-warning { - color: #8a6d3b; -} -a.text-warning:hover, -a.text-warning:focus { - color: #66512c; -} -.text-danger { - color: #a94442; -} -a.text-danger:hover, -a.text-danger:focus { - color: #843534; -} -.bg-primary { - color: #fff; - background-color: #337ab7; -} -a.bg-primary:hover, -a.bg-primary:focus { - background-color: #286090; -} -.bg-success { - background-color: #dff0d8; -} -a.bg-success:hover, -a.bg-success:focus { - background-color: #c1e2b3; -} -.bg-info { - background-color: #d9edf7; -} -a.bg-info:hover, -a.bg-info:focus { - background-color: #afd9ee; -} -.bg-warning { - background-color: #fcf8e3; -} -a.bg-warning:hover, -a.bg-warning:focus { - background-color: #f7ecb5; -} -.bg-danger { - background-color: #f2dede; -} -a.bg-danger:hover, -a.bg-danger:focus { - background-color: #e4b9b9; -} -.page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eee; -} -ul, -ol { - margin-top: 0; - margin-bottom: 10px; -} -ul ul, -ol ul, -ul ol, -ol ol { - margin-bottom: 0; -} -.list-unstyled { - padding-left: 0; - list-style: none; -} -.list-inline { - padding-left: 0; - margin-left: -5px; - list-style: none; -} -.list-inline > li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; -} -dl { - margin-top: 0; - margin-bottom: 20px; -} -dt, -dd { - line-height: 1.42857143; -} -dt { - font-weight: bold; -} -dd { - margin-left: 0; -} -@media (min-width: 768px) { - .dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - } - .dl-horizontal dd { - margin-left: 180px; - } -} -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #777; -} -.initialism { - font-size: 90%; - text-transform: uppercase; -} -blockquote { - padding: 10px 20px; - margin: 0 0 20px; - font-size: 17.5px; - border-left: 5px solid #eee; -} -blockquote p:last-child, -blockquote ul:last-child, -blockquote ol:last-child { - margin-bottom: 0; -} -blockquote footer, -blockquote small, -blockquote .small { - display: block; - font-size: 80%; - line-height: 1.42857143; - color: #777; -} -blockquote footer:before, -blockquote small:before, -blockquote .small:before { - content: '\2014 \00A0'; -} -.blockquote-reverse, -blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - text-align: right; - border-right: 5px solid #eee; - border-left: 0; -} -.blockquote-reverse footer:before, -blockquote.pull-right footer:before, -.blockquote-reverse small:before, -blockquote.pull-right small:before, -.blockquote-reverse .small:before, -blockquote.pull-right .small:before { - content: ''; -} -.blockquote-reverse footer:after, -blockquote.pull-right footer:after, -.blockquote-reverse small:after, -blockquote.pull-right small:after, -.blockquote-reverse .small:after, -blockquote.pull-right .small:after { - content: '\00A0 \2014'; -} -address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.42857143; -} -code, -kbd, -pre, -samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; -} -code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - background-color: #f9f2f4; - border-radius: 4px; -} -kbd { - padding: 2px 4px; - font-size: 90%; - color: #fff; - background-color: #333; - border-radius: 3px; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); -} -kbd kbd { - padding: 0; - font-size: 100%; - font-weight: bold; - -webkit-box-shadow: none; - box-shadow: none; -} -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: #333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - border-radius: 4px; -} -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; -} -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} -.container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -@media (min-width: 768px) { - .container { - width: 750px; - } -} -@media (min-width: 992px) { - .container { - width: 970px; - } -} -@media (min-width: 1200px) { - .container { - width: 1170px; - } -} -.container-fluid { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -.row { - margin-right: -15px; - margin-left: -15px; -} -.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; -} -.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { - float: left; -} -.col-xs-12 { - width: 100%; -} -.col-xs-11 { - width: 91.66666667%; -} -.col-xs-10 { - width: 83.33333333%; -} -.col-xs-9 { - width: 75%; -} -.col-xs-8 { - width: 66.66666667%; -} -.col-xs-7 { - width: 58.33333333%; -} -.col-xs-6 { - width: 50%; -} -.col-xs-5 { - width: 41.66666667%; -} -.col-xs-4 { - width: 33.33333333%; -} -.col-xs-3 { - width: 25%; -} -.col-xs-2 { - width: 16.66666667%; -} -.col-xs-1 { - width: 8.33333333%; -} -.col-xs-pull-12 { - right: 100%; -} -.col-xs-pull-11 { - right: 91.66666667%; -} -.col-xs-pull-10 { - right: 83.33333333%; -} -.col-xs-pull-9 { - right: 75%; -} -.col-xs-pull-8 { - right: 66.66666667%; -} -.col-xs-pull-7 { - right: 58.33333333%; -} -.col-xs-pull-6 { - right: 50%; -} -.col-xs-pull-5 { - right: 41.66666667%; -} -.col-xs-pull-4 { - right: 33.33333333%; -} -.col-xs-pull-3 { - right: 25%; -} -.col-xs-pull-2 { - right: 16.66666667%; -} -.col-xs-pull-1 { - right: 8.33333333%; -} -.col-xs-pull-0 { - right: auto; -} -.col-xs-push-12 { - left: 100%; -} -.col-xs-push-11 { - left: 91.66666667%; -} -.col-xs-push-10 { - left: 83.33333333%; -} -.col-xs-push-9 { - left: 75%; -} -.col-xs-push-8 { - left: 66.66666667%; -} -.col-xs-push-7 { - left: 58.33333333%; -} -.col-xs-push-6 { - left: 50%; -} -.col-xs-push-5 { - left: 41.66666667%; -} -.col-xs-push-4 { - left: 33.33333333%; -} -.col-xs-push-3 { - left: 25%; -} -.col-xs-push-2 { - left: 16.66666667%; -} -.col-xs-push-1 { - left: 8.33333333%; -} -.col-xs-push-0 { - left: auto; -} -.col-xs-offset-12 { - margin-left: 100%; -} -.col-xs-offset-11 { - margin-left: 91.66666667%; -} -.col-xs-offset-10 { - margin-left: 83.33333333%; -} -.col-xs-offset-9 { - margin-left: 75%; -} -.col-xs-offset-8 { - margin-left: 66.66666667%; -} -.col-xs-offset-7 { - margin-left: 58.33333333%; -} -.col-xs-offset-6 { - margin-left: 50%; -} -.col-xs-offset-5 { - margin-left: 41.66666667%; -} -.col-xs-offset-4 { - margin-left: 33.33333333%; -} -.col-xs-offset-3 { - margin-left: 25%; -} -.col-xs-offset-2 { - margin-left: 16.66666667%; -} -.col-xs-offset-1 { - margin-left: 8.33333333%; -} -.col-xs-offset-0 { - margin-left: 0; -} -@media (min-width: 768px) { - .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { - float: left; - } - .col-sm-12 { - width: 100%; - } - .col-sm-11 { - width: 91.66666667%; - } - .col-sm-10 { - width: 83.33333333%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666667%; - } - .col-sm-7 { - width: 58.33333333%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666667%; - } - .col-sm-4 { - width: 33.33333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.66666667%; - } - .col-sm-1 { - width: 8.33333333%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666667%; - } - .col-sm-pull-10 { - right: 83.33333333%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666667%; - } - .col-sm-pull-7 { - right: 58.33333333%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666667%; - } - .col-sm-pull-4 { - right: 33.33333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.66666667%; - } - .col-sm-pull-1 { - right: 8.33333333%; - } - .col-sm-pull-0 { - right: auto; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666667%; - } - .col-sm-push-10 { - left: 83.33333333%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666667%; - } - .col-sm-push-7 { - left: 58.33333333%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666667%; - } - .col-sm-push-4 { - left: 33.33333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.66666667%; - } - .col-sm-push-1 { - left: 8.33333333%; - } - .col-sm-push-0 { - left: auto; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666667%; - } - .col-sm-offset-10 { - margin-left: 83.33333333%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666667%; - } - .col-sm-offset-7 { - margin-left: 58.33333333%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.66666667%; - } - .col-sm-offset-1 { - margin-left: 8.33333333%; - } - .col-sm-offset-0 { - margin-left: 0; - } -} -@media (min-width: 992px) { - .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: auto; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: auto; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .col-md-offset-0 { - margin-left: 0; - } -} -@media (min-width: 1200px) { - .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: auto; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: auto; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0; - } -} -table { - background-color: transparent; -} -caption { - padding-top: 8px; - padding-bottom: 8px; - color: #777; - text-align: left; -} -th { - text-align: left; -} -.table { - width: 100%; - max-width: 100%; - margin-bottom: 20px; -} -.table > thead > tr > th, -.table > tbody > tr > th, -.table > tfoot > tr > th, -.table > thead > tr > td, -.table > tbody > tr > td, -.table > tfoot > tr > td { - padding: 8px; - line-height: 1.42857143; - vertical-align: top; - border-top: 1px solid #ddd; -} -.table > thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #ddd; -} -.table > caption + thead > tr:first-child > th, -.table > colgroup + thead > tr:first-child > th, -.table > thead:first-child > tr:first-child > th, -.table > caption + thead > tr:first-child > td, -.table > colgroup + thead > tr:first-child > td, -.table > thead:first-child > tr:first-child > td { - border-top: 0; -} -.table > tbody + tbody { - border-top: 2px solid #ddd; -} -.table .table { - background-color: #fff; -} -.table-condensed > thead > tr > th, -.table-condensed > tbody > tr > th, -.table-condensed > tfoot > tr > th, -.table-condensed > thead > tr > td, -.table-condensed > tbody > tr > td, -.table-condensed > tfoot > tr > td { - padding: 5px; -} -.table-bordered { - border: 1px solid #ddd; -} -.table-bordered > thead > tr > th, -.table-bordered > tbody > tr > th, -.table-bordered > tfoot > tr > th, -.table-bordered > thead > tr > td, -.table-bordered > tbody > tr > td, -.table-bordered > tfoot > tr > td { - border: 1px solid #ddd; -} -.table-bordered > thead > tr > th, -.table-bordered > thead > tr > td { - border-bottom-width: 2px; -} -.table-striped > tbody > tr:nth-of-type(odd) { - background-color: #f9f9f9; -} -.table-hover > tbody > tr:hover { - background-color: #f5f5f5; -} -table col[class*="col-"] { - position: static; - display: table-column; - float: none; -} -table td[class*="col-"], -table th[class*="col-"] { - position: static; - display: table-cell; - float: none; -} -.table > thead > tr > td.active, -.table > tbody > tr > td.active, -.table > tfoot > tr > td.active, -.table > thead > tr > th.active, -.table > tbody > tr > th.active, -.table > tfoot > tr > th.active, -.table > thead > tr.active > td, -.table > tbody > tr.active > td, -.table > tfoot > tr.active > td, -.table > thead > tr.active > th, -.table > tbody > tr.active > th, -.table > tfoot > tr.active > th { - background-color: #f5f5f5; -} -.table-hover > tbody > tr > td.active:hover, -.table-hover > tbody > tr > th.active:hover, -.table-hover > tbody > tr.active:hover > td, -.table-hover > tbody > tr:hover > .active, -.table-hover > tbody > tr.active:hover > th { - background-color: #e8e8e8; -} -.table > thead > tr > td.success, -.table > tbody > tr > td.success, -.table > tfoot > tr > td.success, -.table > thead > tr > th.success, -.table > tbody > tr > th.success, -.table > tfoot > tr > th.success, -.table > thead > tr.success > td, -.table > tbody > tr.success > td, -.table > tfoot > tr.success > td, -.table > thead > tr.success > th, -.table > tbody > tr.success > th, -.table > tfoot > tr.success > th { - background-color: #dff0d8; -} -.table-hover > tbody > tr > td.success:hover, -.table-hover > tbody > tr > th.success:hover, -.table-hover > tbody > tr.success:hover > td, -.table-hover > tbody > tr:hover > .success, -.table-hover > tbody > tr.success:hover > th { - background-color: #d0e9c6; -} -.table > thead > tr > td.info, -.table > tbody > tr > td.info, -.table > tfoot > tr > td.info, -.table > thead > tr > th.info, -.table > tbody > tr > th.info, -.table > tfoot > tr > th.info, -.table > thead > tr.info > td, -.table > tbody > tr.info > td, -.table > tfoot > tr.info > td, -.table > thead > tr.info > th, -.table > tbody > tr.info > th, -.table > tfoot > tr.info > th { - background-color: #d9edf7; -} -.table-hover > tbody > tr > td.info:hover, -.table-hover > tbody > tr > th.info:hover, -.table-hover > tbody > tr.info:hover > td, -.table-hover > tbody > tr:hover > .info, -.table-hover > tbody > tr.info:hover > th { - background-color: #c4e3f3; -} -.table > thead > tr > td.warning, -.table > tbody > tr > td.warning, -.table > tfoot > tr > td.warning, -.table > thead > tr > th.warning, -.table > tbody > tr > th.warning, -.table > tfoot > tr > th.warning, -.table > thead > tr.warning > td, -.table > tbody > tr.warning > td, -.table > tfoot > tr.warning > td, -.table > thead > tr.warning > th, -.table > tbody > tr.warning > th, -.table > tfoot > tr.warning > th { - background-color: #fcf8e3; -} -.table-hover > tbody > tr > td.warning:hover, -.table-hover > tbody > tr > th.warning:hover, -.table-hover > tbody > tr.warning:hover > td, -.table-hover > tbody > tr:hover > .warning, -.table-hover > tbody > tr.warning:hover > th { - background-color: #faf2cc; -} -.table > thead > tr > td.danger, -.table > tbody > tr > td.danger, -.table > tfoot > tr > td.danger, -.table > thead > tr > th.danger, -.table > tbody > tr > th.danger, -.table > tfoot > tr > th.danger, -.table > thead > tr.danger > td, -.table > tbody > tr.danger > td, -.table > tfoot > tr.danger > td, -.table > thead > tr.danger > th, -.table > tbody > tr.danger > th, -.table > tfoot > tr.danger > th { - background-color: #f2dede; -} -.table-hover > tbody > tr > td.danger:hover, -.table-hover > tbody > tr > th.danger:hover, -.table-hover > tbody > tr.danger:hover > td, -.table-hover > tbody > tr:hover > .danger, -.table-hover > tbody > tr.danger:hover > th { - background-color: #ebcccc; -} -.table-responsive { - min-height: .01%; - overflow-x: auto; -} -@media screen and (max-width: 767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-y: hidden; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid #ddd; - } - .table-responsive > .table { - margin-bottom: 0; - } - .table-responsive > .table > thead > tr > th, - .table-responsive > .table > tbody > tr > th, - .table-responsive > .table > tfoot > tr > th, - .table-responsive > .table > thead > tr > td, - .table-responsive > .table > tbody > tr > td, - .table-responsive > .table > tfoot > tr > td { - white-space: nowrap; - } - .table-responsive > .table-bordered { - border: 0; - } - .table-responsive > .table-bordered > thead > tr > th:first-child, - .table-responsive > .table-bordered > tbody > tr > th:first-child, - .table-responsive > .table-bordered > tfoot > tr > th:first-child, - .table-responsive > .table-bordered > thead > tr > td:first-child, - .table-responsive > .table-bordered > tbody > tr > td:first-child, - .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; - } - .table-responsive > .table-bordered > thead > tr > th:last-child, - .table-responsive > .table-bordered > tbody > tr > th:last-child, - .table-responsive > .table-bordered > tfoot > tr > th:last-child, - .table-responsive > .table-bordered > thead > tr > td:last-child, - .table-responsive > .table-bordered > tbody > tr > td:last-child, - .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; - } - .table-responsive > .table-bordered > tbody > tr:last-child > th, - .table-responsive > .table-bordered > tfoot > tr:last-child > th, - .table-responsive > .table-bordered > tbody > tr:last-child > td, - .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; - } -} -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; -} -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} -label { - display: inline-block; - max-width: 100%; - margin-bottom: 5px; - font-weight: bold; -} -input[type="search"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - line-height: normal; -} -input[type="file"] { - display: block; -} -input[type="range"] { - display: block; - width: 100%; -} -select[multiple], -select[size] { - height: auto; -} -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.42857143; - color: #555; -} -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - color: #555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; - -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -} -.form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); -} -.form-control::-moz-placeholder { - color: #999; - opacity: 1; -} -.form-control:-ms-input-placeholder { - color: #999; -} -.form-control::-webkit-input-placeholder { - color: #999; -} -.form-control::-ms-expand { - background-color: transparent; - border: 0; -} -.form-control[disabled], -.form-control[readonly], -fieldset[disabled] .form-control { - background-color: #eee; - opacity: 1; -} -.form-control[disabled], -fieldset[disabled] .form-control { - cursor: not-allowed; -} -textarea.form-control { - height: auto; -} -input[type="search"] { - -webkit-appearance: none; -} -@media screen and (-webkit-min-device-pixel-ratio: 0) { - input[type="date"].form-control, - input[type="time"].form-control, - input[type="datetime-local"].form-control, - input[type="month"].form-control { - line-height: 34px; - } - input[type="date"].input-sm, - input[type="time"].input-sm, - input[type="datetime-local"].input-sm, - input[type="month"].input-sm, - .input-group-sm input[type="date"], - .input-group-sm input[type="time"], - .input-group-sm input[type="datetime-local"], - .input-group-sm input[type="month"] { - line-height: 30px; - } - input[type="date"].input-lg, - input[type="time"].input-lg, - input[type="datetime-local"].input-lg, - input[type="month"].input-lg, - .input-group-lg input[type="date"], - .input-group-lg input[type="time"], - .input-group-lg input[type="datetime-local"], - .input-group-lg input[type="month"] { - line-height: 46px; - } -} -.form-group { - margin-bottom: 15px; -} -.radio, -.checkbox { - position: relative; - display: block; - margin-top: 10px; - margin-bottom: 10px; -} -.radio label, -.checkbox label { - min-height: 20px; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - cursor: pointer; -} -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - position: absolute; - margin-top: 4px \9; - margin-left: -20px; -} -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; -} -.radio-inline, -.checkbox-inline { - position: relative; - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - vertical-align: middle; - cursor: pointer; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; -} -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"].disabled, -input[type="checkbox"].disabled, -fieldset[disabled] input[type="radio"], -fieldset[disabled] input[type="checkbox"] { - cursor: not-allowed; -} -.radio-inline.disabled, -.checkbox-inline.disabled, -fieldset[disabled] .radio-inline, -fieldset[disabled] .checkbox-inline { - cursor: not-allowed; -} -.radio.disabled label, -.checkbox.disabled label, -fieldset[disabled] .radio label, -fieldset[disabled] .checkbox label { - cursor: not-allowed; -} -.form-control-static { - min-height: 34px; - padding-top: 7px; - padding-bottom: 7px; - margin-bottom: 0; -} -.form-control-static.input-lg, -.form-control-static.input-sm { - padding-right: 0; - padding-left: 0; -} -.input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-sm { - height: 30px; - line-height: 30px; -} -textarea.input-sm, -select[multiple].input-sm { - height: auto; -} -.form-group-sm .form-control { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.form-group-sm select.form-control { - height: 30px; - line-height: 30px; -} -.form-group-sm textarea.form-control, -.form-group-sm select[multiple].form-control { - height: auto; -} -.form-group-sm .form-control-static { - height: 30px; - min-height: 32px; - padding: 6px 10px; - font-size: 12px; - line-height: 1.5; -} -.input-lg { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -select.input-lg { - height: 46px; - line-height: 46px; -} -textarea.input-lg, -select[multiple].input-lg { - height: auto; -} -.form-group-lg .form-control { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -.form-group-lg select.form-control { - height: 46px; - line-height: 46px; -} -.form-group-lg textarea.form-control, -.form-group-lg select[multiple].form-control { - height: auto; -} -.form-group-lg .form-control-static { - height: 46px; - min-height: 38px; - padding: 11px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.has-feedback { - position: relative; -} -.has-feedback .form-control { - padding-right: 42.5px; -} -.form-control-feedback { - position: absolute; - top: 0; - right: 0; - z-index: 2; - display: block; - width: 34px; - height: 34px; - line-height: 34px; - text-align: center; - pointer-events: none; -} -.input-lg + .form-control-feedback, -.input-group-lg + .form-control-feedback, -.form-group-lg .form-control + .form-control-feedback { - width: 46px; - height: 46px; - line-height: 46px; -} -.input-sm + .form-control-feedback, -.input-group-sm + .form-control-feedback, -.form-group-sm .form-control + .form-control-feedback { - width: 30px; - height: 30px; - line-height: 30px; -} -.has-success .help-block, -.has-success .control-label, -.has-success .radio, -.has-success .checkbox, -.has-success .radio-inline, -.has-success .checkbox-inline, -.has-success.radio label, -.has-success.checkbox label, -.has-success.radio-inline label, -.has-success.checkbox-inline label { - color: #3c763d; -} -.has-success .form-control { - border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-success .form-control:focus { - border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; -} -.has-success .input-group-addon { - color: #3c763d; - background-color: #dff0d8; - border-color: #3c763d; -} -.has-success .form-control-feedback { - color: #3c763d; -} -.has-warning .help-block, -.has-warning .control-label, -.has-warning .radio, -.has-warning .checkbox, -.has-warning .radio-inline, -.has-warning .checkbox-inline, -.has-warning.radio label, -.has-warning.checkbox label, -.has-warning.radio-inline label, -.has-warning.checkbox-inline label { - color: #8a6d3b; -} -.has-warning .form-control { - border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-warning .form-control:focus { - border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; -} -.has-warning .input-group-addon { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #8a6d3b; -} -.has-warning .form-control-feedback { - color: #8a6d3b; -} -.has-error .help-block, -.has-error .control-label, -.has-error .radio, -.has-error .checkbox, -.has-error .radio-inline, -.has-error .checkbox-inline, -.has-error.radio label, -.has-error.checkbox label, -.has-error.radio-inline label, -.has-error.checkbox-inline label { - color: #a94442; -} -.has-error .form-control { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-error .form-control:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; -} -.has-error .input-group-addon { - color: #a94442; - background-color: #f2dede; - border-color: #a94442; -} -.has-error .form-control-feedback { - color: #a94442; -} -.has-feedback label ~ .form-control-feedback { - top: 25px; -} -.has-feedback label.sr-only ~ .form-control-feedback { - top: 0; -} -.help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373; -} -@media (min-width: 768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .form-inline .form-control-static { - display: inline-block; - } - .form-inline .input-group { - display: inline-table; - vertical-align: middle; - } - .form-inline .input-group .input-group-addon, - .form-inline .input-group .input-group-btn, - .form-inline .input-group .form-control { - width: auto; - } - .form-inline .input-group > .form-control { - width: 100%; - } - .form-inline .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio, - .form-inline .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio label, - .form-inline .checkbox label { - padding-left: 0; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .form-inline .has-feedback .form-control-feedback { - top: 0; - } -} -.form-horizontal .radio, -.form-horizontal .checkbox, -.form-horizontal .radio-inline, -.form-horizontal .checkbox-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0; -} -.form-horizontal .radio, -.form-horizontal .checkbox { - min-height: 27px; -} -.form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .form-horizontal .control-label { - padding-top: 7px; - margin-bottom: 0; - text-align: right; - } -} -.form-horizontal .has-feedback .form-control-feedback { - right: 15px; -} -@media (min-width: 768px) { - .form-horizontal .form-group-lg .control-label { - padding-top: 11px; - font-size: 18px; - } -} -@media (min-width: 768px) { - .form-horizontal .form-group-sm .control-label { - padding-top: 6px; - font-size: 12px; - } -} -.btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: normal; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -ms-touch-action: manipulation; - touch-action: manipulation; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -.btn:focus, -.btn:active:focus, -.btn.active:focus, -.btn.focus, -.btn:active.focus, -.btn.active.focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.btn:hover, -.btn:focus, -.btn.focus { - color: #333; - text-decoration: none; -} -.btn:active, -.btn.active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -} -.btn.disabled, -.btn[disabled], -fieldset[disabled] .btn { - cursor: not-allowed; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; - opacity: .65; -} -a.btn.disabled, -fieldset[disabled] a.btn { - pointer-events: none; -} -.btn-default { - color: #333; - background-color: #fff; - border-color: #ccc; -} -.btn-default:focus, -.btn-default.focus { - color: #333; - background-color: #e6e6e6; - border-color: #8c8c8c; -} -.btn-default:hover { - color: #333; - background-color: #e6e6e6; - border-color: #adadad; -} -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - color: #333; - background-color: #e6e6e6; - border-color: #adadad; -} -.btn-default:active:hover, -.btn-default.active:hover, -.open > .dropdown-toggle.btn-default:hover, -.btn-default:active:focus, -.btn-default.active:focus, -.open > .dropdown-toggle.btn-default:focus, -.btn-default:active.focus, -.btn-default.active.focus, -.open > .dropdown-toggle.btn-default.focus { - color: #333; - background-color: #d4d4d4; - border-color: #8c8c8c; -} -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - background-image: none; -} -.btn-default.disabled:hover, -.btn-default[disabled]:hover, -fieldset[disabled] .btn-default:hover, -.btn-default.disabled:focus, -.btn-default[disabled]:focus, -fieldset[disabled] .btn-default:focus, -.btn-default.disabled.focus, -.btn-default[disabled].focus, -fieldset[disabled] .btn-default.focus { - background-color: #fff; - border-color: #ccc; -} -.btn-default .badge { - color: #fff; - background-color: #333; -} -.btn-primary { - color: #fff; - background-color: #337ab7; - border-color: #2e6da4; -} -.btn-primary:focus, -.btn-primary.focus { - color: #fff; - background-color: #286090; - border-color: #122b40; -} -.btn-primary:hover { - color: #fff; - background-color: #286090; - border-color: #204d74; -} -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - color: #fff; - background-color: #286090; - border-color: #204d74; -} -.btn-primary:active:hover, -.btn-primary.active:hover, -.open > .dropdown-toggle.btn-primary:hover, -.btn-primary:active:focus, -.btn-primary.active:focus, -.open > .dropdown-toggle.btn-primary:focus, -.btn-primary:active.focus, -.btn-primary.active.focus, -.open > .dropdown-toggle.btn-primary.focus { - color: #fff; - background-color: #204d74; - border-color: #122b40; -} -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - background-image: none; -} -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled.focus, -.btn-primary[disabled].focus, -fieldset[disabled] .btn-primary.focus { - background-color: #337ab7; - border-color: #2e6da4; -} -.btn-primary .badge { - color: #337ab7; - background-color: #fff; -} -.btn-success { - color: #fff; - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success:focus, -.btn-success.focus { - color: #fff; - background-color: #449d44; - border-color: #255625; -} -.btn-success:hover { - color: #fff; - background-color: #449d44; - border-color: #398439; -} -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - color: #fff; - background-color: #449d44; - border-color: #398439; -} -.btn-success:active:hover, -.btn-success.active:hover, -.open > .dropdown-toggle.btn-success:hover, -.btn-success:active:focus, -.btn-success.active:focus, -.open > .dropdown-toggle.btn-success:focus, -.btn-success:active.focus, -.btn-success.active.focus, -.open > .dropdown-toggle.btn-success.focus { - color: #fff; - background-color: #398439; - border-color: #255625; -} -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - background-image: none; -} -.btn-success.disabled:hover, -.btn-success[disabled]:hover, -fieldset[disabled] .btn-success:hover, -.btn-success.disabled:focus, -.btn-success[disabled]:focus, -fieldset[disabled] .btn-success:focus, -.btn-success.disabled.focus, -.btn-success[disabled].focus, -fieldset[disabled] .btn-success.focus { - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success .badge { - color: #5cb85c; - background-color: #fff; -} -.btn-info { - color: #fff; - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-info:focus, -.btn-info.focus { - color: #fff; - background-color: #31b0d5; - border-color: #1b6d85; -} -.btn-info:hover { - color: #fff; - background-color: #31b0d5; - border-color: #269abc; -} -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - color: #fff; - background-color: #31b0d5; - border-color: #269abc; -} -.btn-info:active:hover, -.btn-info.active:hover, -.open > .dropdown-toggle.btn-info:hover, -.btn-info:active:focus, -.btn-info.active:focus, -.open > .dropdown-toggle.btn-info:focus, -.btn-info:active.focus, -.btn-info.active.focus, -.open > .dropdown-toggle.btn-info.focus { - color: #fff; - background-color: #269abc; - border-color: #1b6d85; -} -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - background-image: none; -} -.btn-info.disabled:hover, -.btn-info[disabled]:hover, -fieldset[disabled] .btn-info:hover, -.btn-info.disabled:focus, -.btn-info[disabled]:focus, -fieldset[disabled] .btn-info:focus, -.btn-info.disabled.focus, -.btn-info[disabled].focus, -fieldset[disabled] .btn-info.focus { - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-info .badge { - color: #5bc0de; - background-color: #fff; -} -.btn-warning { - color: #fff; - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning:focus, -.btn-warning.focus { - color: #fff; - background-color: #ec971f; - border-color: #985f0d; -} -.btn-warning:hover { - color: #fff; - background-color: #ec971f; - border-color: #d58512; -} -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - color: #fff; - background-color: #ec971f; - border-color: #d58512; -} -.btn-warning:active:hover, -.btn-warning.active:hover, -.open > .dropdown-toggle.btn-warning:hover, -.btn-warning:active:focus, -.btn-warning.active:focus, -.open > .dropdown-toggle.btn-warning:focus, -.btn-warning:active.focus, -.btn-warning.active.focus, -.open > .dropdown-toggle.btn-warning.focus { - color: #fff; - background-color: #d58512; - border-color: #985f0d; -} -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - background-image: none; -} -.btn-warning.disabled:hover, -.btn-warning[disabled]:hover, -fieldset[disabled] .btn-warning:hover, -.btn-warning.disabled:focus, -.btn-warning[disabled]:focus, -fieldset[disabled] .btn-warning:focus, -.btn-warning.disabled.focus, -.btn-warning[disabled].focus, -fieldset[disabled] .btn-warning.focus { - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning .badge { - color: #f0ad4e; - background-color: #fff; -} -.btn-danger { - color: #fff; - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger:focus, -.btn-danger.focus { - color: #fff; - background-color: #c9302c; - border-color: #761c19; -} -.btn-danger:hover { - color: #fff; - background-color: #c9302c; - border-color: #ac2925; -} -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - color: #fff; - background-color: #c9302c; - border-color: #ac2925; -} -.btn-danger:active:hover, -.btn-danger.active:hover, -.open > .dropdown-toggle.btn-danger:hover, -.btn-danger:active:focus, -.btn-danger.active:focus, -.open > .dropdown-toggle.btn-danger:focus, -.btn-danger:active.focus, -.btn-danger.active.focus, -.open > .dropdown-toggle.btn-danger.focus { - color: #fff; - background-color: #ac2925; - border-color: #761c19; -} -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - background-image: none; -} -.btn-danger.disabled:hover, -.btn-danger[disabled]:hover, -fieldset[disabled] .btn-danger:hover, -.btn-danger.disabled:focus, -.btn-danger[disabled]:focus, -fieldset[disabled] .btn-danger:focus, -.btn-danger.disabled.focus, -.btn-danger[disabled].focus, -fieldset[disabled] .btn-danger.focus { - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger .badge { - color: #d9534f; - background-color: #fff; -} -.btn-link { - font-weight: normal; - color: #337ab7; - border-radius: 0; -} -.btn-link, -.btn-link:active, -.btn-link.active, -.btn-link[disabled], -fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; -} -.btn-link, -.btn-link:hover, -.btn-link:focus, -.btn-link:active { - border-color: transparent; -} -.btn-link:hover, -.btn-link:focus { - color: #23527c; - text-decoration: underline; - background-color: transparent; -} -.btn-link[disabled]:hover, -fieldset[disabled] .btn-link:hover, -.btn-link[disabled]:focus, -fieldset[disabled] .btn-link:focus { - color: #777; - text-decoration: none; -} -.btn-lg, -.btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -.btn-sm, -.btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-xs, -.btn-group-xs > .btn { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-block { - display: block; - width: 100%; -} -.btn-block + .btn-block { - margin-top: 5px; -} -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} -.fade { - opacity: 0; - -webkit-transition: opacity .15s linear; - -o-transition: opacity .15s linear; - transition: opacity .15s linear; -} -.fade.in { - opacity: 1; -} -.collapse { - display: none; -} -.collapse.in { - display: block; -} -tr.collapse.in { - display: table-row; -} -tbody.collapse.in { - display: table-row-group; -} -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition-timing-function: ease; - -o-transition-timing-function: ease; - transition-timing-function: ease; - -webkit-transition-duration: .35s; - -o-transition-duration: .35s; - transition-duration: .35s; - -webkit-transition-property: height, visibility; - -o-transition-property: height, visibility; - transition-property: height, visibility; -} -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px dashed; - border-top: 4px solid \9; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} -.dropup, -.dropdown { - position: relative; -} -.dropdown-toggle:focus { - outline: 0; -} -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); - box-shadow: 0 6px 12px rgba(0, 0, 0, .175); -} -.dropdown-menu.pull-right { - right: 0; - left: auto; -} -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.42857143; - color: #333; - white-space: nowrap; -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - color: #262626; - text-decoration: none; - background-color: #f5f5f5; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #fff; - text-decoration: none; - background-color: #337ab7; - outline: 0; -} -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #777; -} -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.open > .dropdown-menu { - display: block; -} -.open > a { - outline: 0; -} -.dropdown-menu-right { - right: 0; - left: auto; -} -.dropdown-menu-left { - right: auto; - left: 0; -} -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #777; - white-space: nowrap; -} -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px dashed; - border-bottom: 4px solid \9; -} -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 2px; -} -@media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0; - } -} -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; -} -.btn-group > .btn, -.btn-group-vertical > .btn { - position: relative; - float: left; -} -.btn-group > .btn:hover, -.btn-group-vertical > .btn:hover, -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus, -.btn-group > .btn:active, -.btn-group-vertical > .btn:active, -.btn-group > .btn.active, -.btn-group-vertical > .btn.active { - z-index: 2; -} -.btn-group .btn + .btn, -.btn-group .btn + .btn-group, -.btn-group .btn-group + .btn, -.btn-group .btn-group + .btn-group { - margin-left: -1px; -} -.btn-toolbar { - margin-left: -5px; -} -.btn-toolbar .btn, -.btn-toolbar .btn-group, -.btn-toolbar .input-group { - float: left; -} -.btn-toolbar > .btn, -.btn-toolbar > .btn-group, -.btn-toolbar > .input-group { - margin-left: 5px; -} -.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} -.btn-group > .btn:first-child { - margin-left: 0; -} -.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group > .btn-group { - float: left; -} -.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, -.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} -.btn-group > .btn + .dropdown-toggle { - padding-right: 8px; - padding-left: 8px; -} -.btn-group > .btn-lg + .dropdown-toggle { - padding-right: 12px; - padding-left: 12px; -} -.btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -} -.btn-group.open .dropdown-toggle.btn-link { - -webkit-box-shadow: none; - box-shadow: none; -} -.btn .caret { - margin-left: 0; -} -.btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0; -} -.dropup .btn-lg .caret { - border-width: 0 5px 5px; -} -.btn-group-vertical > .btn, -.btn-group-vertical > .btn-group, -.btn-group-vertical > .btn-group > .btn { - display: block; - float: none; - width: 100%; - max-width: 100%; -} -.btn-group-vertical > .btn-group > .btn { - float: none; -} -.btn-group-vertical > .btn + .btn, -.btn-group-vertical > .btn + .btn-group, -.btn-group-vertical > .btn-group + .btn, -.btn-group-vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; -} -.btn-group-vertical > .btn:not(:first-child):not(:last-child) { - border-radius: 0; -} -.btn-group-vertical > .btn:first-child:not(:last-child) { - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn:last-child:not(:first-child) { - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, -.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; -} -.btn-group-justified > .btn, -.btn-group-justified > .btn-group { - display: table-cell; - float: none; - width: 1%; -} -.btn-group-justified > .btn-group .btn { - width: 100%; -} -.btn-group-justified > .btn-group .dropdown-menu { - left: auto; -} -[data-toggle="buttons"] > .btn input[type="radio"], -[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], -[data-toggle="buttons"] > .btn input[type="checkbox"], -[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none; -} -.input-group { - position: relative; - display: table; - border-collapse: separate; -} -.input-group[class*="col-"] { - float: none; - padding-right: 0; - padding-left: 0; -} -.input-group .form-control { - position: relative; - z-index: 2; - float: left; - width: 100%; - margin-bottom: 0; -} -.input-group .form-control:focus { - z-index: 3; -} -.input-group-lg > .form-control, -.input-group-lg > .input-group-addon, -.input-group-lg > .input-group-btn > .btn { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -select.input-group-lg > .form-control, -select.input-group-lg > .input-group-addon, -select.input-group-lg > .input-group-btn > .btn { - height: 46px; - line-height: 46px; -} -textarea.input-group-lg > .form-control, -textarea.input-group-lg > .input-group-addon, -textarea.input-group-lg > .input-group-btn > .btn, -select[multiple].input-group-lg > .form-control, -select[multiple].input-group-lg > .input-group-addon, -select[multiple].input-group-lg > .input-group-btn > .btn { - height: auto; -} -.input-group-sm > .form-control, -.input-group-sm > .input-group-addon, -.input-group-sm > .input-group-btn > .btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-group-sm > .form-control, -select.input-group-sm > .input-group-addon, -select.input-group-sm > .input-group-btn > .btn { - height: 30px; - line-height: 30px; -} -textarea.input-group-sm > .form-control, -textarea.input-group-sm > .input-group-addon, -textarea.input-group-sm > .input-group-btn > .btn, -select[multiple].input-group-sm > .form-control, -select[multiple].input-group-sm > .input-group-addon, -select[multiple].input-group-sm > .input-group-btn > .btn { - height: auto; -} -.input-group-addon, -.input-group-btn, -.input-group .form-control { - display: table-cell; -} -.input-group-addon:not(:first-child):not(:last-child), -.input-group-btn:not(:first-child):not(:last-child), -.input-group .form-control:not(:first-child):not(:last-child) { - border-radius: 0; -} -.input-group-addon, -.input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; -} -.input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: normal; - line-height: 1; - color: #555; - text-align: center; - background-color: #eee; - border: 1px solid #ccc; - border-radius: 4px; -} -.input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px; -} -.input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px; -} -.input-group-addon input[type="radio"], -.input-group-addon input[type="checkbox"] { - margin-top: 0; -} -.input-group .form-control:first-child, -.input-group-addon:first-child, -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group > .btn, -.input-group-btn:first-child > .dropdown-toggle, -.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), -.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.input-group-addon:first-child { - border-right: 0; -} -.input-group .form-control:last-child, -.input-group-addon:last-child, -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group > .btn, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child), -.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.input-group-addon:last-child { - border-left: 0; -} -.input-group-btn { - position: relative; - font-size: 0; - white-space: nowrap; -} -.input-group-btn > .btn { - position: relative; -} -.input-group-btn > .btn + .btn { - margin-left: -1px; -} -.input-group-btn > .btn:hover, -.input-group-btn > .btn:focus, -.input-group-btn > .btn:active { - z-index: 2; -} -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group { - margin-right: -1px; -} -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group { - z-index: 2; - margin-left: -1px; -} -.nav { - padding-left: 0; - margin-bottom: 0; - list-style: none; -} -.nav > li { - position: relative; - display: block; -} -.nav > li > a { - position: relative; - display: block; - padding: 10px 15px; -} -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eee; -} -.nav > li.disabled > a { - color: #777; -} -.nav > li.disabled > a:hover, -.nav > li.disabled > a:focus { - color: #777; - text-decoration: none; - cursor: not-allowed; - background-color: transparent; -} -.nav .open > a, -.nav .open > a:hover, -.nav .open > a:focus { - background-color: #eee; - border-color: #337ab7; -} -.nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.nav > li > a > img { - max-width: none; -} -.nav-tabs { - border-bottom: 1px solid #ddd; -} -.nav-tabs > li { - float: left; - margin-bottom: -1px; -} -.nav-tabs > li > a { - margin-right: 2px; - line-height: 1.42857143; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; -} -.nav-tabs > li > a:hover { - border-color: #eee #eee #ddd; -} -.nav-tabs > li.active > a, -.nav-tabs > li.active > a:hover, -.nav-tabs > li.active > a:focus { - color: #555; - cursor: default; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; -} -.nav-tabs.nav-justified > li { - float: none; -} -.nav-tabs.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.nav-tabs.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-tabs.nav-justified > li > a { - margin-bottom: 0; - } -} -.nav-tabs.nav-justified > li > a { - margin-right: 0; - border-radius: 4px; -} -.nav-tabs.nav-justified > .active > a, -.nav-tabs.nav-justified > .active > a:hover, -.nav-tabs.nav-justified > .active > a:focus { - border: 1px solid #ddd; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs.nav-justified > .active > a, - .nav-tabs.nav-justified > .active > a:hover, - .nav-tabs.nav-justified > .active > a:focus { - border-bottom-color: #fff; - } -} -.nav-pills > li { - float: left; -} -.nav-pills > li > a { - border-radius: 4px; -} -.nav-pills > li + li { - margin-left: 2px; -} -.nav-pills > li.active > a, -.nav-pills > li.active > a:hover, -.nav-pills > li.active > a:focus { - color: #fff; - background-color: #337ab7; -} -.nav-stacked > li { - float: none; -} -.nav-stacked > li + li { - margin-top: 2px; - margin-left: 0; -} -.nav-justified { - width: 100%; -} -.nav-justified > li { - float: none; -} -.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} -@media (min-width: 768px) { - .nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-justified > li > a { - margin-bottom: 0; - } -} -.nav-tabs-justified { - border-bottom: 0; -} -.nav-tabs-justified > li > a { - margin-right: 0; - border-radius: 4px; -} -.nav-tabs-justified > .active > a, -.nav-tabs-justified > .active > a:hover, -.nav-tabs-justified > .active > a:focus { - border: 1px solid #ddd; -} -@media (min-width: 768px) { - .nav-tabs-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs-justified > .active > a, - .nav-tabs-justified > .active > a:hover, - .nav-tabs-justified > .active > a:focus { - border-bottom-color: #fff; - } -} -.tab-content > .tab-pane { - display: none; -} -.tab-content > .active { - display: block; -} -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent; -} -@media (min-width: 768px) { - .navbar { - border-radius: 4px; - } -} -@media (min-width: 768px) { - .navbar-header { - float: left; - } -} -.navbar-collapse { - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - -webkit-overflow-scrolling: touch; - border-top: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); -} -.navbar-collapse.in { - overflow-y: auto; -} -@media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important; - } - .navbar-collapse.in { - overflow-y: visible; - } - .navbar-fixed-top .navbar-collapse, - .navbar-static-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - padding-right: 0; - padding-left: 0; - } -} -.navbar-fixed-top .navbar-collapse, -.navbar-fixed-bottom .navbar-collapse { - max-height: 340px; -} -@media (max-device-width: 480px) and (orientation: landscape) { - .navbar-fixed-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - max-height: 200px; - } -} -.container > .navbar-header, -.container-fluid > .navbar-header, -.container > .navbar-collapse, -.container-fluid > .navbar-collapse { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .container > .navbar-header, - .container-fluid > .navbar-header, - .container > .navbar-collapse, - .container-fluid > .navbar-collapse { - margin-right: 0; - margin-left: 0; - } -} -.navbar-static-top { - z-index: 1000; - border-width: 0 0 1px; -} -@media (min-width: 768px) { - .navbar-static-top { - border-radius: 0; - } -} -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; -} -@media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } -} -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px; -} -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0; -} -.navbar-brand { - float: left; - height: 50px; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; -} -.navbar-brand:hover, -.navbar-brand:focus { - text-decoration: none; -} -.navbar-brand > img { - display: block; -} -@media (min-width: 768px) { - .navbar > .container .navbar-brand, - .navbar > .container-fluid .navbar-brand { - margin-left: -15px; - } -} -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -.navbar-toggle:focus { - outline: 0; -} -.navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; -} -.navbar-toggle .icon-bar + .icon-bar { - margin-top: 4px; -} -@media (min-width: 768px) { - .navbar-toggle { - display: none; - } -} -.navbar-nav { - margin: 7.5px -15px; -} -.navbar-nav > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px; -} -@media (max-width: 767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-nav .open .dropdown-menu > li > a, - .navbar-nav .open .dropdown-menu .dropdown-header { - padding: 5px 15px 5px 25px; - } - .navbar-nav .open .dropdown-menu > li > a { - line-height: 20px; - } - .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-nav .open .dropdown-menu > li > a:focus { - background-image: none; - } -} -@media (min-width: 768px) { - .navbar-nav { - float: left; - margin: 0; - } - .navbar-nav > li { - float: left; - } - .navbar-nav > li > a { - padding-top: 15px; - padding-bottom: 15px; - } -} -.navbar-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); -} -@media (min-width: 768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .navbar-form .form-control-static { - display: inline-block; - } - .navbar-form .input-group { - display: inline-table; - vertical-align: middle; - } - .navbar-form .input-group .input-group-addon, - .navbar-form .input-group .input-group-btn, - .navbar-form .input-group .form-control { - width: auto; - } - .navbar-form .input-group > .form-control { - width: 100%; - } - .navbar-form .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio, - .navbar-form .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio label, - .navbar-form .checkbox label { - padding-left: 0; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .navbar-form .has-feedback .form-control-feedback { - top: 0; - } -} -@media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } - .navbar-form .form-group:last-child { - margin-bottom: 0; - } -} -@media (min-width: 768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } -} -.navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - margin-bottom: 0; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.navbar-btn { - margin-top: 8px; - margin-bottom: 8px; -} -.navbar-btn.btn-sm { - margin-top: 10px; - margin-bottom: 10px; -} -.navbar-btn.btn-xs { - margin-top: 14px; - margin-bottom: 14px; -} -.navbar-text { - margin-top: 15px; - margin-bottom: 15px; -} -@media (min-width: 768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px; - } -} -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - margin-right: -15px; - } - .navbar-right ~ .navbar-right { - margin-right: 0; - } -} -.navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7; -} -.navbar-default .navbar-brand { - color: #777; -} -.navbar-default .navbar-brand:hover, -.navbar-default .navbar-brand:focus { - color: #5e5e5e; - background-color: transparent; -} -.navbar-default .navbar-text { - color: #777; -} -.navbar-default .navbar-nav > li > a { - color: #777; -} -.navbar-default .navbar-nav > li > a:hover, -.navbar-default .navbar-nav > li > a:focus { - color: #333; - background-color: transparent; -} -.navbar-default .navbar-nav > .active > a, -.navbar-default .navbar-nav > .active > a:hover, -.navbar-default .navbar-nav > .active > a:focus { - color: #555; - background-color: #e7e7e7; -} -.navbar-default .navbar-nav > .disabled > a, -.navbar-default .navbar-nav > .disabled > a:hover, -.navbar-default .navbar-nav > .disabled > a:focus { - color: #ccc; - background-color: transparent; -} -.navbar-default .navbar-toggle { - border-color: #ddd; -} -.navbar-default .navbar-toggle:hover, -.navbar-default .navbar-toggle:focus { - background-color: #ddd; -} -.navbar-default .navbar-toggle .icon-bar { - background-color: #888; -} -.navbar-default .navbar-collapse, -.navbar-default .navbar-form { - border-color: #e7e7e7; -} -.navbar-default .navbar-nav > .open > a, -.navbar-default .navbar-nav > .open > a:hover, -.navbar-default .navbar-nav > .open > a:focus { - color: #555; - background-color: #e7e7e7; -} -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu > li > a { - color: #777; - } - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { - color: #333; - background-color: transparent; - } - .navbar-default .navbar-nav .open .dropdown-menu > .active > a, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #555; - background-color: #e7e7e7; - } - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #ccc; - background-color: transparent; - } -} -.navbar-default .navbar-link { - color: #777; -} -.navbar-default .navbar-link:hover { - color: #333; -} -.navbar-default .btn-link { - color: #777; -} -.navbar-default .btn-link:hover, -.navbar-default .btn-link:focus { - color: #333; -} -.navbar-default .btn-link[disabled]:hover, -fieldset[disabled] .navbar-default .btn-link:hover, -.navbar-default .btn-link[disabled]:focus, -fieldset[disabled] .navbar-default .btn-link:focus { - color: #ccc; -} -.navbar-inverse { - background-color: #222; - border-color: #080808; -} -.navbar-inverse .navbar-brand { - color: #9d9d9d; -} -.navbar-inverse .navbar-brand:hover, -.navbar-inverse .navbar-brand:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-text { - color: #9d9d9d; -} -.navbar-inverse .navbar-nav > li > a { - color: #9d9d9d; -} -.navbar-inverse .navbar-nav > li > a:hover, -.navbar-inverse .navbar-nav > li > a:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-nav > .active > a, -.navbar-inverse .navbar-nav > .active > a:hover, -.navbar-inverse .navbar-nav > .active > a:focus { - color: #fff; - background-color: #080808; -} -.navbar-inverse .navbar-nav > .disabled > a, -.navbar-inverse .navbar-nav > .disabled > a:hover, -.navbar-inverse .navbar-nav > .disabled > a:focus { - color: #444; - background-color: transparent; -} -.navbar-inverse .navbar-toggle { - border-color: #333; -} -.navbar-inverse .navbar-toggle:hover, -.navbar-inverse .navbar-toggle:focus { - background-color: #333; -} -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #fff; -} -.navbar-inverse .navbar-collapse, -.navbar-inverse .navbar-form { - border-color: #101010; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .open > a:hover, -.navbar-inverse .navbar-nav > .open > a:focus { - color: #fff; - background-color: #080808; -} -@media (max-width: 767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { - border-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu .divider { - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #9d9d9d; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { - color: #fff; - background-color: transparent; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #fff; - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #444; - background-color: transparent; - } -} -.navbar-inverse .navbar-link { - color: #9d9d9d; -} -.navbar-inverse .navbar-link:hover { - color: #fff; -} -.navbar-inverse .btn-link { - color: #9d9d9d; -} -.navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link:focus { - color: #fff; -} -.navbar-inverse .btn-link[disabled]:hover, -fieldset[disabled] .navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link[disabled]:focus, -fieldset[disabled] .navbar-inverse .btn-link:focus { - color: #444; -} -.breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px; -} -.breadcrumb > li { - display: inline-block; -} -.breadcrumb > li + li:before { - padding: 0 5px; - color: #ccc; - content: "/\00a0"; -} -.breadcrumb > .active { - color: #777; -} -.pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px; -} -.pagination > li { - display: inline; -} -.pagination > li > a, -.pagination > li > span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.42857143; - color: #337ab7; - text-decoration: none; - background-color: #fff; - border: 1px solid #ddd; -} -.pagination > li:first-child > a, -.pagination > li:first-child > span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; -} -.pagination > li:last-child > a, -.pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} -.pagination > li > a:hover, -.pagination > li > span:hover, -.pagination > li > a:focus, -.pagination > li > span:focus { - z-index: 2; - color: #23527c; - background-color: #eee; - border-color: #ddd; -} -.pagination > .active > a, -.pagination > .active > span, -.pagination > .active > a:hover, -.pagination > .active > span:hover, -.pagination > .active > a:focus, -.pagination > .active > span:focus { - z-index: 3; - color: #fff; - cursor: default; - background-color: #337ab7; - border-color: #337ab7; -} -.pagination > .disabled > span, -.pagination > .disabled > span:hover, -.pagination > .disabled > span:focus, -.pagination > .disabled > a, -.pagination > .disabled > a:hover, -.pagination > .disabled > a:focus { - color: #777; - cursor: not-allowed; - background-color: #fff; - border-color: #ddd; -} -.pagination-lg > li > a, -.pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.pagination-lg > li:first-child > a, -.pagination-lg > li:first-child > span { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px; -} -.pagination-lg > li:last-child > a, -.pagination-lg > li:last-child > span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; -} -.pagination-sm > li > a, -.pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; -} -.pagination-sm > li:first-child > a, -.pagination-sm > li:first-child > span { - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; -} -.pagination-sm > li:last-child > a, -.pagination-sm > li:last-child > span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} -.pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none; -} -.pager li { - display: inline; -} -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 15px; -} -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #eee; -} -.pager .next > a, -.pager .next > span { - float: right; -} -.pager .previous > a, -.pager .previous > span { - float: left; -} -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #777; - cursor: not-allowed; - background-color: #fff; -} -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; -} -a.label:hover, -a.label:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.label:empty { - display: none; -} -.btn .label { - position: relative; - top: -1px; -} -.label-default { - background-color: #777; -} -.label-default[href]:hover, -.label-default[href]:focus { - background-color: #5e5e5e; -} -.label-primary { - background-color: #337ab7; -} -.label-primary[href]:hover, -.label-primary[href]:focus { - background-color: #286090; -} -.label-success { - background-color: #5cb85c; -} -.label-success[href]:hover, -.label-success[href]:focus { - background-color: #449d44; -} -.label-info { - background-color: #5bc0de; -} -.label-info[href]:hover, -.label-info[href]:focus { - background-color: #31b0d5; -} -.label-warning { - background-color: #f0ad4e; -} -.label-warning[href]:hover, -.label-warning[href]:focus { - background-color: #ec971f; -} -.label-danger { - background-color: #d9534f; -} -.label-danger[href]:hover, -.label-danger[href]:focus { - background-color: #c9302c; -} -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: middle; - background-color: #777; - border-radius: 10px; -} -.badge:empty { - display: none; -} -.btn .badge { - position: relative; - top: -1px; -} -.btn-xs .badge, -.btn-group-xs > .btn .badge { - top: 0; - padding: 1px 5px; -} -a.badge:hover, -a.badge:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.list-group-item.active > .badge, -.nav-pills > .active > a > .badge { - color: #337ab7; - background-color: #fff; -} -.list-group-item > .badge { - float: right; -} -.list-group-item > .badge + .badge { - margin-right: 5px; -} -.nav-pills > li > a > .badge { - margin-left: 3px; -} -.jumbotron { - padding-top: 30px; - padding-bottom: 30px; - margin-bottom: 30px; - color: inherit; - background-color: #eee; -} -.jumbotron h1, -.jumbotron .h1 { - color: inherit; -} -.jumbotron p { - margin-bottom: 15px; - font-size: 21px; - font-weight: 200; -} -.jumbotron > hr { - border-top-color: #d5d5d5; -} -.container .jumbotron, -.container-fluid .jumbotron { - padding-right: 15px; - padding-left: 15px; - border-radius: 6px; -} -.jumbotron .container { - max-width: 100%; -} -@media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron, - .container-fluid .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1, - .jumbotron .h1 { - font-size: 63px; - } -} -.thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: border .2s ease-in-out; - -o-transition: border .2s ease-in-out; - transition: border .2s ease-in-out; -} -.thumbnail > img, -.thumbnail a > img { - margin-right: auto; - margin-left: auto; -} -a.thumbnail:hover, -a.thumbnail:focus, -a.thumbnail.active { - border-color: #337ab7; -} -.thumbnail .caption { - padding: 9px; - color: #333; -} -.alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px; -} -.alert h4 { - margin-top: 0; - color: inherit; -} -.alert .alert-link { - font-weight: bold; -} -.alert > p, -.alert > ul { - margin-bottom: 0; -} -.alert > p + p { - margin-top: 5px; -} -.alert-dismissable, -.alert-dismissible { - padding-right: 35px; -} -.alert-dismissable .close, -.alert-dismissible .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; -} -.alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.alert-success hr { - border-top-color: #c9e2b3; -} -.alert-success .alert-link { - color: #2b542c; -} -.alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.alert-info hr { - border-top-color: #a6e1ec; -} -.alert-info .alert-link { - color: #245269; -} -.alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.alert-warning hr { - border-top-color: #f7e1b5; -} -.alert-warning .alert-link { - color: #66512c; -} -.alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.alert-danger hr { - border-top-color: #e4b9c0; -} -.alert-danger .alert-link { - color: #843534; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); -} -.progress-bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - line-height: 20px; - color: #fff; - text-align: center; - background-color: #337ab7; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - -webkit-transition: width .6s ease; - -o-transition: width .6s ease; - transition: width .6s ease; -} -.progress-striped .progress-bar, -.progress-bar-striped { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - background-size: 40px 40px; -} -.progress.active .progress-bar, -.progress-bar.active { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -.progress-bar-success { - background-color: #5cb85c; -} -.progress-striped .progress-bar-success { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-info { - background-color: #5bc0de; -} -.progress-striped .progress-bar-info { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-warning { - background-color: #f0ad4e; -} -.progress-striped .progress-bar-warning { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-danger { - background-color: #d9534f; -} -.progress-striped .progress-bar-danger { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.media { - margin-top: 15px; -} -.media:first-child { - margin-top: 0; -} -.media, -.media-body { - overflow: hidden; - zoom: 1; -} -.media-body { - width: 10000px; -} -.media-object { - display: block; -} -.media-object.img-thumbnail { - max-width: none; -} -.media-right, -.media > .pull-right { - padding-left: 10px; -} -.media-left, -.media > .pull-left { - padding-right: 10px; -} -.media-left, -.media-right, -.media-body { - display: table-cell; - vertical-align: top; -} -.media-middle { - vertical-align: middle; -} -.media-bottom { - vertical-align: bottom; -} -.media-heading { - margin-top: 0; - margin-bottom: 5px; -} -.media-list { - padding-left: 0; - list-style: none; -} -.list-group { - padding-left: 0; - margin-bottom: 20px; -} -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #fff; - border: 1px solid #ddd; -} -.list-group-item:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px; -} -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -a.list-group-item, -button.list-group-item { - color: #555; -} -a.list-group-item .list-group-item-heading, -button.list-group-item .list-group-item-heading { - color: #333; -} -a.list-group-item:hover, -button.list-group-item:hover, -a.list-group-item:focus, -button.list-group-item:focus { - color: #555; - text-decoration: none; - background-color: #f5f5f5; -} -button.list-group-item { - width: 100%; - text-align: left; -} -.list-group-item.disabled, -.list-group-item.disabled:hover, -.list-group-item.disabled:focus { - color: #777; - cursor: not-allowed; - background-color: #eee; -} -.list-group-item.disabled .list-group-item-heading, -.list-group-item.disabled:hover .list-group-item-heading, -.list-group-item.disabled:focus .list-group-item-heading { - color: inherit; -} -.list-group-item.disabled .list-group-item-text, -.list-group-item.disabled:hover .list-group-item-text, -.list-group-item.disabled:focus .list-group-item-text { - color: #777; -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - z-index: 2; - color: #fff; - background-color: #337ab7; - border-color: #337ab7; -} -.list-group-item.active .list-group-item-heading, -.list-group-item.active:hover .list-group-item-heading, -.list-group-item.active:focus .list-group-item-heading, -.list-group-item.active .list-group-item-heading > small, -.list-group-item.active:hover .list-group-item-heading > small, -.list-group-item.active:focus .list-group-item-heading > small, -.list-group-item.active .list-group-item-heading > .small, -.list-group-item.active:hover .list-group-item-heading > .small, -.list-group-item.active:focus .list-group-item-heading > .small { - color: inherit; -} -.list-group-item.active .list-group-item-text, -.list-group-item.active:hover .list-group-item-text, -.list-group-item.active:focus .list-group-item-text { - color: #c7ddef; -} -.list-group-item-success { - color: #3c763d; - background-color: #dff0d8; -} -a.list-group-item-success, -button.list-group-item-success { - color: #3c763d; -} -a.list-group-item-success .list-group-item-heading, -button.list-group-item-success .list-group-item-heading { - color: inherit; -} -a.list-group-item-success:hover, -button.list-group-item-success:hover, -a.list-group-item-success:focus, -button.list-group-item-success:focus { - color: #3c763d; - background-color: #d0e9c6; -} -a.list-group-item-success.active, -button.list-group-item-success.active, -a.list-group-item-success.active:hover, -button.list-group-item-success.active:hover, -a.list-group-item-success.active:focus, -button.list-group-item-success.active:focus { - color: #fff; - background-color: #3c763d; - border-color: #3c763d; -} -.list-group-item-info { - color: #31708f; - background-color: #d9edf7; -} -a.list-group-item-info, -button.list-group-item-info { - color: #31708f; -} -a.list-group-item-info .list-group-item-heading, -button.list-group-item-info .list-group-item-heading { - color: inherit; -} -a.list-group-item-info:hover, -button.list-group-item-info:hover, -a.list-group-item-info:focus, -button.list-group-item-info:focus { - color: #31708f; - background-color: #c4e3f3; -} -a.list-group-item-info.active, -button.list-group-item-info.active, -a.list-group-item-info.active:hover, -button.list-group-item-info.active:hover, -a.list-group-item-info.active:focus, -button.list-group-item-info.active:focus { - color: #fff; - background-color: #31708f; - border-color: #31708f; -} -.list-group-item-warning { - color: #8a6d3b; - background-color: #fcf8e3; -} -a.list-group-item-warning, -button.list-group-item-warning { - color: #8a6d3b; -} -a.list-group-item-warning .list-group-item-heading, -button.list-group-item-warning .list-group-item-heading { - color: inherit; -} -a.list-group-item-warning:hover, -button.list-group-item-warning:hover, -a.list-group-item-warning:focus, -button.list-group-item-warning:focus { - color: #8a6d3b; - background-color: #faf2cc; -} -a.list-group-item-warning.active, -button.list-group-item-warning.active, -a.list-group-item-warning.active:hover, -button.list-group-item-warning.active:hover, -a.list-group-item-warning.active:focus, -button.list-group-item-warning.active:focus { - color: #fff; - background-color: #8a6d3b; - border-color: #8a6d3b; -} -.list-group-item-danger { - color: #a94442; - background-color: #f2dede; -} -a.list-group-item-danger, -button.list-group-item-danger { - color: #a94442; -} -a.list-group-item-danger .list-group-item-heading, -button.list-group-item-danger .list-group-item-heading { - color: inherit; -} -a.list-group-item-danger:hover, -button.list-group-item-danger:hover, -a.list-group-item-danger:focus, -button.list-group-item-danger:focus { - color: #a94442; - background-color: #ebcccc; -} -a.list-group-item-danger.active, -button.list-group-item-danger.active, -a.list-group-item-danger.active:hover, -button.list-group-item-danger.active:hover, -a.list-group-item-danger.active:focus, -button.list-group-item-danger.active:focus { - color: #fff; - background-color: #a94442; - border-color: #a94442; -} -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; -} -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3; -} -.panel { - margin-bottom: 20px; - background-color: #fff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: 0 1px 1px rgba(0, 0, 0, .05); -} -.panel-body { - padding: 15px; -} -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel-heading > .dropdown .dropdown-toggle { - color: inherit; -} -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; - color: inherit; -} -.panel-title > a, -.panel-title > small, -.panel-title > .small, -.panel-title > small > a, -.panel-title > .small > a { - color: inherit; -} -.panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .list-group, -.panel > .panel-collapse > .list-group { - margin-bottom: 0; -} -.panel > .list-group .list-group-item, -.panel > .panel-collapse > .list-group .list-group-item { - border-width: 1px 0; - border-radius: 0; -} -.panel > .list-group:first-child .list-group-item:first-child, -.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { - border-top: 0; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .list-group:last-child .list-group-item:last-child, -.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { - border-bottom: 0; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; -} -.list-group + .panel-footer { - border-top-width: 0; -} -.panel > .table, -.panel > .table-responsive > .table, -.panel > .panel-collapse > .table { - margin-bottom: 0; -} -.panel > .table caption, -.panel > .table-responsive > .table caption, -.panel > .panel-collapse > .table caption { - padding-right: 15px; - padding-left: 15px; -} -.panel > .table:first-child, -.panel > .table-responsive:first-child > .table:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, -.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { - border-top-left-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, -.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, -.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, -.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { - border-top-right-radius: 3px; -} -.panel > .table:last-child, -.panel > .table-responsive:last-child > .table:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, -.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, -.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { - border-bottom-right-radius: 3px; -} -.panel > .panel-body + .table, -.panel > .panel-body + .table-responsive, -.panel > .table + .panel-body, -.panel > .table-responsive + .panel-body { - border-top: 1px solid #ddd; -} -.panel > .table > tbody:first-child > tr:first-child th, -.panel > .table > tbody:first-child > tr:first-child td { - border-top: 0; -} -.panel > .table-bordered, -.panel > .table-responsive > .table-bordered { - border: 0; -} -.panel > .table-bordered > thead > tr > th:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, -.panel > .table-bordered > tbody > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, -.panel > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-bordered > thead > tr > td:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, -.panel > .table-bordered > tbody > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, -.panel > .table-bordered > tfoot > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; -} -.panel > .table-bordered > thead > tr > th:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, -.panel > .table-bordered > tbody > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, -.panel > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-bordered > thead > tr > td:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, -.panel > .table-bordered > tbody > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, -.panel > .table-bordered > tfoot > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; -} -.panel > .table-bordered > thead > tr:first-child > td, -.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, -.panel > .table-bordered > tbody > tr:first-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, -.panel > .table-bordered > thead > tr:first-child > th, -.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, -.panel > .table-bordered > tbody > tr:first-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { - border-bottom: 0; -} -.panel > .table-bordered > tbody > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, -.panel > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-bordered > tbody > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, -.panel > .table-bordered > tfoot > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { - border-bottom: 0; -} -.panel > .table-responsive { - margin-bottom: 0; - border: 0; -} -.panel-group { - margin-bottom: 20px; -} -.panel-group .panel { - margin-bottom: 0; - border-radius: 4px; -} -.panel-group .panel + .panel { - margin-top: 5px; -} -.panel-group .panel-heading { - border-bottom: 0; -} -.panel-group .panel-heading + .panel-collapse > .panel-body, -.panel-group .panel-heading + .panel-collapse > .list-group { - border-top: 1px solid #ddd; -} -.panel-group .panel-footer { - border-top: 0; -} -.panel-group .panel-footer + .panel-collapse .panel-body { - border-bottom: 1px solid #ddd; -} -.panel-default { - border-color: #ddd; -} -.panel-default > .panel-heading { - color: #333; - background-color: #f5f5f5; - border-color: #ddd; -} -.panel-default > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #ddd; -} -.panel-default > .panel-heading .badge { - color: #f5f5f5; - background-color: #333; -} -.panel-default > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ddd; -} -.panel-primary { - border-color: #337ab7; -} -.panel-primary > .panel-heading { - color: #fff; - background-color: #337ab7; - border-color: #337ab7; -} -.panel-primary > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #337ab7; -} -.panel-primary > .panel-heading .badge { - color: #337ab7; - background-color: #fff; -} -.panel-primary > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #337ab7; -} -.panel-success { - border-color: #d6e9c6; -} -.panel-success > .panel-heading { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.panel-success > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #d6e9c6; -} -.panel-success > .panel-heading .badge { - color: #dff0d8; - background-color: #3c763d; -} -.panel-success > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #d6e9c6; -} -.panel-info { - border-color: #bce8f1; -} -.panel-info > .panel-heading { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.panel-info > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #bce8f1; -} -.panel-info > .panel-heading .badge { - color: #d9edf7; - background-color: #31708f; -} -.panel-info > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #bce8f1; -} -.panel-warning { - border-color: #faebcc; -} -.panel-warning > .panel-heading { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.panel-warning > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #faebcc; -} -.panel-warning > .panel-heading .badge { - color: #fcf8e3; - background-color: #8a6d3b; -} -.panel-warning > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #faebcc; -} -.panel-danger { - border-color: #ebccd1; -} -.panel-danger > .panel-heading { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.panel-danger > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #ebccd1; -} -.panel-danger > .panel-heading .badge { - color: #f2dede; - background-color: #a94442; -} -.panel-danger > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ebccd1; -} -.embed-responsive { - position: relative; - display: block; - height: 0; - padding: 0; - overflow: hidden; -} -.embed-responsive .embed-responsive-item, -.embed-responsive iframe, -.embed-responsive embed, -.embed-responsive object, -.embed-responsive video { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; - border: 0; -} -.embed-responsive-16by9 { - padding-bottom: 56.25%; -} -.embed-responsive-4by3 { - padding-bottom: 75%; -} -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); -} -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, .15); -} -.well-lg { - padding: 24px; - border-radius: 6px; -} -.well-sm { - padding: 9px; - border-radius: 3px; -} -.close { - float: right; - font-size: 21px; - font-weight: bold; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - filter: alpha(opacity=20); - opacity: .2; -} -.close:hover, -.close:focus { - color: #000; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity=50); - opacity: .5; -} -button.close { - -webkit-appearance: none; - padding: 0; - cursor: pointer; - background: transparent; - border: 0; -} -.modal-open { - overflow: hidden; -} -.modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - display: none; - overflow: hidden; - -webkit-overflow-scrolling: touch; - outline: 0; -} -.modal.fade .modal-dialog { - -webkit-transition: -webkit-transform .3s ease-out; - -o-transition: -o-transform .3s ease-out; - transition: transform .3s ease-out; - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - -o-transform: translate(0, -25%); - transform: translate(0, -25%); -} -.modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - -o-transform: translate(0, 0); - transform: translate(0, 0); -} -.modal-open .modal { - overflow-x: hidden; - overflow-y: auto; -} -.modal-dialog { - position: relative; - width: auto; - margin: 10px; -} -.modal-content { - position: relative; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - outline: 0; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); - box-shadow: 0 3px 9px rgba(0, 0, 0, .5); -} -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000; -} -.modal-backdrop.fade { - filter: alpha(opacity=0); - opacity: 0; -} -.modal-backdrop.in { - filter: alpha(opacity=50); - opacity: .5; -} -.modal-header { - padding: 15px; - border-bottom: 1px solid #e5e5e5; -} -.modal-header .close { - margin-top: -2px; -} -.modal-title { - margin: 0; - line-height: 1.42857143; -} -.modal-body { - position: relative; - padding: 15px; -} -.modal-footer { - padding: 15px; - text-align: right; - border-top: 1px solid #e5e5e5; -} -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} -.modal-scrollbar-measure { - position: absolute; - top: -9999px; - width: 50px; - height: 50px; - overflow: scroll; -} -@media (min-width: 768px) { - .modal-dialog { - width: 600px; - margin: 30px auto; - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - } - .modal-sm { - width: 300px; - } -} -@media (min-width: 992px) { - .modal-lg { - width: 900px; - } -} -.tooltip { - position: absolute; - z-index: 1070; - display: block; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; - font-style: normal; - font-weight: normal; - line-height: 1.42857143; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - white-space: normal; - filter: alpha(opacity=0); - opacity: 0; - - line-break: auto; -} -.tooltip.in { - filter: alpha(opacity=90); - opacity: .9; -} -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - background-color: #000; - border-radius: 4px; -} -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-left .tooltip-arrow { - right: 5px; - bottom: 0; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-right .tooltip-arrow { - bottom: 0; - left: 5px; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000; -} -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000; -} -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-left .tooltip-arrow { - top: 0; - right: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-right .tooltip-arrow { - top: 0; - left: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1060; - display: none; - max-width: 276px; - padding: 1px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: normal; - line-height: 1.42857143; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - white-space: normal; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - - line-break: auto; -} -.popover.top { - margin-top: -10px; -} -.popover.right { - margin-left: 10px; -} -.popover.bottom { - margin-top: 10px; -} -.popover.left { - margin-left: -10px; -} -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0; -} -.popover-content { - padding: 9px 14px; -} -.popover > .arrow, -.popover > .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.popover > .arrow { - border-width: 11px; -} -.popover > .arrow:after { - content: ""; - border-width: 10px; -} -.popover.top > .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, .25); - border-bottom-width: 0; -} -.popover.top > .arrow:after { - bottom: 1px; - margin-left: -10px; - content: " "; - border-top-color: #fff; - border-bottom-width: 0; -} -.popover.right > .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, .25); - border-left-width: 0; -} -.popover.right > .arrow:after { - bottom: -10px; - left: 1px; - content: " "; - border-right-color: #fff; - border-left-width: 0; -} -.popover.bottom > .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, .25); -} -.popover.bottom > .arrow:after { - top: 1px; - margin-left: -10px; - content: " "; - border-top-width: 0; - border-bottom-color: #fff; -} -.popover.left > .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, .25); -} -.popover.left > .arrow:after { - right: 1px; - bottom: -10px; - content: " "; - border-right-width: 0; - border-left-color: #fff; -} -.carousel { - position: relative; -} -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: .6s ease-in-out left; - -o-transition: .6s ease-in-out left; - transition: .6s ease-in-out left; -} -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - line-height: 1; -} -@media all and (transform-3d), (-webkit-transform-3d) { - .carousel-inner > .item { - -webkit-transition: -webkit-transform .6s ease-in-out; - -o-transition: -o-transform .6s ease-in-out; - transition: transform .6s ease-in-out; - - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - -webkit-perspective: 1000px; - perspective: 1000px; - } - .carousel-inner > .item.next, - .carousel-inner > .item.active.right { - left: 0; - -webkit-transform: translate3d(100%, 0, 0); - transform: translate3d(100%, 0, 0); - } - .carousel-inner > .item.prev, - .carousel-inner > .item.active.left { - left: 0; - -webkit-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0); - } - .carousel-inner > .item.next.left, - .carousel-inner > .item.prev.right, - .carousel-inner > .item.active { - left: 0; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} -.carousel-inner > .active { - left: 0; -} -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} -.carousel-inner > .next { - left: 100%; -} -.carousel-inner > .prev { - left: -100%; -} -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} -.carousel-inner > .active.left { - left: -100%; -} -.carousel-inner > .active.right { - left: 100%; -} -.carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); - background-color: rgba(0, 0, 0, 0); - filter: alpha(opacity=50); - opacity: .5; -} -.carousel-control.left { - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control:hover, -.carousel-control:focus { - color: #fff; - text-decoration: none; - filter: alpha(opacity=90); - outline: 0; - opacity: .9; -} -.carousel-control .icon-prev, -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-left, -.carousel-control .glyphicon-chevron-right { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block; - margin-top: -10px; -} -.carousel-control .icon-prev, -.carousel-control .glyphicon-chevron-left { - left: 50%; - margin-left: -10px; -} -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-right { - right: 50%; - margin-right: -10px; -} -.carousel-control .icon-prev, -.carousel-control .icon-next { - width: 20px; - height: 20px; - font-family: serif; - line-height: 1; -} -.carousel-control .icon-prev:before { - content: '\2039'; -} -.carousel-control .icon-next:before { - content: '\203a'; -} -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; -} -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #fff; - border-radius: 10px; -} -.carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #fff; -} -.carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); -} -.carousel-caption .btn { - text-shadow: none; -} -@media screen and (min-width: 768px) { - .carousel-control .glyphicon-chevron-left, - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -10px; - font-size: 30px; - } - .carousel-control .glyphicon-chevron-left, - .carousel-control .icon-prev { - margin-left: -10px; - } - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-next { - margin-right: -10px; - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } -} -.clearfix:before, -.clearfix:after, -.dl-horizontal dd:before, -.dl-horizontal dd:after, -.container:before, -.container:after, -.container-fluid:before, -.container-fluid:after, -.row:before, -.row:after, -.form-horizontal .form-group:before, -.form-horizontal .form-group:after, -.btn-toolbar:before, -.btn-toolbar:after, -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after, -.nav:before, -.nav:after, -.navbar:before, -.navbar:after, -.navbar-header:before, -.navbar-header:after, -.navbar-collapse:before, -.navbar-collapse:after, -.pager:before, -.pager:after, -.panel-body:before, -.panel-body:after, -.modal-header:before, -.modal-header:after, -.modal-footer:before, -.modal-footer:after { - display: table; - content: " "; -} -.clearfix:after, -.dl-horizontal dd:after, -.container:after, -.container-fluid:after, -.row:after, -.form-horizontal .form-group:after, -.btn-toolbar:after, -.btn-group-vertical > .btn-group:after, -.nav:after, -.navbar:after, -.navbar-header:after, -.navbar-collapse:after, -.pager:after, -.panel-body:after, -.modal-header:after, -.modal-footer:after { - clear: both; -} -.center-block { - display: block; - margin-right: auto; - margin-left: auto; -} -.pull-right { - float: right !important; -} -.pull-left { - float: left !important; -} -.hide { - display: none !important; -} -.show { - display: block !important; -} -.invisible { - visibility: hidden; -} -.text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -.hidden { - display: none !important; -} -.affix { - position: fixed; -} -@-ms-viewport { - width: device-width; -} -.visible-xs, -.visible-sm, -.visible-md, -.visible-lg { - display: none !important; -} -.visible-xs-block, -.visible-xs-inline, -.visible-xs-inline-block, -.visible-sm-block, -.visible-sm-inline, -.visible-sm-inline-block, -.visible-md-block, -.visible-md-inline, -.visible-md-inline-block, -.visible-lg-block, -.visible-lg-inline, -.visible-lg-inline-block { - display: none !important; -} -@media (max-width: 767px) { - .visible-xs { - display: block !important; - } - table.visible-xs { - display: table !important; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } -} -@media (max-width: 767px) { - .visible-xs-block { - display: block !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline { - display: inline !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline-block { - display: inline-block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - table.visible-sm { - display: table !important; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-block { - display: block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline { - display: inline !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline-block { - display: inline-block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - table.visible-md { - display: table !important; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-block { - display: block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline { - display: inline !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline-block { - display: inline-block !important; - } -} -@media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - table.visible-lg { - display: table !important; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } -} -@media (min-width: 1200px) { - .visible-lg-block { - display: block !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline { - display: inline !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline-block { - display: inline-block !important; - } -} -@media (max-width: 767px) { - .hidden-xs { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .hidden-sm { - display: none !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-md { - display: none !important; - } -} -@media (min-width: 1200px) { - .hidden-lg { - display: none !important; - } -} -.visible-print { - display: none !important; -} -@media print { - .visible-print { - display: block !important; - } - table.visible-print { - display: table !important; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } -} -.visible-print-block { - display: none !important; -} -@media print { - .visible-print-block { - display: block !important; - } -} -.visible-print-inline { - display: none !important; -} -@media print { - .visible-print-inline { - display: inline !important; - } -} -.visible-print-inline-block { - display: none !important; -} -@media print { - .visible-print-inline-block { - display: inline-block !important; - } -} -@media print { - .hidden-print { - display: none !important; - } -} -/*# sourceMappingURL=bootstrap.css.map */ diff --git a/bomberman/frontend/src/main/webapp/css/style.css b/bomberman/frontend/src/main/webapp/css/style.css deleted file mode 100644 index 672d36dba3..0000000000 --- a/bomberman/frontend/src/main/webapp/css/style.css +++ /dev/null @@ -1,52 +0,0 @@ - .container { - width: 545px; -} - -#game { - margin: auto; - text-align: center; -} - -.footer .alert { - text-align: center; - line-height: 35px; -} - -.footer .alert img { - margin-top: -3px; - margin-right: 5px; -} - -h1 { - line-height: 64px; - margin-bottom: 0; -} - -.html5 { - width: 64px; - height: 64px; - display: block; - float: left; - margin-right: 10px; -} - -.html5 span { - display: none; -} - -h1 strong { - color: #FF4444; -} - -.credits { - color: gray; -} - -.credits a { - color: gray; - text-decoration: underline; -} - -.credits a:hover { - color: black; -} \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/favicon.ico b/bomberman/frontend/src/main/webapp/favicon.ico deleted file mode 100644 index 9fa3a0198c..0000000000 Binary files a/bomberman/frontend/src/main/webapp/favicon.ico and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/betty.png b/bomberman/frontend/src/main/webapp/img/betty.png deleted file mode 100644 index f62ae8b42d..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/betty.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/betty2.png b/bomberman/frontend/src/main/webapp/img/betty2.png deleted file mode 100644 index e2c12eb695..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/betty2.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/bomb.png b/bomberman/frontend/src/main/webapp/img/bomb.png deleted file mode 100644 index dcd2f9c83b..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/bomb.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/bomberman.png b/bomberman/frontend/src/main/webapp/img/bomberman.png deleted file mode 100644 index 3aff57dc20..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/bomberman.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/bonuses.png b/bomberman/frontend/src/main/webapp/img/bonuses.png deleted file mode 100644 index 72e8da257e..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/bonuses.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/fire.png b/bomberman/frontend/src/main/webapp/img/fire.png deleted file mode 100644 index 8394bcbd5b..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/fire.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/george.png b/bomberman/frontend/src/main/webapp/img/george.png deleted file mode 100644 index 6e58db5a71..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/george.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/github.png b/bomberman/frontend/src/main/webapp/img/github.png deleted file mode 100644 index d5f4488590..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/github.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/rpg_character.png b/bomberman/frontend/src/main/webapp/img/rpg_character.png deleted file mode 100644 index b18f94950c..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/rpg_character.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/tile_grass.png b/bomberman/frontend/src/main/webapp/img/tile_grass.png deleted file mode 100644 index b0d192305e..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/tile_grass.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/tile_wall.png b/bomberman/frontend/src/main/webapp/img/tile_wall.png deleted file mode 100644 index 0468c17752..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/tile_wall.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/img/tile_wood.png b/bomberman/frontend/src/main/webapp/img/tile_wood.png deleted file mode 100644 index 07d44d9d5d..0000000000 Binary files a/bomberman/frontend/src/main/webapp/img/tile_wood.png and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/index.html b/bomberman/frontend/src/main/webapp/index.html deleted file mode 100644 index 06b9de0b5d..0000000000 --- a/bomberman/frontend/src/main/webapp/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - Bombergirl - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - -
-

How to play

- - M … mute / unmute sound
- enter … restart
- escape … menu - -
- - -
- - \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/Bomb.js b/bomberman/frontend/src/main/webapp/js/Bomb.js deleted file mode 100644 index c820b0dd6e..0000000000 --- a/bomberman/frontend/src/main/webapp/js/Bomb.js +++ /dev/null @@ -1,71 +0,0 @@ -Bomb = Entity.extend({ - /** - * Entity position on map grid - */ - position: {}, - - /** - * How far the fire reaches when bomb explodes - */ - strength: 1, - - /** - * Bitmap dimensions - */ - size: { - w: 28, - h: 28 - }, - - /** - * Bitmap animation - */ - bmp: null, - - /** - * Timer in frames - */ - timer: 0, - - /** - * Max timer value in seconds - */ - timerMax: 2, - - exploded: false, - - fires: [], - - explodeListener: null, - - init: function(id, position, strength) { - this.id = id; - this.strength = strength; - - var spriteSheet = new createjs.SpriteSheet({ - images: [gGameEngine.bombImg], - frames: { - width: this.size.w, - height: this.size.h, - regX: 5, - regY: 5 - }, - animations: { - idle: [0, 4, "idle", 0.2] - } - }); - this.bmp = new createjs.Sprite(spriteSheet); - this.bmp.gotoAndPlay('idle'); - - this.position = position; - this.bmp.x = position.x; - this.bmp.y = position.y; - - this.fires = []; - gGameEngine.stage.addChild(this.bmp); - }, - - remove: function() { - gGameEngine.stage.removeChild(this.bmp); - } -}); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/Bonus.js b/bomberman/frontend/src/main/webapp/js/Bonus.js deleted file mode 100644 index 4a4c6a1e45..0000000000 --- a/bomberman/frontend/src/main/webapp/js/Bonus.js +++ /dev/null @@ -1,24 +0,0 @@ -Bonus = Entity.extend({ - types: ['speed', 'bomb', 'fire'], - - type: '', - position: {}, - bmp: null, - - init: function(position, typePosition) { - this.type = this.types[typePosition]; - - this.position = position; - - this.bmp = new createjs.Bitmap(gGameEngine.bonusesImg); - var pixels = Utils.convertToBitmapPosition(position); - this.bmp.x = pixels.x; - this.bmp.y = pixels.y; - this.bmp.sourceRect = new createjs.Rectangle(typePosition * 32, 0, 32, 32); - gGameEngine.stage.addChild(this.bmp); - }, - - remove: function() { - gGameEngine.stage.removeChild(this.bmp); - } -}); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/Entity.js b/bomberman/frontend/src/main/webapp/js/Entity.js deleted file mode 100644 index 43f53e4faf..0000000000 --- a/bomberman/frontend/src/main/webapp/js/Entity.js +++ /dev/null @@ -1,12 +0,0 @@ -Entity = Class.extend({ - id: null, - - init: function() { - }, - - update: function() { - }, - - remove: function () { - } -}); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/Fire.js b/bomberman/frontend/src/main/webapp/js/Fire.js deleted file mode 100644 index 495192fda5..0000000000 --- a/bomberman/frontend/src/main/webapp/js/Fire.js +++ /dev/null @@ -1,50 +0,0 @@ -Fire = Entity.extend({ - /** - * Entity position on map grid - */ - position: {}, - - /** - * Bitmap dimensions - */ - size: { - w: 38, - h: 38 - }, - - /** - * Bitmap animation - */ - bmp: null, - - init: function(id, position) { - this.id = id; - var spriteSheet = new createjs.SpriteSheet({ - images: [gGameEngine.fireImg], - frames: { width: this.size.w, height: this.size.h, regX: 0, regY: 0 }, - animations: { - idle: [0, 5, null, 0.4], - } - }); - this.bmp = new createjs.Sprite(spriteSheet); - this.bmp.gotoAndPlay('idle'); - var that = this; - this.bmp.addEventListener('animationend', function() { - that.remove(); - }); - - this.position = position; - - this.bmp.x = position.x + 2; - this.bmp.y = position.y - 5; - - gGameEngine.stage.addChild(this.bmp); - }, - - update: function() { - }, - - remove: function() { - gGameEngine.stage.removeChild(this.bmp); - } -}); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/GameEngine.js b/bomberman/frontend/src/main/webapp/js/GameEngine.js deleted file mode 100644 index 163c3c213a..0000000000 --- a/bomberman/frontend/src/main/webapp/js/GameEngine.js +++ /dev/null @@ -1,204 +0,0 @@ -GameEngine = Class.extend({ - tileSize: 32, - tilesX: 17, - tilesY: 13, - size: {}, - fps: 60, - playersCount: 2, - bonusesPercent: 16, - - stage: null, - menu: null, - players: [], - tiles: [], - bombs: [], - bonuses: [], - fires: [], - - playerBoyImg: null, - playerGirlImg: null, - playerGirl2Img: null, - tilesImgs: {}, - bombImg: null, - fireImg: null, - bonusesImg: null, - - playing: false, - mute: false, - soundtrackLoaded: false, - soundtrackPlaying: false, - soundtrack: null, - - serverProxy: null, - - init: function() { - this.size = { - w: this.tileSize * this.tilesX, - h: this.tileSize * this.tilesY - }; - }, - - load: function() { - // Init canvas - this.stage = new createjs.Stage("canvas"); - this.stage.enableMouseOver(); - - // Load assets - var queue = new createjs.LoadQueue(); - var that = this; - queue.addEventListener("complete", function() { - that.playerBoyImg = queue.getResult("playerBoy"); - that.playerGirlImg = queue.getResult("playerGirl"); - that.playerGirl2Img = queue.getResult("playerGirl2"); - that.tilesImgs.grass = queue.getResult("tile_grass"); - that.tilesImgs.wall = queue.getResult("tile_wall"); - that.tilesImgs.wood = queue.getResult("tile_wood"); - that.bombImg = queue.getResult("bomb"); - that.fireImg = queue.getResult("fire"); - that.bonusesImg = queue.getResult("bonuses"); - that.setup(); - }); - queue.loadManifest([ - {id: "playerBoy", src: "img/george.png"}, - {id: "playerGirl", src: "img/betty.png"}, - {id: "playerGirl2", src: "img/betty2.png"}, - {id: "tile_grass", src: "img/tile_grass.png"}, - {id: "tile_wall", src: "img/tile_wall.png"}, - {id: "tile_wood", src: "img/tile_wood.png"}, - {id: "bomb", src: "img/bomb.png"}, - {id: "fire", src: "img/fire.png"}, - {id: "bonuses", src: "img/bonuses.png"} - ]); - - createjs.Sound.addEventListener("fileload", this.onSoundLoaded); - createjs.Sound.alternateExtensions = ["mp3"]; - createjs.Sound.registerSound("sound/bomb.ogg", "bomb"); - // createjs.Sound.registerSound("sound/game.ogg", "game"); - - this.menu = new Menu(); - }, - - setup: function() { - if (!gInputEngine.bindings.length) { - gInputEngine.setup(); - } - - this.bombs = []; - this.tiles = []; - this.bonuses = []; - - this.serverProxy = new ServerProxy(); - - // Toggle sound - gInputEngine.subscribe('mute', this.toggleSound); - - // Start loop - if (!createjs.Ticker.hasEventListener('tick')) { - createjs.Ticker.addEventListener('tick', gGameEngine.update); - createjs.Ticker.setFPS(this.fps); - } - - if (gGameEngine.playersCount > 0) { - if (this.soundtrackLoaded) { - this.playSoundtrack(); - } - } - - if (!this.playing) { - this.menu.show(); - } - }, - - onSoundLoaded: function(sound) { - if (sound.id == 'game') { - gGameEngine.soundtrackLoaded = true; - if (gGameEngine.playersCount > 0) { - gGameEngine.playSoundtrack(); - } - } - }, - - playSoundtrack: function() { - if (!gGameEngine.soundtrackPlaying) { - gGameEngine.soundtrack = createjs.Sound.play("game", "none", 0, 0, -1); - gGameEngine.soundtrack.setVolume(1); - gGameEngine.soundtrackPlaying = true; - } - }, - - update: function() { - // Player - for (var i = 0; i < gGameEngine.players.length; i++) { - var player = gGameEngine.players[i]; - player.update(); - } - - // Bombs - for (var i = 0; i < gGameEngine.bombs.length; i++) { - var bomb = gGameEngine.bombs[i]; - bomb.update(); - } - - // Menu - gGameEngine.menu.update(); - - // Stage - gGameEngine.stage.update(); - }, - - // gameOver: function(status) { - // if (gGameEngine.menu.visible) { return; } - // - // if (status == 'win') { - // var winText = "You won!"; - // if (gGameEngine.playersCount > 1) { - // var winner = gGameEngine.getWinner(); - // winText = winner == 0 ? "Player 1 won!" : "Player 2 won!"; - // } - // this.menu.show([{text: winText, color: '#669900'}, {text: ' ;D', color: '#99CC00'}]); - // } else { - // this.menu.show([{text: 'Game Over', color: '#CC0000'}, {text: ' :(', color: '#FF4444'}]); - // } - // }, - - restart: function() { - // gInputEngine.removeAllListeners(); - gGameEngine.stage.removeAllChildren(); - gGameEngine.setup(); - this.serverProxy = new ServerProxy(); - }, - - /** - * Moves specified child to the front. - */ - moveToFront: function(child) { - var children = gGameEngine.stage.getNumChildren(); - gGameEngine.stage.setChildIndex(child, children - 1); - }, - - toggleSound: function() { - if (gGameEngine.mute) { - gGameEngine.mute = false; - gGameEngine.soundtrack.resume(); - } else { - gGameEngine.mute = true; - gGameEngine.soundtrack.pause(); - } - }, - - gc: function(survivors) { - [this.players, this.tiles, this.bombs, this.bonuses].forEach(function (it) { - var i = it.length; - while (i--) { - if (!survivors.has(it[i].id)) { - it[i].remove(); - it.splice(i, 1); - } - } - }); - - } - -}); - -gGameEngine = new GameEngine(); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/InputEngine.js b/bomberman/frontend/src/main/webapp/js/InputEngine.js deleted file mode 100644 index f9600c9052..0000000000 --- a/bomberman/frontend/src/main/webapp/js/InputEngine.js +++ /dev/null @@ -1,132 +0,0 @@ -InputEngine = Class.extend({ - - // move notification fps - fps: 60, - - /** - * A dictionary mapping ASCII key codes to string values describing - * the action we want to take when that key is pressed. - */ - bindings: {}, - - /** - * A dictionary mapping actions that might be taken in our game - * to a boolean value indicating whether that action is currently being performed. - */ - actions: {}, - - possessed: null, - - subscribers: [], - - init: function() { }, - - setup: function() { - this.bind(37, 'left'); - this.bind(38, 'up'); - this.bind(39, 'right'); - this.bind(40, 'down'); - - - this.bind(32, 'bomb'); - - this.bind(13, 'restart'); - this.bind(27, 'escape'); - this.bind(77, 'mute'); - - // move multiple presses with fps frequency - this.keyboardController({ - 37 : this.onKeyDown, - 38 : this.onKeyDown, - 39 : this.onKeyDown, - 40 : this.onKeyDown - }, 1000 / this.fps); - - document.addEventListener('keydown', this.onKeyDown); - document.addEventListener('keyup', this.onKeyUp); - }, - - onKeyUp: function(event) { - var action = gInputEngine.bindings[event.keyCode]; - if (action) { - gInputEngine.actions[action] = false; - event.preventDefault(); - } - return false; - }, - - onKeyDown: function(event) { - var action = gInputEngine.bindings[event.keyCode]; - if (action) { - gInputEngine.actions[action] = true; - var subscribers = gInputEngine.subscribers[action]; - if (subscribers) { - for (var i = 0; i < subscribers.length; i++ ) { - subscribers[i]() - } - } - - event.preventDefault(); - } - return false; - }, - - /** - * The bind function takes an ASCII keycode and a string representing - * the action to take when that key is pressed. - */ - bind: function(key, action) { - this.bindings[key] = action; - }, - - subscribe: function (action, callback) { - this.subscribers[action] = this.subscribers[action] || []; - this.subscribers[action].push(callback) - }, - - // Keyboard input with customisable repeat (set to 0 for no key repeat) - keyboardController: function(keys, repeat) { - - // Lookup of key codes to timer ID, or null for no repeat - var timers = {}; - - // When key is pressed and we don't already think it's pressed, call the - // key action callback and set a timer to generate another one after a delay - document.onkeydown= function(event) { - var key = (event || window.event).keyCode; - if (!(key in keys)) - return true; - if (!(key in timers)) { - timers[key] = null; - keys[key](event); - if (repeat !== 0) - var f = function () { - keys[key](event); - }; - timers[key]= setInterval(f, repeat); - } - return false; - }; - - // Cancel timeout and mark key as released on keyup - document.onkeyup = function(event) { - var key= (event || window.event).keyCode; - if (key in timers) { - if (timers[key] !== null) - clearInterval(timers[key]); - delete timers[key]; - } - }; - - // When window is unfocused we may not get key events. To prevent this - // causing a key to 'get stuck down', cancel all held keys - window.onblur = function() { - for (key in timers) - if (timers[key] !== null) - clearInterval(timers[key]); - timers= {}; - }; - } -}); - -gInputEngine = new InputEngine(); diff --git a/bomberman/frontend/src/main/webapp/js/Menu.js b/bomberman/frontend/src/main/webapp/js/Menu.js deleted file mode 100644 index 4cdbdea3c1..0000000000 --- a/bomberman/frontend/src/main/webapp/js/Menu.js +++ /dev/null @@ -1,106 +0,0 @@ -Menu = Class.extend({ - visible: true, - - views: [], - - init: function () { - gGameEngine.playersCount = 0; - - this.showLoader(); - }, - - show: function (text) { - this.visible = true; - - this.draw(text); - }, - - hide: function () { - this.visible = false; - - for (var i = 0; i < this.views.length; i++) { - gGameEngine.stage.removeChild(this.views[i]); - } - - this.views = []; - }, - - update: function () { - if (this.visible) { - for (var i = 0; i < this.views.length; i++) { - gGameEngine.moveToFront(this.views[i]); - } - } - }, - - setHandCursor: function (btn) { - btn.addEventListener('mouseover', function () { - document.body.style.cursor = 'pointer'; - }); - btn.addEventListener('mouseout', function () { - document.body.style.cursor = 'auto'; - }); - }, - - start: function () { - this.hide(); - - gGameEngine.playing = true; - gGameEngine.serverProxy.getSessionIdFromMatchMaker(); - gGameEngine.restart(); - }, - - draw: function (text) { - var that = this; - - // semi-transparent black background - var bgGraphics = new createjs.Graphics().beginFill("rgba(0, 0, 0, 0.5)").drawRect(0, 0, gGameEngine.size.w, gGameEngine.size.h); - var bg = new createjs.Shape(bgGraphics); - gGameEngine.stage.addChild(bg); - this.views.push(bg); - - - // start button - var startButtonX = gGameEngine.size.w / 2 - 55; - var startButtonY = gGameEngine.size.h / 2 - 80; - var startButtonSize = 110; - - var singleBgGraphics = new createjs.Graphics().beginFill("rgba(0, 0, 0, 0.5)").drawRect(startButtonX, startButtonY, startButtonSize, startButtonSize); - var singleBg = new createjs.Shape(singleBgGraphics); - gGameEngine.stage.addChild(singleBg); - this.views.push(singleBg); - this.setHandCursor(singleBg); - singleBg.addEventListener('click', function () { - that.start(); - }); - - var playButton = new createjs.Text("Play", "32px Helvetica", "#ff4444"); - var singleTitleWidth = playButton.getMeasuredWidth(); - var modeTitlesY = startButtonY + startButtonSize - playButton.getMeasuredHeight() - 20; - - playButton.x = startButtonX + (startButtonSize - singleTitleWidth) / 2; - playButton.y = modeTitlesY; - gGameEngine.stage.addChild(playButton); - this.views.push(playButton); - - var iconsY = startButtonY + 13; - var singleIcon = new createjs.Bitmap("img/betty.png"); - singleIcon.sourceRect = new createjs.Rectangle(0, 0, 48, 48); - singleIcon.x = startButtonX + (startButtonSize - 48) / 2; - singleIcon.y = iconsY; - gGameEngine.stage.addChild(singleIcon); - this.views.push(singleIcon); - }, - - showLoader: function () { - var bgGraphics = new createjs.Graphics().beginFill("#000000").drawRect(0, 0, gGameEngine.size.w, gGameEngine.size.h); - var bg = new createjs.Shape(bgGraphics); - gGameEngine.stage.addChild(bg); - - var loadingText = new createjs.Text("Loading...", "20px Helvetica", "#FFFFFF"); - loadingText.x = gGameEngine.size.w / 2 - loadingText.getMeasuredWidth() / 2; - loadingText.y = gGameEngine.size.h / 2 - loadingText.getMeasuredHeight() / 2 - 150; - gGameEngine.stage.addChild(loadingText); - gGameEngine.stage.update(); - } -}); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/Message.js b/bomberman/frontend/src/main/webapp/js/Message.js deleted file mode 100644 index 467e2ef8a5..0000000000 --- a/bomberman/frontend/src/main/webapp/js/Message.js +++ /dev/null @@ -1,112 +0,0 @@ -Messages = Class.extend({ - handler: {}, - - init: function () { - this.handler['Pawn'] = this.handlePawn; - this.handler['Bomb'] = this.handleBomb; - this.handler['Wood'] = this.handleTile; - this.handler['Wall'] = this.handleTile; - this.handler['Fire'] = this.handleFire; - }, - - move: function (direction) { - var template = { - topic: "MOVE", - data: {} - }; - - template.data.direction = direction.toUpperCase(); - return JSON.stringify(template); - }, - - plantBomb: function () { - var template = { - topic: "PLANT_BOMB", - data: {} - }; - - return JSON.stringify(template); - }, - - - handleReplica: function (msg) { - //var gameObjects = JSON.parse(msg.data).objects - var gameObjects = msg.data.objects; - var survivors = new Set(); - - for (var i = 0; i < gameObjects.length; i++) { - var obj = gameObjects[i]; - if (gMessages.handler[obj.type] === undefined) - continue; - - survivors.add(obj.id); - gMessages.handler[obj.type](obj); - } - gGameEngine.gc(survivors); - }, - - handlePossess: function (msg) { - gInputEngine.possessed = parseInt(msg.data); - }, - - handlePawn: function(obj) { - var player = gGameEngine.players.find(function (el) { - return el.id === obj.id; - }); - var position = Utils.getEntityPosition(obj.position); - - if (player) { - player.bmp.x = position.x; - player.bmp.y = position.y; - } else { - console.log(new Date().getTime() + " handel new player " + obj.id); - player = new Player(obj.id, position); - gGameEngine.players.push(player); - } - }, - - handleBomb: function(obj) { - var bomb = gGameEngine.bombs.find(function (el) { - return el.id === obj.id; - }); - var position = Utils.getEntityPosition(obj.position); - - if (bomb) { - bomb.bmp.x = position.x; - bomb.bmp.y = position.y; - } else { - bomb = new Bomb(obj.id, position); - gGameEngine.bombs.push(bomb); - } - }, - - handleTile: function (obj) { - var tile = gGameEngine.tiles.find(function (el) { - return el.id === obj.id; - }); - - //var position = Utils.getEntityPosition(Utils.convertToBitmapPosition(obj.position)); - var position = Utils.getEntityPosition(obj.position); - if (tile) { - tile.material = obj.type; - } else { - tile = new Tile(obj.id, obj.type, position); - gGameEngine.tiles.push(tile); - } - }, - - handleFire: function (obj) { - var fire = gGameEngine.fires.find(function (el) { - return el.id === obj.id; - }); - - var position = Utils.getEntityPosition(obj.position); - if (!fire) { - fire = new Fire(obj.id, position); - gGameEngine.fires.push(fire); - } - } - -}); - -gMessages = new Messages(); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/Player.js b/bomberman/frontend/src/main/webapp/js/Player.js deleted file mode 100644 index 486a17a8ad..0000000000 --- a/bomberman/frontend/src/main/webapp/js/Player.js +++ /dev/null @@ -1,117 +0,0 @@ -Player = Entity.extend({ - /** - * Bitmap dimensions - */ - size: { - w: 48, - h: 48 - }, - - /** - * Bitmap animation - */ - bmp: null, - - alive: true, - - bombs: [], - - controls: { - 'up': 'up', - 'left': 'left', - 'down': 'down', - 'right': 'right', - 'bomb': 'bomb' - }, - - /** - * Bomb that player can escape from even when there is a collision - */ - escapeBomb: null, - - deadTimer: 0, - - - - init: function(id, position) { - this.id = id; - - var img = gGameEngine.playerGirlImg; - - var spriteSheet = new createjs.SpriteSheet({ - images: [img], - frames: { width: this.size.w, height: this.size.h, regX: 10, regY: 12 }, - animations: { - idle: [0, 0, 'idle'], - down: [0, 3, 'down', 0.1], - left: [4, 7, 'left', 0.1], - up: [8, 11, 'up', 0.1], - right: [12, 15, 'right', 0.1], - dead: [16, 16, 'dead', 0.1] - } - }); - this.bmp = new createjs.Sprite(spriteSheet); - - this.bmp.x = position.x; - this.bmp.y = position.y; - - gGameEngine.stage.addChild(this.bmp); - - this.bombs = []; - }, - - - update: function() { - if (!this.alive) { - return; - } - - if (gInputEngine.possessed !== this.id) { - return; - } - - if (gInputEngine.actions[this.controls.up]) { - this.animate('up'); - } else if (gInputEngine.actions[this.controls.down]) { - this.animate('down'); - } else if (gInputEngine.actions[this.controls.left]) { - this.animate('left'); - } else if (gInputEngine.actions[this.controls.right]) { - this.animate('right'); - } else { - this.animate('idle'); - } - }, - - /** - * Changes animation if requested animation is not already current. - */ - animate: function(animation) { - if (!this.bmp.currentAnimation || this.bmp.currentAnimation.indexOf(animation) === -1) { - this.bmp.gotoAndPlay(animation); - } - }, - - die: function() { - this.alive = false; - - this.bmp.gotoAndPlay('dead'); - this.fade(); - }, - - fade: function() { - var timer = 0; - var bmp = this.bmp; - var fade = setInterval(function() { - timer++; - - if (timer > 30) { - bmp.alpha -= 0.05; - } - if (bmp.alpha <= 0) { - clearInterval(fade); - } - - }, 30); - } -}); diff --git a/bomberman/frontend/src/main/webapp/js/ServerProxy.js b/bomberman/frontend/src/main/webapp/js/ServerProxy.js deleted file mode 100644 index 53bfc190d1..0000000000 --- a/bomberman/frontend/src/main/webapp/js/ServerProxy.js +++ /dev/null @@ -1,91 +0,0 @@ -ServerProxy = Class.extend({ - gameServerUrl: "localhost:8090", - matchMakerUrl: "localhost:8080/matchmaker/join", - gameId: "1234", - - socket: null, - - handler: {}, - - init: function () { - this.handler['REPLICA'] = gMessages.handleReplica; - this.handler['POSSESS'] = gMessages.handlePossess; - - var self = this; - gInputEngine.subscribe('up', function () { - self.socket.send(gMessages.move('up')) - }); - gInputEngine.subscribe('down', function () { - self.socket.send(gMessages.move('down')) - }); - gInputEngine.subscribe('left', function () { - self.socket.send(gMessages.move('left')) - }); - gInputEngine.subscribe('right', function () { - self.socket.send(gMessages.move('right')) - }); - gInputEngine.subscribe('bomb', function () { - self.socket.send(gMessages.plantBomb()) - }); - }, - - getSessionIdFromMatchMaker: function () { - var that = this; - var login = $("#loginInput").val(); - if(!login){ - alert("Please input login"); - console.log("Empty login, retry login"); - } - $.ajax({ - contentType: 'application/x-www-form-urlencoded', - data: { - "name": login - }, - dataType: 'text', - success: function(data){ - that.gameId=data; - console.log("Matchmaker returned gameId=" + data); - that.connectToGameServer(that.gameId, login); - }, - error: function(){ - alert("Matchmaker request failed, use default gameId=" + that.gameId); - console.log("Matchmaker request failed, use default gameId=" + that.gameId); - that.connectToGameServer(that.gameId, login); - }, - //processData: false - type: 'POST', - url: that.matchMakerUrl - }); - }, - - connectToGameServer: function (gameId, login) { - var self = this; - this.socket = new WebSocket("ws://" + this.gameServerUrl + "/game/connect?gameId=" + gameId + "&name=" + login); - - this.socket.onopen = function () { - console.log("Connection established."); - }; - - this.socket.onclose = function (event) { - if (event.wasClean) { - console.log('closed'); - } else { - console.log('alert close'); - } - console.log('Code: ' + event.code + ' cause: ' + event.reason); - }; - - this.socket.onmessage = function (event) { - var msg = JSON.parse(event.data); - if (self.handler[msg.topic] === undefined) - return; - - self.handler[msg.topic](msg); - }; - - this.socket.onerror = function (error) { - console.log("Error " + error.message); - }; - } - -}); diff --git a/bomberman/frontend/src/main/webapp/js/Tile.js b/bomberman/frontend/src/main/webapp/js/Tile.js deleted file mode 100644 index b0e0f2a6aa..0000000000 --- a/bomberman/frontend/src/main/webapp/js/Tile.js +++ /dev/null @@ -1,48 +0,0 @@ -Tile = Entity.extend({ - /** - * Entity position on map grid - */ - position: {}, - - /** - * Bitmap dimensions - */ - size: { - w: 32, - h: 32 - }, - - /** - * Bitmap animation - */ - bmp: null, - - material: '', - - init: function(id, material, position) { - this.id = id; - this.material = material; - this.position = position; - var img; - if (material == 'grass') { - img = gGameEngine.tilesImgs.grass; - } else if (material === 'Wall') { - img = gGameEngine.tilesImgs.wall; - } else if (material === 'Wood') { - img = gGameEngine.tilesImgs.wood; - } - this.bmp = new createjs.Bitmap(img); - - this.bmp.x = position.x; - this.bmp.y = position.y; - - gGameEngine.stage.addChild(this.bmp); - }, - - update: function() { - }, - - remove: function() { - gGameEngine.stage.removeChild(this.bmp); - } -}); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/Utils.js b/bomberman/frontend/src/main/webapp/js/Utils.js deleted file mode 100644 index 35446f8049..0000000000 --- a/bomberman/frontend/src/main/webapp/js/Utils.js +++ /dev/null @@ -1,48 +0,0 @@ -var Utils = {}; - -/** - * Returns true if positions are equal. - */ -Utils.comparePositions = function(pos1, pos2) { - return pos1.x == pos2.x && pos1.y == pos2.y; -}; - - -/** - * Convert bitmap pixels position to entity on grid position. - */ -Utils.convertToEntityPosition = function(pixels) { - var position = {}; - position.x = Math.round(pixels.x / gGameEngine.tileSize); - position.y = Math.round(pixels.y /gGameEngine.tileSize); - return position; -}; - -Utils.getEntityPosition = function (pixels) { - var position = {}; - position.x = pixels.x; - position.y = -pixels.y + 12 * 32; - return position; -} - -/** - * Convert entity on grid position to bitmap pixels position. - */ -Utils.convertToBitmapPosition = function(entity) { - var position = {}; - position.x = entity.x * gGameEngine.tileSize; - position.y = entity.y * gGameEngine.tileSize; - return position; -}; - -/** - * Removes an item from array. - */ -Utils.removeFromArray = function(array, item) { - for (var i = 0; i < array.length; i++) { - if (item == array[i]) { - array.splice(i, 1); - } - } - return array; -}; \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/core.js b/bomberman/frontend/src/main/webapp/js/core.js deleted file mode 100644 index 31f5105790..0000000000 --- a/bomberman/frontend/src/main/webapp/js/core.js +++ /dev/null @@ -1,64 +0,0 @@ -/* Simple JavaScript Inheritance - * By John Resig http://ejohn.org/ - * MIT Licensed. - */ -// Inspired by base2 and Prototype -(function(){ - var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; - - // The base Class implementation (does nothing) - this.Class = function(){}; - - // Create a new Class that inherits from this class - Class.extend = function(prop) { - var _super = this.prototype; - - // Instantiate a base class (but only create the instance, - // don't run the init constructor) - initializing = true; - var prototype = new this(); - initializing = false; - - // Copy the properties over onto the new prototype - for (var name in prop) { - // Check if we're overwriting an existing function - prototype[name] = typeof prop[name] == "function" && - typeof _super[name] == "function" && fnTest.test(prop[name]) ? - (function(name, fn){ - return function() { - var tmp = this._super; - - // Add a new ._super() method that is the same method - // but on the super-class - this._super = _super[name]; - - // The method only need to be bound temporarily, so we - // remove it when we're done executing - var ret = fn.apply(this, arguments); - this._super = tmp; - - return ret; - }; - })(name, prop[name]) : - prop[name]; - } - - // The dummy class constructor - function Class() { - // All construction is actually done in the init method - if ( !initializing && this.init ) - this.init.apply(this, arguments); - } - - // Populate our constructed prototype object - Class.prototype = prototype; - - // Enforce the constructor to be what we expect - Class.prototype.constructor = Class; - - // And make this class extendable - Class.extend = arguments.callee; - - return Class; - }; -})(); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/lib/easeljs-NEXT.combined.js b/bomberman/frontend/src/main/webapp/js/lib/easeljs-NEXT.combined.js deleted file mode 100644 index 6f2e17b093..0000000000 --- a/bomberman/frontend/src/main/webapp/js/lib/easeljs-NEXT.combined.js +++ /dev/null @@ -1,13413 +0,0 @@ -/*! -* EaselJS -* 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. -*/ - - -//############################################################################## -// 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; -}; - -//############################################################################## -// 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; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - -// public methods: - /** - * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true 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; -}()); - -//############################################################################## -// 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; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// static public methods: - /** - * Static initializer to mix EventDispatcher methods into a target object or prototype. - * - * EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class - * EventDispatcher.initialize(myObject); // add to a specific instance - * - * @method initialize - * @static - * @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a - * prototype. - **/ - EventDispatcher.initialize = function(target) { - target.addEventListener = p.addEventListener; - target.on = p.on; - target.removeEventListener = target.off = p.removeEventListener; - target.removeAllEventListeners = p.removeAllEventListeners; - target.hasEventListener = p.hasEventListener; - target.dispatchEvent = p.dispatchEvent; - target._dispatchEvent = p._dispatchEvent; - target.willTrigger = p.willTrigger; - }; - - -// public methods: - /** - * Adds the specified event listener. Note that adding multiple listeners to the same function will result in - * multiple callbacks getting fired. - * - *

Example

- * - * displayObject.addEventListener("click", handleClick); - * function handleClick(event) { - * // Click happened. - * } - * - * @method addEventListener - * @param {String} type The string type of the event. - * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when - * the event is dispatched. - * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. - * @return {Function | Object} Returns the listener for chaining or assignment. - **/ - p.addEventListener = function(type, listener, useCapture) { - var listeners; - if (useCapture) { - listeners = this._captureListeners = this._captureListeners||{}; - } else { - listeners = this._listeners = this._listeners||{}; - } - var arr = listeners[type]; - if (arr) { this.removeEventListener(type, listener, useCapture); } - arr = listeners[type]; // remove may have deleted the array - if (!arr) { listeners[type] = [listener]; } - else { arr.push(listener); } - return listener; - }; - - /** - * A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener - * only run once, associate arbitrary data with the listener, and remove the listener. - * - * This method works by creating an anonymous wrapper function and subscribing it with addEventListener. - * The 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; iExample - * - * createjs.Ticker.addEventListener("tick", handleTick); - * function handleTick(event) { - * // Actions carried out each tick (aka frame) - * if (!event.paused) { - * // Actions carried out when the Ticker is not paused. - * } - * } - * - * @class Ticker - * @uses EventDispatcher - * @static - **/ - function Ticker() { - throw "Ticker cannot be instantiated."; - } - - -// constants: - /** - * In this mode, Ticker uses the requestAnimationFrame API, but attempts to synch the ticks to target framerate. It - * uses a simple heuristic that compares the time of the RAF return to the target time for the current frame and - * dispatches the tick when the time is within a certain threshold. - * - * This mode has a higher variance for time between frames than {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}}, - * but does not require that content be time based as with {{#crossLink "Ticker/RAF:property"}}{{/crossLink}} while - * gaining the benefits of that API (screen synch, background throttling). - * - * Variance is usually lowest for framerates that are a divisor of the RAF frequency. This is usually 60, so - * framerates of 10, 12, 15, 20, and 30 work well. - * - * Falls back to {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}} if the requestAnimationFrame API is not - * supported. - * @property RAF_SYNCHED - * @static - * @type {String} - * @default "synched" - * @readonly - **/ - Ticker.RAF_SYNCHED = "synched"; - - /** - * In this mode, Ticker passes through the requestAnimationFrame heartbeat, ignoring the target framerate completely. - * Because requestAnimationFrame frequency is not deterministic, any content using this mode should be time based. - * You can leverage {{#crossLink "Ticker/getTime"}}{{/crossLink}} and the {{#crossLink "Ticker/tick:event"}}{{/crossLink}} - * event object's "delta" properties to make this easier. - * - * Falls back on {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}} if the requestAnimationFrame API is not - * supported. - * @property RAF - * @static - * @type {String} - * @default "raf" - * @readonly - **/ - Ticker.RAF = "raf"; - - /** - * In this mode, Ticker uses the setTimeout API. This provides predictable, adaptive frame timing, but does not - * provide the benefits of requestAnimationFrame (screen synch, background throttling). - * @property TIMEOUT - * @static - * @type {String} - * @default "timeout" - * @readonly - **/ - Ticker.TIMEOUT = "timeout"; - - -// static events: - /** - * Dispatched each tick. The event will be dispatched to each listener even when the Ticker has been paused using - * {{#crossLink "Ticker/setPaused"}}{{/crossLink}}. - * - *

Example

- * - * createjs.Ticker.addEventListener("tick", handleTick); - * function handleTick(event) { - * console.log("Paused:", event.paused, event.delta); - * } - * - * @event tick - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Boolean} paused Indicates whether the ticker is currently paused. - * @param {Number} delta The time elapsed in ms since the last tick. - * @param {Number} time The total time in ms since Ticker was initialized. - * @param {Number} runTime The total time in ms that Ticker was not paused since it was initialized. For example, - * you could determine the amount of time that the Ticker has been paused since initialization with `time-runTime`. - * @since 0.6.0 - */ - - -// public static properties: - /** - * Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}, and will be removed in a future version. If true, timingMode will - * use {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} by default. - * @deprecated Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}. - * @property useRAF - * @static - * @type {Boolean} - * @default false - **/ - Ticker.useRAF = false; - - /** - * Specifies the timing api (setTimeout or requestAnimationFrame) and mode to use. See - * {{#crossLink "Ticker/TIMEOUT"}}{{/crossLink}}, {{#crossLink "Ticker/RAF"}}{{/crossLink}}, and - * {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} for mode details. - * @property timingMode - * @static - * @type {String} - * @default Ticker.TIMEOUT - **/ - Ticker.timingMode = null; - - /** - * Specifies a maximum value for the delta property in the tick event object. This is useful when building time - * based animations and systems to prevent issues caused by large time gaps caused by background tabs, system sleep, - * alert dialogs, or other blocking routines. Double the expected frame duration is often an effective value - * (ex. maxDelta=50 when running at 40fps). - * - * This does not impact any other values (ex. time, runTime, etc), so you may experience issues if you enable maxDelta - * when using both delta and other values. - * - * If 0, there is no maximum. - * @property maxDelta - * @static - * @type {number} - * @default 0 - */ - Ticker.maxDelta = 0; - - /** - * When the ticker is paused, all listeners will still receive a tick event, but the paused property - * of the event will be `true`. Also, while paused the `runTime` will not increase. See {{#crossLink "Ticker/tick:event"}}{{/crossLink}}, - * {{#crossLink "Ticker/getTime"}}{{/crossLink}}, and {{#crossLink "Ticker/getEventTime"}}{{/crossLink}} for more - * info. - * - *

Example

- * - * createjs.Ticker.addEventListener("tick", handleTick); - * createjs.Ticker.paused = true; - * function handleTick(event) { - * console.log(event.paused, - * createjs.Ticker.getTime(false), - * createjs.Ticker.getTime(true)); - * } - * - * @property paused - * @static - * @type {Boolean} - * @default false - **/ - Ticker.paused = false; - - -// mix-ins: - // EventDispatcher methods: - Ticker.removeEventListener = null; - Ticker.removeAllEventListeners = null; - Ticker.dispatchEvent = null; - Ticker.hasEventListener = null; - Ticker._listeners = null; - createjs.EventDispatcher.initialize(Ticker); // inject EventDispatcher methods. - Ticker._addEventListener = Ticker.addEventListener; - Ticker.addEventListener = function() { - !Ticker._inited&&Ticker.init(); - return Ticker._addEventListener.apply(Ticker, arguments); - }; - - -// private static properties: - /** - * @property _inited - * @static - * @type {Boolean} - * @protected - **/ - Ticker._inited = false; - - /** - * @property _startTime - * @static - * @type {Number} - * @protected - **/ - Ticker._startTime = 0; - - /** - * @property _pausedTime - * @static - * @type {Number} - * @protected - **/ - Ticker._pausedTime=0; - - /** - * The number of ticks that have passed - * @property _ticks - * @static - * @type {Number} - * @protected - **/ - Ticker._ticks = 0; - - /** - * The number of ticks that have passed while Ticker has been paused - * @property _pausedTicks - * @static - * @type {Number} - * @protected - **/ - Ticker._pausedTicks = 0; - - /** - * @property _interval - * @static - * @type {Number} - * @protected - **/ - Ticker._interval = 50; - - /** - * @property _lastTime - * @static - * @type {Number} - * @protected - **/ - Ticker._lastTime = 0; - - /** - * @property _times - * @static - * @type {Array} - * @protected - **/ - Ticker._times = null; - - /** - * @property _tickTimes - * @static - * @type {Array} - * @protected - **/ - Ticker._tickTimes = null; - - /** - * Stores the timeout or requestAnimationFrame id. - * @property _timerId - * @static - * @type {Number} - * @protected - **/ - Ticker._timerId = null; - - /** - * True if currently using requestAnimationFrame, false if using setTimeout. This may be different than timingMode - * if that property changed and a tick hasn't fired. - * @property _raf - * @static - * @type {Boolean} - * @protected - **/ - Ticker._raf = true; - - -// static getter / setters: - /** - * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead. - * @method setInterval - * @static - * @param {Number} interval - * @deprecated - **/ - Ticker.setInterval = function(interval) { - Ticker._interval = interval; - if (!Ticker._inited) { return; } - Ticker._setupTick(); - }; - - /** - * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead. - * @method getInterval - * @static - * @return {Number} - * @deprecated - **/ - Ticker.getInterval = function() { - return Ticker._interval; - }; - - /** - * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead. - * @method setFPS - * @static - * @param {Number} value - * @deprecated - **/ - Ticker.setFPS = function(value) { - Ticker.setInterval(1000/value); - }; - - /** - * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead. - * @method getFPS - * @static - * @return {Number} - * @deprecated - **/ - Ticker.getFPS = function() { - return 1000/Ticker._interval; - }; - - /** - * Indicates the target time (in milliseconds) between ticks. Default is 50 (20 FPS). - * Note that actual time between ticks may be more than specified depending on CPU load. - * This property is ignored if the ticker is using the `RAF` timing mode. - * @property interval - * @static - * @type {Number} - **/ - - /** - * Indicates the target frame rate in frames per second (FPS). Effectively just a shortcut to `interval`, where - * `framerate == 1000/interval`. - * @property framerate - * @static - * @type {Number} - **/ - try { - Object.defineProperties(Ticker, { - interval: { get: Ticker.getInterval, set: Ticker.setInterval }, - framerate: { get: Ticker.getFPS, set: Ticker.setFPS } - }); - } catch (e) { console.log(e); } - - -// public static methods: - /** - * Starts the tick. This is called automatically when the first listener is added. - * @method init - * @static - **/ - Ticker.init = function() { - if (Ticker._inited) { return; } - Ticker._inited = true; - Ticker._times = []; - Ticker._tickTimes = []; - Ticker._startTime = Ticker._getTime(); - Ticker._times.push(Ticker._lastTime = 0); - Ticker.interval = Ticker._interval; - }; - - /** - * Stops the Ticker and removes all listeners. Use init() to restart the Ticker. - * @method reset - * @static - **/ - Ticker.reset = function() { - if (Ticker._raf) { - var f = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame; - f&&f(Ticker._timerId); - } else { - clearTimeout(Ticker._timerId); - } - Ticker.removeAllEventListeners("tick"); - Ticker._timerId = Ticker._times = Ticker._tickTimes = null; - Ticker._startTime = Ticker._lastTime = Ticker._ticks = 0; - Ticker._inited = false; - }; - - /** - * Returns the average time spent within a tick. This can vary significantly from the value provided by getMeasuredFPS - * because it only measures the time spent within the tick execution stack. - * - * Example 1: With a target FPS of 20, getMeasuredFPS() returns 20fps, which indicates an average of 50ms between - * the end of one tick and the end of the next. However, getMeasuredTickTime() returns 15ms. This indicates that - * there may be up to 35ms of "idle" time between the end of one tick and the start of the next. - * - * Example 2: With a target FPS of 30, getFPS() returns 10fps, which indicates an average of 100ms between the end of - * one tick and the end of the next. However, getMeasuredTickTime() returns 20ms. This would indicate that something - * other than the tick is using ~80ms (another script, DOM rendering, etc). - * @method getMeasuredTickTime - * @static - * @param {Number} [ticks] The number of previous ticks over which to measure the average time spent in a tick. - * Defaults to the number of ticks per second. To get only the last tick's time, pass in 1. - * @return {Number} The average time spent in a tick in milliseconds. - **/ - Ticker.getMeasuredTickTime = function(ticks) { - var ttl=0, times=Ticker._tickTimes; - if (!times || times.length < 1) { return -1; } - - // by default, calculate average for the past ~1 second: - ticks = Math.min(times.length, ticks||(Ticker.getFPS()|0)); - for (var i=0; i= (Ticker._interval-1)*0.97) { - Ticker._tick(); - } - }; - - /** - * @method _handleRAF - * @static - * @protected - **/ - Ticker._handleRAF = function() { - Ticker._timerId = null; - Ticker._setupTick(); - Ticker._tick(); - }; - - /** - * @method _handleTimeout - * @static - * @protected - **/ - Ticker._handleTimeout = function() { - Ticker._timerId = null; - Ticker._setupTick(); - Ticker._tick(); - }; - - /** - * @method _setupTick - * @static - * @protected - **/ - Ticker._setupTick = function() { - if (Ticker._timerId != null) { return; } // avoid duplicates - - var mode = Ticker.timingMode||(Ticker.useRAF&&Ticker.RAF_SYNCHED); - if (mode == Ticker.RAF_SYNCHED || mode == Ticker.RAF) { - var f = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame; - if (f) { - Ticker._timerId = f(mode == Ticker.RAF ? Ticker._handleRAF : Ticker._handleSynch); - Ticker._raf = true; - return; - } - } - Ticker._raf = false; - Ticker._timerId = setTimeout(Ticker._handleTimeout, Ticker._interval); - }; - - /** - * @method _tick - * @static - * @protected - **/ - Ticker._tick = function() { - var paused = Ticker.paused; - var time = Ticker._getTime(); - var elapsedTime = time-Ticker._lastTime; - Ticker._lastTime = time; - Ticker._ticks++; - - if (paused) { - Ticker._pausedTicks++; - Ticker._pausedTime += elapsedTime; - } - - if (Ticker.hasEventListener("tick")) { - var event = new createjs.Event("tick"); - var maxDelta = Ticker.maxDelta; - event.delta = (maxDelta && elapsedTime > maxDelta) ? maxDelta : elapsedTime; - event.paused = paused; - event.time = time; - event.runTime = time-Ticker._pausedTime; - Ticker.dispatchEvent(event); - } - - Ticker._tickTimes.unshift(Ticker._getTime()-time); - while (Ticker._tickTimes.length > 100) { Ticker._tickTimes.pop(); } - - Ticker._times.unshift(time); - while (Ticker._times.length > 100) { Ticker._times.pop(); } - }; - - /** - * @method _getTime - * @static - * @protected - **/ - var now = window.performance && (performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow); - Ticker._getTime = function() { - return ((now&&now.call(performance))||(new Date().getTime())) - Ticker._startTime; - }; - - - createjs.Ticker = Ticker; -}()); - -//############################################################################## -// UID.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Global utility for generating sequential unique ID numbers. The UID class uses a static interface (ex. UID.get()) - * and should not be instantiated. - * @class UID - * @static - **/ - function UID() { - throw "UID cannot be instantiated"; - } - - -// private static properties: - /** - * @property _nextID - * @type Number - * @protected - **/ - UID._nextID = 0; - - -// public static methods: - /** - * Returns the next unique id. - * @method get - * @return {Number} The next unique id - * @static - **/ - UID.get = function() { - return UID._nextID++; - }; - - - createjs.UID = UID; -}()); - -//############################################################################## -// MouseEvent.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Passed as the parameter to all mouse/pointer/touch related events. For a listing of mouse events and their properties, - * see the {{#crossLink "DisplayObject"}}{{/crossLink}} and {{#crossLink "Stage"}}{{/crossLink}} event listings. - * @class MouseEvent - * @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. - * @param {Number} stageX The normalized x position relative to the stage. - * @param {Number} stageY The normalized y position relative to the stage. - * @param {MouseEvent} nativeEvent The native DOM event related to this mouse event. - * @param {Number} pointerID The unique id for the pointer. - * @param {Boolean} primary Indicates whether this is the primary pointer in a multitouch environment. - * @param {Number} rawX The raw x position relative to the stage. - * @param {Number} rawY The raw y position relative to the stage. - * @param {DisplayObject} relatedTarget The secondary target for the event. - * @extends Event - * @constructor - **/ - function MouseEvent(type, bubbles, cancelable, stageX, stageY, nativeEvent, pointerID, primary, rawX, rawY, relatedTarget) { - this.Event_constructor(type, bubbles, cancelable); - - - // public properties: - /** - * The normalized x position on the stage. This will always be within the range 0 to stage width. - * @property stageX - * @type Number - */ - this.stageX = stageX; - - /** - * The normalized y position on the stage. This will always be within the range 0 to stage height. - * @property stageY - * @type Number - **/ - this.stageY = stageY; - - /** - * The raw x position relative to the stage. Normally this will be the same as the stageX value, unless - * stage.mouseMoveOutside is true and the pointer is outside of the stage bounds. - * @property rawX - * @type Number - */ - this.rawX = (rawX==null)?stageX:rawX; - - /** - * The raw y position relative to the stage. Normally this will be the same as the stageY value, unless - * stage.mouseMoveOutside is true and the pointer is outside of the stage bounds. - * @property rawY - * @type Number - */ - this.rawY = (rawY==null)?stageY:rawY; - - /** - * The native MouseEvent generated by the browser. The properties and API for this - * event may differ between browsers. This property will be null if the - * EaselJS property was not directly generated from a native MouseEvent. - * @property nativeEvent - * @type HtmlMouseEvent - * @default null - **/ - this.nativeEvent = nativeEvent; - - /** - * The unique id for the pointer (touch point or cursor). This will be either -1 for the mouse, or the system - * supplied id value. - * @property pointerID - * @type {Number} - */ - this.pointerID = pointerID; - - /** - * Indicates whether this is the primary pointer in a multitouch environment. This will always be true for the mouse. - * For touch pointers, the first pointer in the current stack will be considered the primary pointer. - * @property primary - * @type {Boolean} - */ - this.primary = !!primary; - - /** - * The secondary target for the event, if applicable. This is used for mouseout/rollout - * events to indicate the object that the mouse entered from, mouseover/rollover for the object the mouse exited, - * and stagemousedown/stagemouseup events for the object that was the under the cursor, if any. - * - * Only valid interaction targets will be returned (ie. objects with mouse listeners or a cursor set). - * @property relatedTarget - * @type {DisplayObject} - */ - this.relatedTarget = relatedTarget; - } - var p = createjs.extend(MouseEvent, createjs.Event); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// getter / setters: - /** - * Returns the x position of the mouse in the local coordinate system of the current target (ie. the dispatcher). - * @property localX - * @type {Number} - * @readonly - */ - p._get_localX = function() { - return this.currentTarget.globalToLocal(this.rawX, this.rawY).x; - }; - - /** - * Returns the y position of the mouse in the local coordinate system of the current target (ie. the dispatcher). - * @property localY - * @type {Number} - * @readonly - */ - p._get_localY = function() { - return this.currentTarget.globalToLocal(this.rawX, this.rawY).y; - }; - - /** - * Indicates whether the event was generated by a touch input (versus a mouse input). - * @property isTouch - * @type {Boolean} - * @readonly - */ - p._get_isTouch = function() { - return this.pointerID !== -1; - }; - - - try { - Object.defineProperties(p, { - localX: { get: p._get_localX }, - localY: { get: p._get_localY }, - isTouch: { get: p._get_isTouch } - }); - } catch (e) {} // TODO: use Log - - -// public methods: - /** - * Returns a clone of the MouseEvent instance. - * @method clone - * @return {MouseEvent} a clone of the MouseEvent instance. - **/ - p.clone = function() { - return new MouseEvent(this.type, this.bubbles, this.cancelable, this.stageX, this.stageY, this.nativeEvent, this.pointerID, this.primary, this.rawX, this.rawY); - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[MouseEvent (type="+this.type+" stageX="+this.stageX+" stageY="+this.stageY+")]"; - }; - - - createjs.MouseEvent = createjs.promote(MouseEvent, "Event"); -}()); - -//############################################################################## -// Matrix2D.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Represents an affine transformation matrix, and provides tools for constructing and concatenating matrices. - * - * This matrix can be visualized as: - * - * [ a c tx - * b d ty - * 0 0 1 ] - * - * Note the locations of b and c. - * - * @class Matrix2D - * @param {Number} [a=1] Specifies the a property for the new matrix. - * @param {Number} [b=0] Specifies the b property for the new matrix. - * @param {Number} [c=0] Specifies the c property for the new matrix. - * @param {Number} [d=1] Specifies the d property for the new matrix. - * @param {Number} [tx=0] Specifies the tx property for the new matrix. - * @param {Number} [ty=0] Specifies the ty property for the new matrix. - * @constructor - **/ - function Matrix2D(a, b, c, d, tx, ty) { - this.setValues(a,b,c,d,tx,ty); - - // public properties: - // assigned in the setValues method. - /** - * Position (0, 0) in a 3x3 affine transformation matrix. - * @property a - * @type Number - **/ - - /** - * Position (0, 1) in a 3x3 affine transformation matrix. - * @property b - * @type Number - **/ - - /** - * Position (1, 0) in a 3x3 affine transformation matrix. - * @property c - * @type Number - **/ - - /** - * Position (1, 1) in a 3x3 affine transformation matrix. - * @property d - * @type Number - **/ - - /** - * Position (2, 0) in a 3x3 affine transformation matrix. - * @property tx - * @type Number - **/ - - /** - * Position (2, 1) in a 3x3 affine transformation matrix. - * @property ty - * @type Number - **/ - } - var p = Matrix2D.prototype; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// constants: - /** - * Multiplier for converting degrees to radians. Used internally by Matrix2D. - * @property DEG_TO_RAD - * @static - * @final - * @type Number - * @readonly - **/ - Matrix2D.DEG_TO_RAD = Math.PI/180; - - -// static public properties: - /** - * An identity matrix, representing a null transformation. - * @property identity - * @static - * @type Matrix2D - * @readonly - **/ - Matrix2D.identity = null; // set at bottom of class definition. - - -// public methods: - /** - * Sets the specified values on this instance. - * @method setValues - * @param {Number} [a=1] Specifies the a property for the new matrix. - * @param {Number} [b=0] Specifies the b property for the new matrix. - * @param {Number} [c=0] Specifies the c property for the new matrix. - * @param {Number} [d=1] Specifies the d property for the new matrix. - * @param {Number} [tx=0] Specifies the tx property for the new matrix. - * @param {Number} [ty=0] Specifies the ty property for the new matrix. - * @return {Matrix2D} This instance. Useful for chaining method calls. - */ - p.setValues = function(a, b, c, d, tx, ty) { - // don't forget to update docs in the constructor if these change: - this.a = (a == null) ? 1 : a; - this.b = b || 0; - this.c = c || 0; - this.d = (d == null) ? 1 : d; - this.tx = tx || 0; - this.ty = ty || 0; - return this; - }; - - /** - * Appends the specified matrix properties to this matrix. All parameters are required. - * This is the equivalent of multiplying `(this matrix) * (specified matrix)`. - * @method append - * @param {Number} a - * @param {Number} b - * @param {Number} c - * @param {Number} d - * @param {Number} tx - * @param {Number} ty - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.append = function(a, b, c, d, tx, ty) { - var a1 = this.a; - var b1 = this.b; - var c1 = this.c; - var d1 = this.d; - if (a != 1 || b != 0 || c != 0 || d != 1) { - this.a = a1*a+c1*b; - this.b = b1*a+d1*b; - this.c = a1*c+c1*d; - this.d = b1*c+d1*d; - } - this.tx = a1*tx+c1*ty+this.tx; - this.ty = b1*tx+d1*ty+this.ty; - return this; - }; - - /** - * Prepends the specified matrix properties to this matrix. - * This is the equivalent of multiplying `(specified matrix) * (this matrix)`. - * All parameters are required. - * @method prepend - * @param {Number} a - * @param {Number} b - * @param {Number} c - * @param {Number} d - * @param {Number} tx - * @param {Number} ty - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.prepend = function(a, b, c, d, tx, ty) { - var a1 = this.a; - var c1 = this.c; - var tx1 = this.tx; - - this.a = a*a1+c*this.b; - this.b = b*a1+d*this.b; - this.c = a*c1+c*this.d; - this.d = b*c1+d*this.d; - this.tx = a*tx1+c*this.ty+tx; - this.ty = b*tx1+d*this.ty+ty; - return this; - }; - - /** - * Appends the specified matrix to this matrix. - * This is the equivalent of multiplying `(this matrix) * (specified matrix)`. - * @method appendMatrix - * @param {Matrix2D} matrix - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.appendMatrix = function(matrix) { - return this.append(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); - }; - - /** - * Prepends the specified matrix to this matrix. - * This is the equivalent of multiplying `(specified matrix) * (this matrix)`. - * For example, you could calculate the combined transformation for a child object using: - * - * var o = myDisplayObject; - * var mtx = o.getMatrix(); - * while (o = o.parent) { - * // prepend each parent's transformation in turn: - * o.prependMatrix(o.getMatrix()); - * } - * @method prependMatrix - * @param {Matrix2D} matrix - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.prependMatrix = function(matrix) { - return this.prepend(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); - }; - - /** - * Generates matrix properties from the specified display object transform properties, and appends them to this matrix. - * For example, you can use this to generate a matrix representing the transformations of a display object: - * - * var mtx = new createjs.Matrix2D(); - * mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation); - * @method appendTransform - * @param {Number} x - * @param {Number} y - * @param {Number} scaleX - * @param {Number} scaleY - * @param {Number} rotation - * @param {Number} skewX - * @param {Number} skewY - * @param {Number} regX Optional. - * @param {Number} regY Optional. - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.appendTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) { - if (rotation%360) { - var r = rotation*Matrix2D.DEG_TO_RAD; - var cos = Math.cos(r); - var sin = Math.sin(r); - } else { - cos = 1; - sin = 0; - } - - if (skewX || skewY) { - // TODO: can this be combined into a single append operation? - skewX *= Matrix2D.DEG_TO_RAD; - skewY *= Matrix2D.DEG_TO_RAD; - this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y); - this.append(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, 0, 0); - } else { - this.append(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, x, y); - } - - if (regX || regY) { - // append the registration offset: - this.tx -= regX*this.a+regY*this.c; - this.ty -= regX*this.b+regY*this.d; - } - return this; - }; - - /** - * Generates matrix properties from the specified display object transform properties, and prepends them to this matrix. - * For example, you could calculate the combined transformation for a child object using: - * - * var o = myDisplayObject; - * var mtx = new createjs.Matrix2D(); - * do { - * // prepend each parent's transformation in turn: - * mtx.prependTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY); - * } while (o = o.parent); - * - * Note that the above example would not account for {{#crossLink "DisplayObject/transformMatrix:property"}}{{/crossLink}} - * values. See {{#crossLink "Matrix2D/prependMatrix"}}{{/crossLink}} for an example that does. - * @method prependTransform - * @param {Number} x - * @param {Number} y - * @param {Number} scaleX - * @param {Number} scaleY - * @param {Number} rotation - * @param {Number} skewX - * @param {Number} skewY - * @param {Number} regX Optional. - * @param {Number} regY Optional. - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.prependTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) { - if (rotation%360) { - var r = rotation*Matrix2D.DEG_TO_RAD; - var cos = Math.cos(r); - var sin = Math.sin(r); - } else { - cos = 1; - sin = 0; - } - - if (regX || regY) { - // prepend the registration offset: - this.tx -= regX; this.ty -= regY; - } - if (skewX || skewY) { - // TODO: can this be combined into a single prepend operation? - skewX *= Matrix2D.DEG_TO_RAD; - skewY *= Matrix2D.DEG_TO_RAD; - this.prepend(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, 0, 0); - this.prepend(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y); - } else { - this.prepend(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, x, y); - } - return this; - }; - - /** - * Applies a clockwise rotation transformation to the matrix. - * @method rotate - * @param {Number} angle The angle to rotate by, in degrees. To use a value in radians, multiply it by `180/Math.PI`. - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.rotate = function(angle) { - angle = angle*Matrix2D.DEG_TO_RAD; - var cos = Math.cos(angle); - var sin = Math.sin(angle); - - var a1 = this.a; - var b1 = this.b; - - this.a = a1*cos+this.c*sin; - this.b = b1*cos+this.d*sin; - this.c = -a1*sin+this.c*cos; - this.d = -b1*sin+this.d*cos; - return this; - }; - - /** - * Applies a skew transformation to the matrix. - * @method skew - * @param {Number} skewX The amount to skew horizontally in degrees. To use a value in radians, multiply it by `180/Math.PI`. - * @param {Number} skewY The amount to skew vertically in degrees. - * @return {Matrix2D} This matrix. Useful for chaining method calls. - */ - p.skew = function(skewX, skewY) { - skewX = skewX*Matrix2D.DEG_TO_RAD; - skewY = skewY*Matrix2D.DEG_TO_RAD; - this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), 0, 0); - return this; - }; - - /** - * Applies a scale transformation to the matrix. - * @method scale - * @param {Number} x The amount to scale horizontally. E.G. a value of 2 will double the size in the X direction, and 0.5 will halve it. - * @param {Number} y The amount to scale vertically. - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.scale = function(x, y) { - this.a *= x; - this.b *= x; - this.c *= y; - this.d *= y; - //this.tx *= x; - //this.ty *= y; - return this; - }; - - /** - * Translates the matrix on the x and y axes. - * @method translate - * @param {Number} x - * @param {Number} y - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.translate = function(x, y) { - this.tx += this.a*x + this.c*y; - this.ty += this.b*x + this.d*y; - return this; - }; - - /** - * Sets the properties of the matrix to those of an identity matrix (one that applies a null transformation). - * @method identity - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.identity = function() { - this.a = this.d = 1; - this.b = this.c = this.tx = this.ty = 0; - return this; - }; - - /** - * Inverts the matrix, causing it to perform the opposite transformation. - * @method invert - * @return {Matrix2D} This matrix. Useful for chaining method calls. - **/ - p.invert = function() { - var a1 = this.a; - var b1 = this.b; - var c1 = this.c; - var d1 = this.d; - var tx1 = this.tx; - var n = a1*d1-b1*c1; - - this.a = d1/n; - this.b = -b1/n; - this.c = -c1/n; - this.d = a1/n; - this.tx = (c1*this.ty-d1*tx1)/n; - this.ty = -(a1*this.ty-b1*tx1)/n; - return this; - }; - - /** - * Returns true if the matrix is an identity matrix. - * @method isIdentity - * @return {Boolean} - **/ - p.isIdentity = function() { - return this.tx === 0 && this.ty === 0 && this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1; - }; - - /** - * Returns true if this matrix is equal to the specified matrix (all property values are equal). - * @method equals - * @param {Matrix2D} matrix The matrix to compare. - * @return {Boolean} - **/ - p.equals = function(matrix) { - return this.tx === matrix.tx && this.ty === matrix.ty && this.a === matrix.a && this.b === matrix.b && this.c === matrix.c && this.d === matrix.d; - }; - - /** - * Transforms a point according to this matrix. - * @method transformPoint - * @param {Number} x The x component of the point to transform. - * @param {Number} y The y component of the point to transform. - * @param {Point | Object} [pt] An object to copy the result into. If omitted a generic object with x/y properties will be returned. - * @return {Point} This matrix. Useful for chaining method calls. - **/ - p.transformPoint = function(x, y, pt) { - pt = pt||{}; - pt.x = x*this.a+y*this.c+this.tx; - pt.y = x*this.b+y*this.d+this.ty; - return pt; - }; - - /** - * Decomposes the matrix into transform properties (x, y, scaleX, scaleY, and rotation). Note that these values - * may not match the transform properties you used to generate the matrix, though they will produce the same visual - * results. - * @method decompose - * @param {Object} target The object to apply the transform properties to. If null, then a new object will be returned. - * @return {Object} The target, or a new generic object with the transform properties applied. - */ - p.decompose = function(target) { - // TODO: it would be nice to be able to solve for whether the matrix can be decomposed into only scale/rotation even when scale is negative - if (target == null) { target = {}; } - target.x = this.tx; - target.y = this.ty; - target.scaleX = Math.sqrt(this.a * this.a + this.b * this.b); - target.scaleY = Math.sqrt(this.c * this.c + this.d * this.d); - - var skewX = Math.atan2(-this.c, this.d); - var skewY = Math.atan2(this.b, this.a); - - var delta = Math.abs(1-skewX/skewY); - if (delta < 0.00001) { // effectively identical, can use rotation: - target.rotation = skewY/Matrix2D.DEG_TO_RAD; - if (this.a < 0 && this.d >= 0) { - target.rotation += (target.rotation <= 0) ? 180 : -180; - } - target.skewX = target.skewY = 0; - } else { - target.skewX = skewX/Matrix2D.DEG_TO_RAD; - target.skewY = skewY/Matrix2D.DEG_TO_RAD; - } - return target; - }; - - /** - * Copies all properties from the specified matrix to this matrix. - * @method copy - * @param {Matrix2D} matrix The matrix to copy properties from. - * @return {Matrix2D} This matrix. Useful for chaining method calls. - */ - p.copy = function(matrix) { - return this.setValues(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); - }; - - /** - * Returns a clone of the Matrix2D instance. - * @method clone - * @return {Matrix2D} a clone of the Matrix2D instance. - **/ - p.clone = function() { - return new Matrix2D(this.a, this.b, this.c, this.d, this.tx, this.ty); - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Matrix2D (a="+this.a+" b="+this.b+" c="+this.c+" d="+this.d+" tx="+this.tx+" ty="+this.ty+")]"; - }; - - // this has to be populated after the class is defined: - Matrix2D.identity = new Matrix2D(); - - - createjs.Matrix2D = Matrix2D; -}()); - -//############################################################################## -// DisplayProps.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - /** - * Used for calculating and encapsulating display related properties. - * @class DisplayProps - * @param {Number} [visible=true] Visible value. - * @param {Number} [alpha=1] Alpha value. - * @param {Number} [shadow=null] A Shadow instance or null. - * @param {Number} [compositeOperation=null] A compositeOperation value or null. - * @param {Number} [matrix] A transformation matrix. Defaults to a new identity matrix. - * @constructor - **/ - function DisplayProps(visible, alpha, shadow, compositeOperation, matrix) { - this.setValues(visible, alpha, shadow, compositeOperation, matrix); - - // public properties: - // assigned in the setValues method. - /** - * Property representing the alpha that will be applied to a display object. - * @property alpha - * @type Number - **/ - - /** - * Property representing the shadow that will be applied to a display object. - * @property shadow - * @type Shadow - **/ - - /** - * Property representing the compositeOperation that will be applied to a display object. - * You can find a list of valid composite operations at: - * https://developer.mozilla.org/en/Canvas_tutorial/Compositing - * @property compositeOperation - * @type String - **/ - - /** - * Property representing the value for visible that will be applied to a display object. - * @property visible - * @type Boolean - **/ - - /** - * The transformation matrix that will be applied to a display object. - * @property matrix - * @type Matrix2D - **/ - } - var p = DisplayProps.prototype; - -// initialization: - /** - * Reinitializes the instance with the specified values. - * @method setValues - * @param {Number} [visible=true] Visible value. - * @param {Number} [alpha=1] Alpha value. - * @param {Number} [shadow=null] A Shadow instance or null. - * @param {Number} [compositeOperation=null] A compositeOperation value or null. - * @param {Number} [matrix] A transformation matrix. Defaults to an identity matrix. - * @return {DisplayProps} This instance. Useful for chaining method calls. - * @chainable - */ - p.setValues = function (visible, alpha, shadow, compositeOperation, matrix) { - this.visible = visible == null ? true : !!visible; - this.alpha = alpha == null ? 1 : alpha; - this.shadow = shadow; - this.compositeOperation = compositeOperation; - this.matrix = matrix || (this.matrix&&this.matrix.identity()) || new createjs.Matrix2D(); - return this; - }; - -// public methods: - /** - * Appends the specified display properties. This is generally used to apply a child's properties its parent's. - * @method append - * @param {Boolean} visible desired visible value - * @param {Number} alpha desired alpha value - * @param {Shadow} shadow desired shadow value - * @param {String} compositeOperation desired composite operation value - * @param {Matrix2D} [matrix] a Matrix2D instance - * @return {DisplayProps} This instance. Useful for chaining method calls. - * @chainable - */ - p.append = function(visible, alpha, shadow, compositeOperation, matrix) { - this.alpha *= alpha; - this.shadow = shadow || this.shadow; - this.compositeOperation = compositeOperation || this.compositeOperation; - this.visible = this.visible && visible; - matrix&&this.matrix.appendMatrix(matrix); - return this; - }; - - /** - * Prepends the specified display properties. This is generally used to apply a parent's properties to a child's. - * For example, to get the combined display properties that would be applied to a child, you could use: - * - * var o = myDisplayObject; - * var props = new createjs.DisplayProps(); - * do { - * // prepend each parent's props in turn: - * props.prepend(o.visible, o.alpha, o.shadow, o.compositeOperation, o.getMatrix()); - * } while (o = o.parent); - * - * @method prepend - * @param {Boolean} visible desired visible value - * @param {Number} alpha desired alpha value - * @param {Shadow} shadow desired shadow value - * @param {String} compositeOperation desired composite operation value - * @param {Matrix2D} [matrix] a Matrix2D instance - * @return {DisplayProps} This instance. Useful for chaining method calls. - * @chainable - */ - p.prepend = function(visible, alpha, shadow, compositeOperation, matrix) { - this.alpha *= alpha; - this.shadow = this.shadow || shadow; - this.compositeOperation = this.compositeOperation || compositeOperation; - this.visible = this.visible && visible; - matrix&&this.matrix.prependMatrix(matrix); - return this; - }; - - /** - * Resets this instance and its matrix to default values. - * @method identity - * @return {DisplayProps} This instance. Useful for chaining method calls. - * @chainable - */ - p.identity = function() { - this.visible = true; - this.alpha = 1; - this.shadow = this.compositeOperation = null; - this.matrix.identity(); - return this; - }; - - /** - * Returns a clone of the DisplayProps instance. Clones the associated matrix. - * @method clone - * @return {DisplayProps} a clone of the DisplayProps instance. - **/ - p.clone = function() { - return new DisplayProps(this.alpha, this.shadow, this.compositeOperation, this.visible, this.matrix.clone()); - }; - -// private methods: - - createjs.DisplayProps = DisplayProps; -})(); - -//############################################################################## -// Point.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Represents a point on a 2 dimensional x / y coordinate system. - * - *

Example

- * - * var point = new createjs.Point(0, 100); - * - * @class Point - * @param {Number} [x=0] X position. - * @param {Number} [y=0] Y position. - * @constructor - **/ - function Point(x, y) { - this.setValues(x, y); - - - // public properties: - // assigned in the setValues method. - /** - * X position. - * @property x - * @type Number - **/ - - /** - * Y position. - * @property y - * @type Number - **/ - } - var p = Point.prototype; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// public methods: - /** - * Sets the specified values on this instance. - * @method setValues - * @param {Number} [x=0] X position. - * @param {Number} [y=0] Y position. - * @return {Point} This instance. Useful for chaining method calls. - * @chainable - */ - p.setValues = function(x, y) { - this.x = x||0; - this.y = y||0; - return this; - }; - - /** - * Copies all properties from the specified point to this point. - * @method copy - * @param {Point} point The point to copy properties from. - * @return {Point} This point. Useful for chaining method calls. - * @chainable - */ - p.copy = function(point) { - this.x = point.x; - this.y = point.y; - return this; - }; - - /** - * Returns a clone of the Point instance. - * @method clone - * @return {Point} a clone of the Point instance. - **/ - p.clone = function() { - return new Point(this.x, this.y); - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Point (x="+this.x+" y="+this.y+")]"; - }; - - - createjs.Point = Point; -}()); - -//############################################################################## -// Rectangle.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Represents a rectangle as defined by the points (x, y) and (x+width, y+height). - * - *

Example

- * - * var rect = new createjs.Rectangle(0, 0, 100, 100); - * - * @class Rectangle - * @param {Number} [x=0] X position. - * @param {Number} [y=0] Y position. - * @param {Number} [width=0] The width of the Rectangle. - * @param {Number} [height=0] The height of the Rectangle. - * @constructor - **/ - function Rectangle(x, y, width, height) { - this.setValues(x, y, width, height); - - - // public properties: - // assigned in the setValues method. - /** - * X position. - * @property x - * @type Number - **/ - - /** - * Y position. - * @property y - * @type Number - **/ - - /** - * Width. - * @property width - * @type Number - **/ - - /** - * Height. - * @property height - * @type Number - **/ - } - var p = Rectangle.prototype; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// public methods: - /** - * Sets the specified values on this instance. - * @method setValues - * @param {Number} [x=0] X position. - * @param {Number} [y=0] Y position. - * @param {Number} [width=0] The width of the Rectangle. - * @param {Number} [height=0] The height of the Rectangle. - * @return {Rectangle} This instance. Useful for chaining method calls. - * @chainable - */ - p.setValues = function(x, y, width, height) { - // don't forget to update docs in the constructor if these change: - this.x = x||0; - this.y = y||0; - this.width = width||0; - this.height = height||0; - return this; - }; - - /** - * Extends the rectangle's bounds to include the described point or rectangle. - * @method extend - * @param {Number} x X position of the point or rectangle. - * @param {Number} y Y position of the point or rectangle. - * @param {Number} [width=0] The width of the rectangle. - * @param {Number} [height=0] The height of the rectangle. - * @return {Rectangle} This instance. Useful for chaining method calls. - * @chainable - */ - p.extend = function(x, y, width, height) { - width = width||0; - height = height||0; - if (x+width > this.x+this.width) { this.width = x+width-this.x; } - if (y+height > this.y+this.height) { this.height = y+height-this.y; } - if (x < this.x) { this.width += this.x-x; this.x = x; } - if (y < this.y) { this.height += this.y-y; this.y = y; } - return this; - }; - - /** - * Adds the specified padding to the rectangle's bounds. - * @method pad - * @param {Number} top - * @param {Number} left - * @param {Number} right - * @param {Number} bottom - * @return {Rectangle} This instance. Useful for chaining method calls. - * @chainable - */ - p.pad = function(top, left, bottom, right) { - this.x -= left; - this.y -= top; - this.width += left+right; - this.height += top+bottom; - return this; - }; - - /** - * Copies all properties from the specified rectangle to this rectangle. - * @method copy - * @param {Rectangle} rectangle The rectangle to copy properties from. - * @return {Rectangle} This rectangle. Useful for chaining method calls. - * @chainable - */ - p.copy = function(rectangle) { - return this.setValues(rectangle.x, rectangle.y, rectangle.width, rectangle.height); - }; - - /** - * Returns true if this rectangle fully encloses the described point or rectangle. - * @method contains - * @param {Number} x X position of the point or rectangle. - * @param {Number} y Y position of the point or rectangle. - * @param {Number} [width=0] The width of the rectangle. - * @param {Number} [height=0] The height of the rectangle. - * @return {Boolean} True if the described point or rectangle is contained within this rectangle. - */ - p.contains = function(x, y, width, height) { - width = width||0; - height = height||0; - return (x >= this.x && x+width <= this.x+this.width && y >= this.y && y+height <= this.y+this.height); - }; - - /** - * Returns a new rectangle which contains this rectangle and the specified rectangle. - * @method union - * @param {Rectangle} rect The rectangle to calculate a union with. - * @return {Rectangle} A new rectangle describing the union. - */ - p.union = function(rect) { - return this.clone().extend(rect.x, rect.y, rect.width, rect.height); - }; - - /** - * Returns a new rectangle which describes the intersection (overlap) of this rectangle and the specified rectangle, - * or null if they do not intersect. - * @method intersection - * @param {Rectangle} rect The rectangle to calculate an intersection with. - * @return {Rectangle} A new rectangle describing the intersection or null. - */ - p.intersection = function(rect) { - var x1 = rect.x, y1 = rect.y, x2 = x1+rect.width, y2 = y1+rect.height; - if (this.x > x1) { x1 = this.x; } - if (this.y > y1) { y1 = this.y; } - if (this.x + this.width < x2) { x2 = this.x + this.width; } - if (this.y + this.height < y2) { y2 = this.y + this.height; } - return (x2 <= x1 || y2 <= y1) ? null : new Rectangle(x1, y1, x2-x1, y2-y1); - }; - - /** - * Returns true if the specified rectangle intersects (has any overlap) with this rectangle. - * @method intersects - * @param {Rectangle} rect The rectangle to compare. - * @return {Boolean} True if the rectangles intersect. - */ - p.intersects = function(rect) { - return (rect.x <= this.x+this.width && this.x <= rect.x+rect.width && rect.y <= this.y+this.height && this.y <= rect.y + rect.height); - }; - - /** - * Returns true if the width or height are equal or less than 0. - * @method isEmpty - * @return {Boolean} True if the rectangle is empty. - */ - p.isEmpty = function() { - return this.width <= 0 || this.height <= 0; - }; - - /** - * Returns a clone of the Rectangle instance. - * @method clone - * @return {Rectangle} a clone of the Rectangle instance. - **/ - p.clone = function() { - return new Rectangle(this.x, this.y, this.width, this.height); - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Rectangle (x="+this.x+" y="+this.y+" width="+this.width+" height="+this.height+")]"; - }; - - - createjs.Rectangle = Rectangle; -}()); - -//############################################################################## -// ButtonHelper.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * The ButtonHelper is a helper class to create interactive buttons from {{#crossLink "MovieClip"}}{{/crossLink}} or - * {{#crossLink "Sprite"}}{{/crossLink}} instances. This class will intercept mouse events from an object, and - * automatically call {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} or {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}}, - * to the respective animation labels, add a pointer cursor, and allows the user to define a hit state frame. - * - * The ButtonHelper instance does not need to be added to the stage, but a reference should be maintained to prevent - * garbage collection. - * - * Note that over states will not work unless you call {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. - * - *

Example

- * - * var helper = new createjs.ButtonHelper(myInstance, "out", "over", "down", false, myInstance, "hit"); - * myInstance.addEventListener("click", handleClick); - * function handleClick(event) { - * // Click Happened. - * } - * - * @class ButtonHelper - * @param {Sprite|MovieClip} target The instance to manage. - * @param {String} [outLabel="out"] The label or animation to go to when the user rolls out of the button. - * @param {String} [overLabel="over"] The label or animation to go to when the user rolls over the button. - * @param {String} [downLabel="down"] The label or animation to go to when the user presses the button. - * @param {Boolean} [play=false] If the helper should call "gotoAndPlay" or "gotoAndStop" on the button when changing - * states. - * @param {DisplayObject} [hitArea] An optional item to use as the hit state for the button. If this is not defined, - * then the button's visible states will be used instead. Note that the same instance as the "target" argument can be - * used for the hitState. - * @param {String} [hitLabel] The label or animation on the hitArea instance that defines the hitArea bounds. If this is - * null, then the default state of the hitArea will be used. * - * @constructor - */ - function ButtonHelper(target, outLabel, overLabel, downLabel, play, hitArea, hitLabel) { - if (!target.addEventListener) { return; } - - - // public properties: - /** - * The target for this button helper. - * @property target - * @type MovieClip | Sprite - * @readonly - **/ - this.target = target; - - /** - * The label name or frame number to display when the user mouses out of the target. Defaults to "over". - * @property overLabel - * @type String | Number - **/ - this.overLabel = overLabel == null ? "over" : overLabel; - - /** - * The label name or frame number to display when the user mouses over the target. Defaults to "out". - * @property outLabel - * @type String | Number - **/ - this.outLabel = outLabel == null ? "out" : outLabel; - - /** - * The label name or frame number to display when the user presses on the target. Defaults to "down". - * @property downLabel - * @type String | Number - **/ - this.downLabel = downLabel == null ? "down" : downLabel; - - /** - * If true, then ButtonHelper will call gotoAndPlay, if false, it will use gotoAndStop. Default is false. - * @property play - * @default false - * @type Boolean - **/ - this.play = play; - - - // private properties - /** - * @property _isPressed - * @type Boolean - * @protected - **/ - this._isPressed = false; - - /** - * @property _isOver - * @type Boolean - * @protected - **/ - this._isOver = false; - - /** - * @property _enabled - * @type Boolean - * @protected - **/ - this._enabled = false; - - // setup: - target.mouseChildren = false; // prevents issues when children are removed from the display list when state changes. - this.enabled = true; - this.handleEvent({}); - if (hitArea) { - if (hitLabel) { - hitArea.actionsEnabled = false; - hitArea.gotoAndStop&&hitArea.gotoAndStop(hitLabel); - } - target.hitArea = hitArea; - } - } - var p = ButtonHelper.prototype; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// getter / setters: - /** - * Use the {{#crossLink "ButtonHelper/enabled:property"}}{{/crossLink}} property instead. - * @method setEnabled - * @param {Boolean} value - * @deprecated - **/ - p.setEnabled = function(value) { // TODO: deprecated. - if (value == this._enabled) { return; } - var o = this.target; - this._enabled = value; - if (value) { - o.cursor = "pointer"; - o.addEventListener("rollover", this); - o.addEventListener("rollout", this); - o.addEventListener("mousedown", this); - o.addEventListener("pressup", this); - if (o._reset) { o.__reset = o._reset; o._reset = this._reset;} - } else { - o.cursor = null; - o.removeEventListener("rollover", this); - o.removeEventListener("rollout", this); - o.removeEventListener("mousedown", this); - o.removeEventListener("pressup", this); - if (o.__reset) { o._reset = o.__reset; delete(o.__reset); } - } - }; - /** - * Use the {{#crossLink "ButtonHelper/enabled:property"}}{{/crossLink}} property instead. - * @method getEnabled - * @return {Boolean} - * @deprecated - **/ - p.getEnabled = function() { - return this._enabled; - }; - - /** - * Enables or disables the button functionality on the target. - * @property enabled - * @type {Boolean} - **/ - try { - Object.defineProperties(p, { - enabled: { get: p.getEnabled, set: p.setEnabled } - }); - } catch (e) {} // TODO: use Log - - -// public methods: - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[ButtonHelper]"; - }; - - -// private methods: - /** - * @method handleEvent - * @param {Object} evt The mouse event to handle. - * @protected - **/ - p.handleEvent = function(evt) { - var label, t = this.target, type = evt.type; - if (type == "mousedown") { - this._isPressed = true; - label = this.downLabel; - } else if (type == "pressup") { - this._isPressed = false; - label = this._isOver ? this.overLabel : this.outLabel; - } else if (type == "rollover") { - this._isOver = true; - label = this._isPressed ? this.downLabel : this.overLabel; - } else { // rollout and default - this._isOver = false; - label = this._isPressed ? this.overLabel : this.outLabel; - } - if (this.play) { - t.gotoAndPlay&&t.gotoAndPlay(label); - } else { - t.gotoAndStop&&t.gotoAndStop(label); - } - }; - - /** - * Injected into target. Preserves the paused state through a reset. - * @method _reset - * @protected - **/ - p._reset = function() { - // TODO: explore better ways to handle this issue. This is hacky & disrupts object signatures. - var p = this.paused; - this.__reset(); - this.paused = p; - }; - - - createjs.ButtonHelper = ButtonHelper; -}()); - -//############################################################################## -// Shadow.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * This class encapsulates the properties required to define a shadow to apply to a {{#crossLink "DisplayObject"}}{{/crossLink}} - * via its shadow property. - * - *

Example

- * - * myImage.shadow = new createjs.Shadow("#000000", 5, 5, 10); - * - * @class Shadow - * @constructor - * @param {String} color The color of the shadow. This can be any valid CSS color value. - * @param {Number} offsetX The x offset of the shadow in pixels. - * @param {Number} offsetY The y offset of the shadow in pixels. - * @param {Number} blur The size of the blurring effect. - **/ - function Shadow(color, offsetX, offsetY, blur) { - - - // public properties: - /** - * The color of the shadow. This can be any valid CSS color value. - * @property color - * @type String - * @default null - */ - this.color = color||"black"; - - /** The x offset of the shadow. - * @property offsetX - * @type Number - * @default 0 - */ - this.offsetX = offsetX||0; - - /** The y offset of the shadow. - * @property offsetY - * @type Number - * @default 0 - */ - this.offsetY = offsetY||0; - - /** The blur of the shadow. - * @property blur - * @type Number - * @default 0 - */ - this.blur = blur||0; - } - var p = Shadow.prototype; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// static public properties: - /** - * An identity shadow object (all properties are set to 0). - * @property identity - * @type Shadow - * @static - * @final - * @readonly - **/ - Shadow.identity = new Shadow("transparent", 0, 0, 0); - - -// public methods: - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Shadow]"; - }; - - /** - * Returns a clone of this Shadow instance. - * @method clone - * @return {Shadow} A clone of the current Shadow instance. - **/ - p.clone = function() { - return new Shadow(this.color, this.offsetX, this.offsetY, this.blur); - }; - - - createjs.Shadow = Shadow; -}()); - -//############################################################################## -// SpriteSheet.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Encapsulates the properties and methods associated with a sprite sheet. A sprite sheet is a series of images (usually - * animation frames) combined into a larger image (or images). For example, an animation consisting of eight 100x100 - * images could be combined into a single 400x200 sprite sheet (4 frames across by 2 high). - * - * The data passed to the SpriteSheet constructor defines: - *
    - *
  1. The source image or images to use.
  2. - *
  3. The positions of individual image frames.
  4. - *
  5. Sequences of frames that form named animations. Optional.
  6. - *
  7. The target playback framerate. Optional.
  8. - *
- *

SpriteSheet Format

- * SpriteSheets are an object with two required properties (`images` and `frames`), and two optional properties - * (`framerate` and `animations`). This makes them easy to define in javascript code, or in JSON. - * - *

images

- * An array of source images. Images can be either an HTMlimage - * instance, or a uri to an image. The former is recommended to control preloading. - * - * images: [image1, "path/to/image2.png"], - * - *

frames

- * Defines the individual frames. There are two supported formats for frame data: - * When all of the frames are the same size (in a grid), use an object with `width`, `height`, `regX`, `regY`, - * and `count` properties. - * - *
    - *
  • `width` & `height` are required and specify the dimensions of the frames
  • - *
  • `regX` & `regY` indicate the registration point or "origin" of the frames
  • - *
  • `spacing` indicate the spacing between frames
  • - *
  • `margin` specify the margin around the image(s)
  • - *
  • `count` allows you to specify the total number of frames in the spritesheet; if omitted, this will - * be calculated based on the dimensions of the source images and the frames. Frames will be assigned - * indexes based on their position in the source images (left to right, top to bottom).
  • - *
- * - * frames: {width:64, height:64, count:20, regX: 32, regY:64, spacing:0, margin:0} - * - * If the frames are of different sizes, use an array of frame definitions. Each definition is itself an array - * with 4 required and 3 optional entries, in the order: - * - *
    - *
  • The first four, `x`, `y`, `width`, and `height` are required and define the frame rectangle.
  • - *
  • The fifth, `imageIndex`, specifies the index of the source image (defaults to 0)
  • - *
  • The last two, `regX` and `regY` specify the registration point of the frame
  • - *
- * - * frames: [ - * // x, y, width, height, imageIndex*, regX*, regY* - * [64, 0, 96, 64], - * [0, 0, 64, 64, 1, 32, 32] - * // etc. - * ] - * - *

animations

- * Optional. An object defining sequences of frames to play as named animations. Each property corresponds to an - * animation of the same name. Each animation must specify the frames to play, and may - * also include a relative playback `speed` (ex. 2 would playback at double speed, 0.5 at half), and - * the name of the `next` animation to sequence to after it completes. - * - * There are three formats supported for defining the frames in an animation, which can be mixed and matched as appropriate: - *
    - *
  1. for a single frame animation, you can simply specify the frame index - * - * animations: { - * sit: 7 - * } - * - *
  2. - *
  3. - * for an animation of consecutive frames, you can use an array with two required, and two optional entries - * in the order: `start`, `end`, `next`, and `speed`. This will play the frames from start to end inclusive. - * - * animations: { - * // start, end, next*, speed* - * run: [0, 8], - * jump: [9, 12, "run", 2] - * } - * - *
  4. - *
  5. - * for non-consecutive frames, you can use an object with a `frames` property defining an array of frame - * indexes to play in order. The object can also specify `next` and `speed` properties. - * - * animations: { - * walk: { - * frames: [1,2,3,3,2,1] - * }, - * shoot: { - * frames: [1,4,5,6], - * next: "walk", - * speed: 0.5 - * } - * } - * - *
  6. - *
- * Note: the `speed` property was added in EaselJS 0.7.0. Earlier versions had a `frequency` - * property instead, which was the inverse of `speed`. For example, a value of "4" would be 1/4 normal speed in - * earlier versions, but is 4x normal speed in EaselJS 0.7.0+. - * - *

framerate

- * Optional. Indicates the default framerate to play this spritesheet at in frames per second. See - * {{#crossLink "SpriteSheet/framerate:property"}}{{/crossLink}} for more information. - * - * framerate: 20 - * - * Note that the Sprite framerate will only work if the stage update method is provided with the {{#crossLink "Ticker/tick:event"}}{{/crossLink}} - * event generated by the {{#crossLink "Ticker"}}{{/crossLink}}. - * - * createjs.Ticker.on("tick", handleTick); - * function handleTick(event) { - * stage.update(event); - * } - * - *

Example

- * To define a simple sprite sheet, with a single image "sprites.jpg" arranged in a regular 50x50 grid with three - * animations: "stand" showing the first frame, "run" looping frame 1-5 inclusive, and "jump" playing frame 6-8 and - * sequencing back to run. - * - * var data = { - * images: ["sprites.jpg"], - * frames: {width:50, height:50}, - * animations: { - * stand:0, - * run:[1,5], - * jump:[6,8,"run"] - * } - * }; - * var spriteSheet = new createjs.SpriteSheet(data); - * var animation = new createjs.Sprite(spriteSheet, "run"); - * - *

Generating SpriteSheet Images

- * Spritesheets can be created manually by combining images in PhotoShop, and specifying the frame size or - * coordinates manually, however there are a number of tools that facilitate this. - *
    - *
  • Exporting SpriteSheets or HTML5 content from Flash Pro supports the EaselJS SpriteSheet format.
  • - *
  • The popular Texture Packer has - * EaselJS support. - *
  • SWF animations in Flash can be exported to SpriteSheets using
  • - *
- * - *

Cross Origin Issues

- * Warning: Images loaded cross-origin will throw cross-origin security errors when interacted with - * using: - *
    - *
  • a mouse
  • - *
  • methods such as {{#crossLink "Container/getObjectUnderPoint"}}{{/crossLink}}
  • - *
  • Filters (see {{#crossLink "Filter"}}{{/crossLink}})
  • - *
  • caching (see {{#crossLink "DisplayObject/cache"}}{{/crossLink}})
  • - *
- * You can get around this by setting `crossOrigin` property on your images before passing them to EaselJS, or - * setting the `crossOrigin` property on PreloadJS' LoadQueue or LoadItems. - * - * var image = new Image(); - * img.crossOrigin="Anonymous"; - * img.src = "http://server-with-CORS-support.com/path/to/image.jpg"; - * - * If you pass string paths to SpriteSheets, they will not work cross-origin. The server that stores the image must - * support cross-origin requests, or this will not work. For more information, check out - * CORS overview on MDN. - * - * @class SpriteSheet - * @constructor - * @param {Object} data An object describing the SpriteSheet data. - * @extends EventDispatcher - **/ - function SpriteSheet(data) { - this.EventDispatcher_constructor(); - - - // public properties: - /** - * Indicates whether all images are finished loading. - * @property complete - * @type Boolean - * @readonly - **/ - this.complete = true; - - /** - * Specifies the framerate to use by default for Sprite instances using the SpriteSheet. See the Sprite class - * {{#crossLink "Sprite/framerate:property"}}{{/crossLink}} for more information. - * @property framerate - * @type Number - **/ - this.framerate = 0; - - - // private properties: - /** - * @property _animations - * @protected - * @type Array - **/ - this._animations = null; - - /** - * @property _frames - * @protected - * @type Array - **/ - this._frames = null; - - /** - * @property _images - * @protected - * @type Array - **/ - this._images = null; - - /** - * @property _data - * @protected - * @type Object - **/ - this._data = null; - - /** - * @property _loadCount - * @protected - * @type Number - **/ - this._loadCount = 0; - - // only used for simple frame defs: - /** - * @property _frameHeight - * @protected - * @type Number - **/ - this._frameHeight = 0; - - /** - * @property _frameWidth - * @protected - * @type Number - **/ - this._frameWidth = 0; - - /** - * @property _numFrames - * @protected - * @type Number - **/ - this._numFrames = 0; - - /** - * @property _regX - * @protected - * @type Number - **/ - this._regX = 0; - - /** - * @property _regY - * @protected - * @type Number - **/ - this._regY = 0; - - /** - * @property _spacing - * @protected - * @type Number - **/ - this._spacing = 0; - - /** - * @property _margin - * @protected - * @type Number - **/ - this._margin = 0; - - // setup: - this._parseData(data); - } - var p = createjs.extend(SpriteSheet, createjs.EventDispatcher); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// events: - /** - * Dispatched when all images are loaded. Note that this only fires if the images - * were not fully loaded when the sprite sheet was initialized. You should check the complete property - * to prior to adding a listener. Ex. - * - * var sheet = new createjs.SpriteSheet(data); - * if (!sheet.complete) { - * // not preloaded, listen for the complete event: - * sheet.addEventListener("complete", handler); - * } - * - * @event complete - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.6.0 - */ - - /** - * Dispatched when getFrame is called with a valid frame index. This is primarily intended for use by {{#crossLink "SpriteSheetBuilder"}}{{/crossLink}} - * when doing on-demand rendering. - * @event getframe - * @param {Number} index The frame index. - * @param {Object} frame The frame object that getFrame will return. - */ - - /** - * Dispatched when an image encounters an error. A SpriteSheet will dispatch an error event for each image that - * encounters an error, and will still dispatch a {{#crossLink "SpriteSheet/complete:event"}}{{/crossLink}} - * event once all images are finished processing, even if an error is encountered. - * @event error - * @param {String} src The source of the image that failed to load. - * @since 0.8.2 - */ - - -// getter / setters: - /** - * Use the {{#crossLink "SpriteSheet/animations:property"}}{{/crossLink}} property instead. - * @method getAnimations - * @return {Array} - * @deprecated - **/ - p.getAnimations = function() { - return this._animations.slice(); - }; - - /** - * Returns an array of all available animation names available on this sprite sheet as strings. - * @property animations - * @type {Array} - * @readonly - **/ - try { - Object.defineProperties(p, { - animations: { get: p.getAnimations } - }); - } catch (e) {} - - -// public methods: - /** - * Returns the total number of frames in the specified animation, or in the whole sprite - * sheet if the animation param is omitted. Returns 0 if the spritesheet relies on calculated frame counts, and - * the images have not been fully loaded. - * @method getNumFrames - * @param {String} animation The name of the animation to get a frame count for. - * @return {Number} The number of frames in the animation, or in the entire sprite sheet if the animation param is omitted. - */ - p.getNumFrames = function(animation) { - if (animation == null) { - return this._frames ? this._frames.length : this._numFrames || 0; - } else { - var data = this._data[animation]; - if (data == null) { return 0; } - else { return data.frames.length; } - } - }; - - /** - * Returns an object defining the specified animation. The returned object contains:
    - *
  • frames: an array of the frame ids in the animation
  • - *
  • speed: the playback speed for this animation
  • - *
  • name: the name of the animation
  • - *
  • next: the default animation to play next. If the animation loops, the name and next property will be the - * same.
  • - *
- * @method getAnimation - * @param {String} name The name of the animation to get. - * @return {Object} a generic object with frames, speed, name, and next properties. - **/ - p.getAnimation = function(name) { - return this._data[name]; - }; - - /** - * Returns an object specifying the image and source rect of the specified frame. The returned object has:
    - *
  • an image property holding a reference to the image object in which the frame is found
  • - *
  • a rect property containing a Rectangle instance which defines the boundaries for the frame within that - * image.
  • - *
  • A regX and regY property corresponding to the regX/Y values for the frame. - *
- * @method getFrame - * @param {Number} frameIndex The index of the frame. - * @return {Object} a generic object with image and rect properties. Returns null if the frame does not exist. - **/ - p.getFrame = function(frameIndex) { - var frame; - if (this._frames && (frame=this._frames[frameIndex])) { return frame; } - return null; - }; - - /** - * Returns a {{#crossLink "Rectangle"}}{{/crossLink}} instance defining the bounds of the specified frame relative - * to the origin. For example, a 90 x 70 frame with a regX of 50 and a regY of 40 would return: - * - * [x=-50, y=-40, width=90, height=70] - * - * @method getFrameBounds - * @param {Number} frameIndex The index of the frame. - * @param {Rectangle} [rectangle] A Rectangle instance to copy the values into. By default a new instance is created. - * @return {Rectangle} A Rectangle instance. Returns null if the frame does not exist, or the image is not fully loaded. - **/ - p.getFrameBounds = function(frameIndex, rectangle) { - var frame = this.getFrame(frameIndex); - return frame ? (rectangle||new createjs.Rectangle()).setValues(-frame.regX, -frame.regY, frame.rect.width, frame.rect.height) : null; - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[SpriteSheet]"; - }; - - /** - * SpriteSheet cannot be cloned. A SpriteSheet can be shared by multiple Sprite instances without cloning it. - * @method clone - **/ - p.clone = function() { - throw("SpriteSheet cannot be cloned.") - }; - -// private methods: - /** - * @method _parseData - * @param {Object} data An object describing the SpriteSheet data. - * @protected - **/ - p._parseData = function(data) { - var i,l,o,a; - if (data == null) { return; } - - this.framerate = data.framerate||0; - - // parse images: - if (data.images && (l=data.images.length) > 0) { - a = this._images = []; - for (i=0; i= maxFrames) { break imgLoop; } - frameCount++; - this._frames.push({ - image: img, - rect: new createjs.Rectangle(x, y, frameWidth, frameHeight), - regX: this._regX, - regY: this._regY - }); - x += frameWidth+spacing; - } - y += frameHeight+spacing; - } - } - this._numFrames = frameCount; - }; - - - createjs.SpriteSheet = createjs.promote(SpriteSheet, "EventDispatcher"); -}()); - -//############################################################################## -// Graphics.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * The Graphics class exposes an easy to use API for generating vector drawing instructions and drawing them to a - * specified context. Note that you can use Graphics without any dependency on the EaselJS framework by calling {{#crossLink "Graphics/draw"}}{{/crossLink}} - * directly, or it can be used with the {{#crossLink "Shape"}}{{/crossLink}} object to draw vector graphics within the - * context of an EaselJS display list. - * - * There are two approaches to working with Graphics object: calling methods on a Graphics instance (the "Graphics API"), or - * instantiating Graphics command objects and adding them to the graphics queue via {{#crossLink "Graphics/append"}}{{/crossLink}}. - * The former abstracts the latter, simplifying beginning and ending paths, fills, and strokes. - * - * var g = new createjs.Graphics(); - * g.setStrokeStyle(1); - * g.beginStroke("#000000"); - * g.beginFill("red"); - * g.drawCircle(0,0,30); - * - * All drawing methods in Graphics return the Graphics instance, so they can be chained together. For example, - * the following line of code would generate the instructions to draw a rectangle with a red stroke and blue fill: - * - * myGraphics.beginStroke("red").beginFill("blue").drawRect(20, 20, 100, 50); - * - * Each graphics API call generates a command object (see below). The last command to be created can be accessed via - * {{#crossLink "Graphics/command:property"}}{{/crossLink}}: - * - * var fillCommand = myGraphics.beginFill("red").command; - * // ... later, update the fill style/color: - * fillCommand.style = "blue"; - * // or change it to a bitmap fill: - * fillCommand.bitmap(myImage); - * - * For more direct control of rendering, you can instantiate and append command objects to the graphics queue directly. In this case, you - * need to manage path creation manually, and ensure that fill/stroke is applied to a defined path: - * - * // start a new path. Graphics.beginCmd is a reusable BeginPath instance: - * myGraphics.append(createjs.Graphics.beginCmd); - * // we need to define the path before applying the fill: - * var circle = new createjs.Graphics.Circle(0,0,30); - * myGraphics.append(circle); - * // fill the path we just defined: - * var fill = new createjs.Graphics.Fill("red"); - * myGraphics.append(fill); - * - * These approaches can be used together, for example to insert a custom command: - * - * myGraphics.beginFill("red"); - * var customCommand = new CustomSpiralCommand(etc); - * myGraphics.append(customCommand); - * myGraphics.beginFill("blue"); - * myGraphics.drawCircle(0, 0, 30); - * - * See {{#crossLink "Graphics/append"}}{{/crossLink}} for more info on creating custom commands. - * - *

Tiny API

- * The Graphics class also includes a "tiny API", which is one or two-letter methods that are shortcuts for all of the - * Graphics methods. These methods are great for creating compact instructions, and is used by the Toolkit for CreateJS - * to generate readable code. All tiny methods are marked as protected, so you can view them by enabling protected - * descriptions in the docs. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
TinyMethodTinyMethod
mt{{#crossLink "Graphics/moveTo"}}{{/crossLink}} lt {{#crossLink "Graphics/lineTo"}}{{/crossLink}}
a/at{{#crossLink "Graphics/arc"}}{{/crossLink}} / {{#crossLink "Graphics/arcTo"}}{{/crossLink}} bt{{#crossLink "Graphics/bezierCurveTo"}}{{/crossLink}}
qt{{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} (also curveTo)r{{#crossLink "Graphics/rect"}}{{/crossLink}}
cp{{#crossLink "Graphics/closePath"}}{{/crossLink}} c{{#crossLink "Graphics/clear"}}{{/crossLink}}
f{{#crossLink "Graphics/beginFill"}}{{/crossLink}} lf{{#crossLink "Graphics/beginLinearGradientFill"}}{{/crossLink}}
rf{{#crossLink "Graphics/beginRadialGradientFill"}}{{/crossLink}} bf{{#crossLink "Graphics/beginBitmapFill"}}{{/crossLink}}
ef{{#crossLink "Graphics/endFill"}}{{/crossLink}} ss / sd{{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} / {{#crossLink "Graphics/setStrokeDash"}}{{/crossLink}}
s{{#crossLink "Graphics/beginStroke"}}{{/crossLink}} ls{{#crossLink "Graphics/beginLinearGradientStroke"}}{{/crossLink}}
rs{{#crossLink "Graphics/beginRadialGradientStroke"}}{{/crossLink}} bs{{#crossLink "Graphics/beginBitmapStroke"}}{{/crossLink}}
es{{#crossLink "Graphics/endStroke"}}{{/crossLink}} dr{{#crossLink "Graphics/drawRect"}}{{/crossLink}}
rr{{#crossLink "Graphics/drawRoundRect"}}{{/crossLink}} rc{{#crossLink "Graphics/drawRoundRectComplex"}}{{/crossLink}}
dc{{#crossLink "Graphics/drawCircle"}}{{/crossLink}} de{{#crossLink "Graphics/drawEllipse"}}{{/crossLink}}
dp{{#crossLink "Graphics/drawPolyStar"}}{{/crossLink}} p{{#crossLink "Graphics/decodePath"}}{{/crossLink}}
- * - * Here is the above example, using the tiny API instead. - * - * myGraphics.s("red").f("blue").r(20, 20, 100, 50); - * - * @class Graphics - * @constructor - **/ - function Graphics() { - - - // public properties - /** - * Holds a reference to the last command that was created or appended. For example, you could retain a reference - * to a Fill command in order to dynamically update the color later by using: - * - * var myFill = myGraphics.beginFill("red").command; - * // update color later: - * myFill.style = "yellow"; - * - * @property command - * @type Object - **/ - this.command = null; - - - // private properties - /** - * @property _stroke - * @protected - * @type {Stroke} - **/ - this._stroke = null; - - /** - * @property _strokeStyle - * @protected - * @type {StrokeStyle} - **/ - this._strokeStyle = null; - - /** - * @property _oldStrokeStyle - * @protected - * @type {StrokeStyle} - **/ - this._oldStrokeStyle = null; - - /** - * @property _strokeDash - * @protected - * @type {StrokeDash} - **/ - this._strokeDash = null; - - /** - * @property _oldStrokeDash - * @protected - * @type {StrokeDash} - **/ - this._oldStrokeDash = null; - - /** - * @property _strokeIgnoreScale - * @protected - * @type Boolean - **/ - this._strokeIgnoreScale = false; - - /** - * @property _fill - * @protected - * @type {Fill} - **/ - this._fill = null; - - /** - * @property _instructions - * @protected - * @type {Array} - **/ - this._instructions = []; - - /** - * Indicates the last instruction index that was committed. - * @property _commitIndex - * @protected - * @type {Number} - **/ - this._commitIndex = 0; - - /** - * Uncommitted instructions. - * @property _activeInstructions - * @protected - * @type {Array} - **/ - this._activeInstructions = []; - - /** - * This indicates that there have been changes to the activeInstruction list since the last updateInstructions call. - * @property _dirty - * @protected - * @type {Boolean} - * @default false - **/ - this._dirty = false; - - /** - * Index to draw from if a store operation has happened. - * @property _storeIndex - * @protected - * @type {Number} - * @default 0 - **/ - this._storeIndex = 0; - - // setup: - this.clear(); - } - var p = Graphics.prototype; - var G = Graphics; // shortcut - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// static public methods: - /** - * Returns a CSS compatible color string based on the specified RGB numeric color values in the format - * "rgba(255,255,255,1.0)", or if alpha is null then in the format "rgb(255,255,255)". For example, - * - * createjs.Graphics.getRGB(50, 100, 150, 0.5); - * // Returns "rgba(50,100,150,0.5)" - * - * It also supports passing a single hex color value as the first param, and an optional alpha value as the second - * param. For example, - * - * createjs.Graphics.getRGB(0xFF00FF, 0.2); - * // Returns "rgba(255,0,255,0.2)" - * - * @method getRGB - * @static - * @param {Number} r The red component for the color, between 0 and 0xFF (255). - * @param {Number} g The green component for the color, between 0 and 0xFF (255). - * @param {Number} b The blue component for the color, between 0 and 0xFF (255). - * @param {Number} [alpha] The alpha component for the color where 0 is fully transparent and 1 is fully opaque. - * @return {String} A CSS compatible color string based on the specified RGB numeric color values in the format - * "rgba(255,255,255,1.0)", or if alpha is null then in the format "rgb(255,255,255)". - **/ - Graphics.getRGB = function(r, g, b, alpha) { - if (r != null && b == null) { - alpha = g; - b = r&0xFF; - g = r>>8&0xFF; - r = r>>16&0xFF; - } - if (alpha == null) { - return "rgb("+r+","+g+","+b+")"; - } else { - return "rgba("+r+","+g+","+b+","+alpha+")"; - } - }; - - /** - * Returns a CSS compatible color string based on the specified HSL numeric color values in the format "hsla(360,100,100,1.0)", - * or if alpha is null then in the format "hsl(360,100,100)". - * - * createjs.Graphics.getHSL(150, 100, 70); - * // Returns "hsl(150,100,70)" - * - * @method getHSL - * @static - * @param {Number} hue The hue component for the color, between 0 and 360. - * @param {Number} saturation The saturation component for the color, between 0 and 100. - * @param {Number} lightness The lightness component for the color, between 0 and 100. - * @param {Number} [alpha] The alpha component for the color where 0 is fully transparent and 1 is fully opaque. - * @return {String} A CSS compatible color string based on the specified HSL numeric color values in the format - * "hsla(360,100,100,1.0)", or if alpha is null then in the format "hsl(360,100,100)". - **/ - Graphics.getHSL = function(hue, saturation, lightness, alpha) { - if (alpha == null) { - return "hsl("+(hue%360)+","+saturation+"%,"+lightness+"%)"; - } else { - return "hsla("+(hue%360)+","+saturation+"%,"+lightness+"%,"+alpha+")"; - } - }; - - -// static properties: - /** - * A reusable instance of {{#crossLink "Graphics/BeginPath"}}{{/crossLink}} to avoid - * unnecessary instantiation. - * @property beginCmd - * @type {Graphics.BeginPath} - * @static - **/ - // defined at the bottom of this file. - - /** - * Map of Base64 characters to values. Used by {{#crossLink "Graphics/decodePath"}}{{/crossLink}}. - * @property BASE_64 - * @static - * @final - * @readonly - * @type {Object} - **/ - Graphics.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}; - - /** - * Maps numeric values for the caps parameter of {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} to - * corresponding string values. This is primarily for use with the tiny API. The mappings are as follows: 0 to - * "butt", 1 to "round", and 2 to "square". - * For example, to set the line caps to "square": - * - * myGraphics.ss(16, 2); - * - * @property STROKE_CAPS_MAP - * @static - * @final - * @readonly - * @type {Array} - **/ - Graphics.STROKE_CAPS_MAP = ["butt", "round", "square"]; - - /** - * Maps numeric values for the joints parameter of {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} to - * corresponding string values. This is primarily for use with the tiny API. The mappings are as follows: 0 to - * "miter", 1 to "round", and 2 to "bevel". - * For example, to set the line joints to "bevel": - * - * myGraphics.ss(16, 0, 2); - * - * @property STROKE_JOINTS_MAP - * @static - * @final - * @readonly - * @type {Array} - **/ - Graphics.STROKE_JOINTS_MAP = ["miter", "round", "bevel"]; - - /** - * @property _ctx - * @static - * @protected - * @type {CanvasRenderingContext2D} - **/ - var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")); - if (canvas.getContext) { - Graphics._ctx = canvas.getContext("2d"); - canvas.width = canvas.height = 1; - } - - -// getter / setters: - /** - * Use the {{#crossLink "Graphics/instructions:property"}}{{/crossLink}} property instead. - * @method getInstructions - * @return {Array} - * @deprecated - **/ - p.getInstructions = function() { - this._updateInstructions(); - return this._instructions; - }; - - /** - * Returns the graphics instructions array. Each entry is a graphics command object (ex. Graphics.Fill, Graphics.Rect) - * Modifying the returned array directly is not recommended, and is likely to result in unexpected behaviour. - * - * This property is mainly intended for introspection of the instructions (ex. for graphics export). - * @property instructions - * @type {Array} - * @readonly - **/ - try { - Object.defineProperties(p, { - instructions: { get: p.getInstructions } - }); - } catch (e) {} - - -// public methods: - /** - * Returns true if this Graphics instance has no drawing commands. - * @method isEmpty - * @return {Boolean} Returns true if this Graphics instance has no drawing commands. - **/ - p.isEmpty = function() { - return !(this._instructions.length || this._activeInstructions.length); - }; - - /** - * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. - * Returns true if the draw was handled (useful for overriding functionality). - * - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method draw - * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. - * @param {Object} data Optional data that is passed to graphics command exec methods. When called from a Shape instance, the shape passes itself as the data parameter. This can be used by custom graphic commands to insert contextual data. - **/ - p.draw = function(ctx, data) { - this._updateInstructions(); - var instr = this._instructions; - for (var i=this._storeIndex, l=instr.length; iDisplayObject.mask to draw the clipping path, for example. - * - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method drawAsPath - * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. - **/ - p.drawAsPath = function(ctx) { - this._updateInstructions(); - var instr, instrs = this._instructions; - for (var i=this._storeIndex, l=instrs.length; i - * whatwg spec. - * @method lineTo - * @param {Number} x The x coordinate the drawing point should draw to. - * @param {Number} y The y coordinate the drawing point should draw to. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.lineTo = function(x, y) { - return this.append(new G.LineTo(x,y)); - }; - - /** - * Draws an arc with the specified control points and radius. For detailed information, read the - * - * whatwg spec. A tiny API method "at" also exists. - * @method arcTo - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} radius - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.arcTo = function(x1, y1, x2, y2, radius) { - return this.append(new G.ArcTo(x1, y1, x2, y2, radius)); - }; - - /** - * Draws an arc defined by the radius, startAngle and endAngle arguments, centered at the position (x, y). For - * example, to draw a full circle with a radius of 20 centered at (100, 100): - * - * arc(100, 100, 20, 0, Math.PI*2); - * - * For detailed information, read the - * whatwg spec. - * A tiny API method "a" also exists. - * @method arc - * @param {Number} x - * @param {Number} y - * @param {Number} radius - * @param {Number} startAngle Measured in radians. - * @param {Number} endAngle Measured in radians. - * @param {Boolean} anticlockwise - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.arc = function(x, y, radius, startAngle, endAngle, anticlockwise) { - return this.append(new G.Arc(x, y, radius, startAngle, endAngle, anticlockwise)); - }; - - /** - * Draws a quadratic curve from the current drawing point to (x, y) using the control point (cpx, cpy). For detailed - * information, read the - * whatwg spec. A tiny API method "qt" also exists. - * @method quadraticCurveTo - * @param {Number} cpx - * @param {Number} cpy - * @param {Number} x - * @param {Number} y - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.quadraticCurveTo = function(cpx, cpy, x, y) { - return this.append(new G.QuadraticCurveTo(cpx, cpy, x, y)); - }; - - /** - * Draws a bezier curve from the current drawing point to (x, y) using the control points (cp1x, cp1y) and (cp2x, - * cp2y). For detailed information, read the - * - * whatwg spec. A tiny API method "bt" also exists. - * @method bezierCurveTo - * @param {Number} cp1x - * @param {Number} cp1y - * @param {Number} cp2x - * @param {Number} cp2y - * @param {Number} x - * @param {Number} y - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) { - return this.append(new G.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)); - }; - - /** - * Draws a rectangle at (x, y) with the specified width and height using the current fill and/or stroke. - * For detailed information, read the - * - * whatwg spec. A tiny API method "r" also exists. - * @method rect - * @param {Number} x - * @param {Number} y - * @param {Number} w Width of the rectangle - * @param {Number} h Height of the rectangle - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.rect = function(x, y, w, h) { - return this.append(new G.Rect(x, y, w, h)); - }; - - /** - * Closes the current path, effectively drawing a line from the current drawing point to the first drawing point specified - * since the fill or stroke was last set. A tiny API method "cp" also exists. - * @method closePath - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.closePath = function() { - return this._activeInstructions.length ? this.append(new G.ClosePath()) : this; - }; - - -// public methods that roughly map to Flash graphics APIs: - /** - * Clears all drawing instructions, effectively resetting this Graphics instance. Any line and fill styles will need - * to be redefined to draw shapes following a clear call. A tiny API method "c" also exists. - * @method clear - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.clear = function() { - 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 = false; - return this; - }; - - /** - * Begins a fill with the specified color. This ends the current sub-path. A tiny API method "f" also exists. - * @method beginFill - * @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to - * null will result in no fill. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.beginFill = function(color) { - return this._setFill(color ? new G.Fill(color) : null); - }; - - /** - * Begins a linear gradient fill defined by the line (x0, y0) to (x1, y1). This ends the current sub-path. For - * example, the following code defines a black to white vertical gradient ranging from 20px to 120px, and draws a - * square to display it: - * - * myGraphics.beginLinearGradientFill(["#000","#FFF"], [0, 1], 0, 20, 0, 120).drawRect(20, 20, 120, 120); - * - * A tiny API method "lf" also exists. - * @method beginLinearGradientFill - * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define a gradient - * drawing from red to blue. - * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 0.9] would draw - * the first color to 10% then interpolating to the second color at 90%. - * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. - * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. - * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. - * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.beginLinearGradientFill = function(colors, ratios, x0, y0, x1, y1) { - return this._setFill(new G.Fill().linearGradient(colors, ratios, x0, y0, x1, y1)); - }; - - /** - * Begins a radial gradient fill. This ends the current sub-path. For example, the following code defines a red to - * blue radial gradient centered at (100, 100), with a radius of 50, and draws a circle to display it: - * - * myGraphics.beginRadialGradientFill(["#F00","#00F"], [0, 1], 100, 100, 0, 100, 100, 50).drawCircle(100, 100, 50); - * - * A tiny API method "rf" also exists. - * @method beginRadialGradientFill - * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define - * a gradient drawing from red to blue. - * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, - * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. - * @param {Number} x0 Center position of the inner circle that defines the gradient. - * @param {Number} y0 Center position of the inner circle that defines the gradient. - * @param {Number} r0 Radius of the inner circle that defines the gradient. - * @param {Number} x1 Center position of the outer circle that defines the gradient. - * @param {Number} y1 Center position of the outer circle that defines the gradient. - * @param {Number} r1 Radius of the outer circle that defines the gradient. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.beginRadialGradientFill = function(colors, ratios, x0, y0, r0, x1, y1, r1) { - return this._setFill(new G.Fill().radialGradient(colors, ratios, x0, y0, r0, x1, y1, r1)); - }; - - /** - * Begins a pattern fill using the specified image. This ends the current sub-path. A tiny API method "bf" also - * exists. - * @method beginBitmapFill - * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use - * as the pattern. Must be loaded prior to creating a bitmap fill, or the fill will be empty. - * @param {String} repetition Optional. Indicates whether to repeat the image in the fill area. One of "repeat", - * "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". Note that Firefox does not support "repeat-x" or - * "repeat-y" (latest tests were in FF 20.0), and will default to "repeat". - * @param {Matrix2D} matrix Optional. Specifies a transformation matrix for the bitmap fill. This transformation - * will be applied relative to the parent transform. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.beginBitmapFill = function(image, repetition, matrix) { - return this._setFill(new G.Fill(null,matrix).bitmap(image, repetition)); - }; - - /** - * Ends the current sub-path, and begins a new one with no fill. Functionally identical to beginFill(null). - * A tiny API method "ef" also exists. - * @method endFill - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.endFill = function() { - return this.beginFill(); - }; - - /** - * Sets the stroke style. Like all drawing methods, this can be chained, so you can define - * the stroke style and color in a single line of code like so: - * - * myGraphics.setStrokeStyle(8,"round").beginStroke("#F00"); - * - * A tiny API method "ss" also exists. - * @method setStrokeStyle - * @param {Number} thickness The width of the stroke. - * @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt, - * round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2 (square) for use with - * the tiny API. - * @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet. - * One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel) - * for use with the tiny API. - * @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which - * controls at what point a mitered joint will be clipped. - * @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless - * of active transformations. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.setStrokeStyle = function(thickness, caps, joints, miterLimit, ignoreScale) { - this._updateInstructions(true); - this._strokeStyle = this.command = new G.StrokeStyle(thickness, caps, joints, miterLimit, ignoreScale); - - // ignoreScale lives on Stroke, not StrokeStyle, so we do a little trickery: - if (this._stroke) { this._stroke.ignoreScale = ignoreScale; } - this._strokeIgnoreScale = ignoreScale; - return this; - }; - - /** - * Sets or clears the stroke dash pattern. - * - * myGraphics.setStrokeDash([20, 10], 0); - * - * A tiny API method `sd` also exists. - * @method setStrokeDash - * @param {Array} [segments] An array specifying the dash pattern, alternating between line and gap. - * For example, `[20,10]` would create a pattern of 20 pixel lines with 10 pixel gaps between them. - * Passing null or an empty array will clear the existing stroke dash. - * @param {Number} [offset=0] The offset of the dash pattern. For example, you could increment this value to create a "marching ants" effect. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.setStrokeDash = function(segments, offset) { - this._updateInstructions(true); - this._strokeDash = this.command = new G.StrokeDash(segments, offset); - return this; - }; - - /** - * Begins a stroke with the specified color. This ends the current sub-path. A tiny API method "s" also exists. - * @method beginStroke - * @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to - * null will result in no stroke. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.beginStroke = function(color) { - return this._setStroke(color ? new G.Stroke(color) : null); - }; - - /** - * Begins a linear gradient stroke defined by the line (x0, y0) to (x1, y1). This ends the current sub-path. For - * example, the following code defines a black to white vertical gradient ranging from 20px to 120px, and draws a - * square to display it: - * - * myGraphics.setStrokeStyle(10). - * beginLinearGradientStroke(["#000","#FFF"], [0, 1], 0, 20, 0, 120).drawRect(20, 20, 120, 120); - * - * A tiny API method "ls" also exists. - * @method beginLinearGradientStroke - * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define - * a gradient drawing from red to blue. - * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, - * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. - * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. - * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. - * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. - * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.beginLinearGradientStroke = function(colors, ratios, x0, y0, x1, y1) { - return this._setStroke(new G.Stroke().linearGradient(colors, ratios, x0, y0, x1, y1)); - }; - - /** - * Begins a radial gradient stroke. This ends the current sub-path. For example, the following code defines a red to - * blue radial gradient centered at (100, 100), with a radius of 50, and draws a rectangle to display it: - * - * myGraphics.setStrokeStyle(10) - * .beginRadialGradientStroke(["#F00","#00F"], [0, 1], 100, 100, 0, 100, 100, 50) - * .drawRect(50, 90, 150, 110); - * - * A tiny API method "rs" also exists. - * @method beginRadialGradientStroke - * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define - * a gradient drawing from red to blue. - * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, - * 0.9] would draw the first color to 10% then interpolating to the second color at 90%, then draw the second color - * to 100%. - * @param {Number} x0 Center position of the inner circle that defines the gradient. - * @param {Number} y0 Center position of the inner circle that defines the gradient. - * @param {Number} r0 Radius of the inner circle that defines the gradient. - * @param {Number} x1 Center position of the outer circle that defines the gradient. - * @param {Number} y1 Center position of the outer circle that defines the gradient. - * @param {Number} r1 Radius of the outer circle that defines the gradient. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.beginRadialGradientStroke = function(colors, ratios, x0, y0, r0, x1, y1, r1) { - return this._setStroke(new G.Stroke().radialGradient(colors, ratios, x0, y0, r0, x1, y1, r1)); - }; - - /** - * Begins a pattern fill using the specified image. This ends the current sub-path. Note that unlike bitmap fills, - * strokes do not currently support a matrix parameter due to limitations in the canvas API. A tiny API method "bs" - * also exists. - * @method beginBitmapStroke - * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use - * as the pattern. Must be loaded prior to creating a bitmap fill, or the fill will be empty. - * @param {String} [repetition=repeat] Optional. Indicates whether to repeat the image in the fill area. One of - * "repeat", "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.beginBitmapStroke = function(image, repetition) { - // NOTE: matrix is not supported for stroke because transforms on strokes also affect the drawn stroke width. - return this._setStroke(new G.Stroke().bitmap(image, repetition)); - }; - - /** - * Ends the current sub-path, and begins a new one with no stroke. Functionally identical to beginStroke(null). - * A tiny API method "es" also exists. - * @method endStroke - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.endStroke = function() { - return this.beginStroke(); - }; - - /** - * Maps the familiar ActionScript curveTo() method to the functionally similar {{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} - * method. - * @method quadraticCurveTo - * @param {Number} cpx - * @param {Number} cpy - * @param {Number} x - * @param {Number} y - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.curveTo = p.quadraticCurveTo; - - /** - * - * Maps the familiar ActionScript drawRect() method to the functionally similar {{#crossLink "Graphics/rect"}}{{/crossLink}} - * method. - * @method drawRect - * @param {Number} x - * @param {Number} y - * @param {Number} w Width of the rectangle - * @param {Number} h Height of the rectangle - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.drawRect = p.rect; - - /** - * Draws a rounded rectangle with all corners with the specified radius. - * @method drawRoundRect - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - * @param {Number} radius Corner radius. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.drawRoundRect = function(x, y, w, h, radius) { - return this.drawRoundRectComplex(x, y, w, h, radius, radius, radius, radius); - }; - - /** - * Draws a rounded rectangle with different corner radii. Supports positive and negative corner radii. A tiny API - * method "rc" also exists. - * @method drawRoundRectComplex - * @param {Number} x The horizontal coordinate to draw the round rect. - * @param {Number} y The vertical coordinate to draw the round rect. - * @param {Number} w The width of the round rect. - * @param {Number} h The height of the round rect. - * @param {Number} radiusTL Top left corner radius. - * @param {Number} radiusTR Top right corner radius. - * @param {Number} radiusBR Bottom right corner radius. - * @param {Number} radiusBL Bottom left corner radius. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.drawRoundRectComplex = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL) { - return this.append(new G.RoundRect(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL)); - }; - - /** - * Draws a circle with the specified radius at (x, y). - * - * var g = new createjs.Graphics(); - * g.setStrokeStyle(1); - * g.beginStroke(createjs.Graphics.getRGB(0,0,0)); - * g.beginFill(createjs.Graphics.getRGB(255,0,0)); - * g.drawCircle(0,0,3); - * - * var s = new createjs.Shape(g); - * s.x = 100; - * s.y = 100; - * - * stage.addChild(s); - * stage.update(); - * - * A tiny API method "dc" also exists. - * @method drawCircle - * @param {Number} x x coordinate center point of circle. - * @param {Number} y y coordinate center point of circle. - * @param {Number} radius Radius of circle. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.drawCircle = function(x, y, radius) { - return this.append(new G.Circle(x, y, radius)); - }; - - /** - * Draws an ellipse (oval) with a specified width (w) and height (h). Similar to {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}, - * except the width and height can be different. A tiny API method "de" also exists. - * @method drawEllipse - * @param {Number} x The left coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} - * which draws from center. - * @param {Number} y The top coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} - * which draws from the center. - * @param {Number} w The height (horizontal diameter) of the ellipse. The horizontal radius will be half of this - * number. - * @param {Number} h The width (vertical diameter) of the ellipse. The vertical radius will be half of this number. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.drawEllipse = function(x, y, w, h) { - return this.append(new G.Ellipse(x, y, w, h)); - }; - - /** - * Draws a star if pointSize is greater than 0, or a regular polygon if pointSize is 0 with the specified number of - * points. For example, the following code will draw a familiar 5 pointed star shape centered at 100, 100 and with a - * radius of 50: - * - * myGraphics.beginFill("#FF0").drawPolyStar(100, 100, 50, 5, 0.6, -90); - * // Note: -90 makes the first point vertical - * - * A tiny API method "dp" also exists. - * - * @method drawPolyStar - * @param {Number} x Position of the center of the shape. - * @param {Number} y Position of the center of the shape. - * @param {Number} radius The outer radius of the shape. - * @param {Number} sides The number of points on the star or sides on the polygon. - * @param {Number} pointSize The depth or "pointy-ness" of the star points. A pointSize of 0 will draw a regular - * polygon (no points), a pointSize of 1 will draw nothing because the points are infinitely pointy. - * @param {Number} angle The angle of the first point / corner. For example a value of 0 will draw the first point - * directly to the right of the center. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.drawPolyStar = function(x, y, radius, sides, pointSize, angle) { - return this.append(new G.PolyStar(x, y, radius, sides, pointSize, angle)); - }; - - // TODO: deprecated. - /** - * Removed in favour of using custom command objects with {{#crossLink "Graphics/append"}}{{/crossLink}}. - * @method inject - * @deprecated - **/ - - /** - * Appends a graphics command object to the graphics queue. Command objects expose an "exec" method - * that accepts two parameters: the Context2D to operate on, and an arbitrary data object passed into - * {{#crossLink "Graphics/draw"}}{{/crossLink}}. The latter will usually be the Shape instance that called draw. - * - * This method is used internally by Graphics methods, such as drawCircle, but can also be used directly to insert - * built-in or custom graphics commands. For example: - * - * // attach data to our shape, so we can access it during the draw: - * myShape.color = "red"; - * - * // append a Circle command object: - * myShape.graphics.append(new createjs.Graphics.Circle(50, 50, 30)); - * - * // append a custom command object with an exec method that sets the fill style - * // based on the shape's data, and then fills the circle. - * myShape.graphics.append({exec:function(ctx, shape) { - * ctx.fillStyle = shape.color; - * ctx.fill(); - * }}); - * - * @method append - * @param {Object} command A graphics command object exposing an "exec" method. - * @param {boolean} clean The clean param is primarily for internal use. A value of true indicates that a command does not generate a path that should be stroked or filled. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.append = function(command, clean) { - this._activeInstructions.push(command); - this.command = command; - if (!clean) { this._dirty = true; } - return this; - }; - - /** - * Decodes a compact encoded path string into a series of draw instructions. - * This format is not intended to be human readable, and is meant for use by authoring tools. - * The format uses a base64 character set, with each character representing 6 bits, to define a series of draw - * commands. - * - * Each command is comprised of a single "header" character followed by a variable number of alternating x and y - * position values. Reading the header bits from left to right (most to least significant): bits 1 to 3 specify the - * type of operation (0-moveTo, 1-lineTo, 2-quadraticCurveTo, 3-bezierCurveTo, 4-closePath, 5-7 unused). Bit 4 - * indicates whether position values use 12 bits (2 characters) or 18 bits (3 characters), with a one indicating the - * latter. Bits 5 and 6 are currently unused. - * - * Following the header is a series of 0 (closePath), 2 (moveTo, lineTo), 4 (quadraticCurveTo), or 6 (bezierCurveTo) - * parameters. These parameters are alternating x/y positions represented by 2 or 3 characters (as indicated by the - * 4th bit in the command char). These characters consist of a 1 bit sign (1 is negative, 0 is positive), followed - * by an 11 (2 char) or 17 (3 char) bit integer value. All position values are in tenths of a pixel. Except in the - * case of move operations which are absolute, this value is a delta from the previous x or y position (as - * appropriate). - * - * For example, the string "A3cAAMAu4AAA" represents a line starting at -150,0 and ending at 150,0. - *
A - bits 000000. First 3 bits (000) indicate a moveTo operation. 4th bit (0) indicates 2 chars per - * parameter. - *
n0 - 110111011100. Absolute x position of -150.0px. First bit indicates a negative value, remaining bits - * indicate 1500 tenths of a pixel. - *
AA - 000000000000. Absolute y position of 0. - *
I - 001100. First 3 bits (001) indicate a lineTo operation. 4th bit (1) indicates 3 chars per parameter. - *
Au4 - 000000101110111000. An x delta of 300.0px, which is added to the previous x value of -150.0px to - * provide an absolute position of +150.0px. - *
AAA - 000000000000000000. A y delta value of 0. - * - * A tiny API method "p" also exists. - * @method decodePath - * @param {String} str The path string to decode. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.decodePath = function(str) { - var instructions = [this.moveTo, this.lineTo, this.quadraticCurveTo, this.bezierCurveTo, this.closePath]; - var paramCount = [2, 2, 4, 6, 0]; - var i=0, l=str.length; - var params = []; - var x=0, y=0; - var base64 = Graphics.BASE_64; - - while (i>3; // highest order bits 1-3 code for operation. - var f = instructions[fi]; - // check that we have a valid instruction & that the unused bits are empty: - if (!f || (n&3)) { throw("bad path data (@"+i+"): "+c); } - var pl = paramCount[fi]; - if (!fi) { x=y=0; } // move operations reset the position. - params.length = 0; - i++; - var charCount = (n>>2&1)+2; // 4th header bit indicates number size for this operation. - for (var p=0; p>5) ? -1 : 1; - num = ((num&31)<<6)|(base64[str.charAt(i+1)]); - if (charCount == 3) { num = (num<<6)|(base64[str.charAt(i+2)]); } - num = sign*num/10; - if (p%2) { x = (num += x); } - else { y = (num += y); } - params[p] = num; - i += charCount; - } - f.apply(this,params); - } - return this; - }; - - /** - * Stores all graphics commands so they won't be executed in future draws. Calling store() a second time adds to - * the existing store. This also affects `drawAsPath()`. - * - * This is useful in cases where you are creating vector graphics in an iterative manner (ex. generative art), so - * that only new graphics need to be drawn (which can provide huge performance benefits), but you wish to retain all - * of the vector instructions for later use (ex. scaling, modifying, or exporting). - * - * Note that calling store() will force the active path (if any) to be ended in a manner similar to changing - * the fill or stroke. - * - * For example, consider a application where the user draws lines with the mouse. As each line segment (or collection of - * segments) are added to a Shape, it can be rasterized using {{#crossLink "DisplayObject/updateCache"}}{{/crossLink}}, - * and then stored, so that it can be redrawn at a different scale when the application is resized, or exported to SVG. - * - * // set up cache: - * myShape.cache(0,0,500,500,scale); - * - * // when the user drags, draw a new line: - * myShape.graphics.moveTo(oldX,oldY).lineTo(newX,newY); - * // then draw it into the existing cache: - * myShape.updateCache("source-over"); - * // store the new line, so it isn't redrawn next time: - * myShape.store(); - * - * // then, when the window resizes, we can re-render at a different scale: - * // first, unstore all our lines: - * myShape.unstore(); - * // then cache using the new scale: - * myShape.cache(0,0,500,500,newScale); - * // finally, store the existing commands again: - * myShape.store(); - * - * @method store - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.store = function() { - this._updateInstructions(true); - this._storeIndex = this._instructions.length; - return this; - }; - - /** - * Unstores any graphics commands that were previously stored using {{#crossLink "Graphics/store"}}{{/crossLink}} - * so that they will be executed in subsequent draw calls. - * - * @method unstore - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.unstore = function() { - this._storeIndex = 0; - return this; - }; - - /** - * Returns a clone of this Graphics instance. Note that the individual command objects are not cloned. - * @method clone - * @return {Graphics} A clone of the current Graphics instance. - **/ - p.clone = function() { - var o = new Graphics(); - o.command = this.command; - o._stroke = this._stroke; - o._strokeStyle = this._strokeStyle; - o._strokeDash = this._strokeDash; - o._strokeIgnoreScale = this._strokeIgnoreScale; - o._fill = this._fill; - o._instructions = this._instructions.slice(); - o._commitIndex = this._commitIndex; - o._activeInstructions = this._activeInstructions.slice(); - o._dirty = this._dirty; - o._storeIndex = this._storeIndex; - return o; - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Graphics]"; - }; - - -// tiny API: - /** - * Shortcut to moveTo. - * @method mt - * @param {Number} x The x coordinate the drawing point should move to. - * @param {Number} y The y coordinate the drawing point should move to. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls). - * @chainable - * @protected - **/ - p.mt = p.moveTo; - - /** - * Shortcut to lineTo. - * @method lt - * @param {Number} x The x coordinate the drawing point should draw to. - * @param {Number} y The y coordinate the drawing point should draw to. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.lt = p.lineTo; - - /** - * Shortcut to arcTo. - * @method at - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} radius - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.at = p.arcTo; - - /** - * Shortcut to bezierCurveTo. - * @method bt - * @param {Number} cp1x - * @param {Number} cp1y - * @param {Number} cp2x - * @param {Number} cp2y - * @param {Number} x - * @param {Number} y - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.bt = p.bezierCurveTo; - - /** - * Shortcut to quadraticCurveTo / curveTo. - * @method qt - * @param {Number} cpx - * @param {Number} cpy - * @param {Number} x - * @param {Number} y - * @protected - * @chainable - **/ - p.qt = p.quadraticCurveTo; - - /** - * Shortcut to arc. - * @method a - * @param {Number} x - * @param {Number} y - * @param {Number} radius - * @param {Number} startAngle Measured in radians. - * @param {Number} endAngle Measured in radians. - * @param {Boolean} anticlockwise - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @protected - * @chainable - **/ - p.a = p.arc; - - /** - * Shortcut to rect. - * @method r - * @param {Number} x - * @param {Number} y - * @param {Number} w Width of the rectangle - * @param {Number} h Height of the rectangle - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.r = p.rect; - - /** - * Shortcut to closePath. - * @method cp - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.cp = p.closePath; - - /** - * Shortcut to clear. - * @method c - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.c = p.clear; - - /** - * Shortcut to beginFill. - * @method f - * @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to - * null will result in no fill. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.f = p.beginFill; - - /** - * Shortcut to beginLinearGradientFill. - * @method lf - * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define a gradient - * drawing from red to blue. - * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 0.9] would draw - * the first color to 10% then interpolating to the second color at 90%. - * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. - * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. - * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. - * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.lf = p.beginLinearGradientFill; - - /** - * Shortcut to beginRadialGradientFill. - * @method rf - * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define - * a gradient drawing from red to blue. - * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, - * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. - * @param {Number} x0 Center position of the inner circle that defines the gradient. - * @param {Number} y0 Center position of the inner circle that defines the gradient. - * @param {Number} r0 Radius of the inner circle that defines the gradient. - * @param {Number} x1 Center position of the outer circle that defines the gradient. - * @param {Number} y1 Center position of the outer circle that defines the gradient. - * @param {Number} r1 Radius of the outer circle that defines the gradient. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.rf = p.beginRadialGradientFill; - - /** - * Shortcut to beginBitmapFill. - * @method bf - * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use - * as the pattern. - * @param {String} repetition Optional. Indicates whether to repeat the image in the fill area. One of "repeat", - * "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". Note that Firefox does not support "repeat-x" or - * "repeat-y" (latest tests were in FF 20.0), and will default to "repeat". - * @param {Matrix2D} matrix Optional. Specifies a transformation matrix for the bitmap fill. This transformation - * will be applied relative to the parent transform. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.bf = p.beginBitmapFill; - - /** - * Shortcut to endFill. - * @method ef - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.ef = p.endFill; - - /** - * Shortcut to setStrokeStyle. - * @method ss - * @param {Number} thickness The width of the stroke. - * @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt, - * round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2 (square) for use with - * the tiny API. - * @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet. - * One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel) - * for use with the tiny API. - * @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which - * controls at what point a mitered joint will be clipped. - * @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless - * of active transformations. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.ss = p.setStrokeStyle; - - /** - * Shortcut to setStrokeDash. - * @method sd - * @param {Array} [segments] An array specifying the dash pattern, alternating between line and gap. - * For example, [20,10] would create a pattern of 20 pixel lines with 10 pixel gaps between them. - * Passing null or an empty array will clear any existing dash. - * @param {Number} [offset=0] The offset of the dash pattern. For example, you could increment this value to create a "marching ants" effect. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.sd = p.setStrokeDash; - - /** - * Shortcut to beginStroke. - * @method s - * @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to - * null will result in no stroke. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.s = p.beginStroke; - - /** - * Shortcut to beginLinearGradientStroke. - * @method ls - * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define - * a gradient drawing from red to blue. - * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, - * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. - * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. - * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. - * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. - * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.ls = p.beginLinearGradientStroke; - - /** - * Shortcut to beginRadialGradientStroke. - * @method rs - * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define - * a gradient drawing from red to blue. - * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, - * 0.9] would draw the first color to 10% then interpolating to the second color at 90%, then draw the second color - * to 100%. - * @param {Number} x0 Center position of the inner circle that defines the gradient. - * @param {Number} y0 Center position of the inner circle that defines the gradient. - * @param {Number} r0 Radius of the inner circle that defines the gradient. - * @param {Number} x1 Center position of the outer circle that defines the gradient. - * @param {Number} y1 Center position of the outer circle that defines the gradient. - * @param {Number} r1 Radius of the outer circle that defines the gradient. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.rs = p.beginRadialGradientStroke; - - /** - * Shortcut to beginBitmapStroke. - * @method bs - * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use - * as the pattern. - * @param {String} [repetition=repeat] Optional. Indicates whether to repeat the image in the fill area. One of - * "repeat", "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.bs = p.beginBitmapStroke; - - /** - * Shortcut to endStroke. - * @method es - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.es = p.endStroke; - - /** - * Shortcut to drawRect. - * @method dr - * @param {Number} x - * @param {Number} y - * @param {Number} w Width of the rectangle - * @param {Number} h Height of the rectangle - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.dr = p.drawRect; - - /** - * Shortcut to drawRoundRect. - * @method rr - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - * @param {Number} radius Corner radius. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.rr = p.drawRoundRect; - - /** - * Shortcut to drawRoundRectComplex. - * @method rc - * @param {Number} x The horizontal coordinate to draw the round rect. - * @param {Number} y The vertical coordinate to draw the round rect. - * @param {Number} w The width of the round rect. - * @param {Number} h The height of the round rect. - * @param {Number} radiusTL Top left corner radius. - * @param {Number} radiusTR Top right corner radius. - * @param {Number} radiusBR Bottom right corner radius. - * @param {Number} radiusBL Bottom left corner radius. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.rc = p.drawRoundRectComplex; - - /** - * Shortcut to drawCircle. - * @method dc - * @param {Number} x x coordinate center point of circle. - * @param {Number} y y coordinate center point of circle. - * @param {Number} radius Radius of circle. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.dc = p.drawCircle; - - /** - * Shortcut to drawEllipse. - * @method de - * @param {Number} x The left coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} - * which draws from center. - * @param {Number} y The top coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} - * which draws from the center. - * @param {Number} w The height (horizontal diameter) of the ellipse. The horizontal radius will be half of this - * number. - * @param {Number} h The width (vertical diameter) of the ellipse. The vertical radius will be half of this number. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.de = p.drawEllipse; - - /** - * Shortcut to drawPolyStar. - * @method dp - * @param {Number} x Position of the center of the shape. - * @param {Number} y Position of the center of the shape. - * @param {Number} radius The outer radius of the shape. - * @param {Number} sides The number of points on the star or sides on the polygon. - * @param {Number} pointSize The depth or "pointy-ness" of the star points. A pointSize of 0 will draw a regular - * polygon (no points), a pointSize of 1 will draw nothing because the points are infinitely pointy. - * @param {Number} angle The angle of the first point / corner. For example a value of 0 will draw the first point - * directly to the right of the center. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.dp = p.drawPolyStar; - - /** - * Shortcut to decodePath. - * @method p - * @param {String} str The path string to decode. - * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) - * @chainable - * @protected - **/ - p.p = p.decodePath; - - -// private methods: - /** - * @method _updateInstructions - * @param commit - * @protected - **/ - p._updateInstructions = function(commit) { - var instr = this._instructions, active = this._activeInstructions, commitIndex = this._commitIndex; - - if (this._dirty && active.length) { - instr.length = commitIndex; // remove old, uncommitted commands - instr.push(Graphics.beginCmd); - - var l = active.length, ll = instr.length; - instr.length = ll+l; - for (var i=0; i= 2) { - var o = this.style = Graphics._ctx.createPattern(image, repetition || ""); - o.props = {image: image, repetition: repetition, type: "bitmap"}; - } - return this; - }; - p.path = false; - - /** - * Graphics command object. See {{#crossLink "Graphics/beginStroke"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. - * @class Stroke - * @constructor - * @param {Object} style A valid Context2D fillStyle. - * @param {Boolean} ignoreScale - **/ - /** - * A valid Context2D strokeStyle. - * @property style - * @type Object - */ - /** - * @property ignoreScale - * @type Boolean - */ - /** - * Execute the Graphics command in the provided Canvas context. - * @method exec - * @param {CanvasRenderingContext2D} ctx The canvas rendering context - */ - p = (G.Stroke = function(style, ignoreScale) { - this.style = style; - this.ignoreScale = ignoreScale; - }).prototype; - p.exec = function(ctx) { - if (!this.style) { return; } - ctx.strokeStyle = this.style; - if (this.ignoreScale) { ctx.save(); ctx.setTransform(1,0,0,1,0,0); } - ctx.stroke(); - if (this.ignoreScale) { ctx.restore(); } - }; - /** - * Creates a linear gradient style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}. - * See {{#crossLink "Graphics/beginLinearGradientStroke"}}{{/crossLink}} for more information. - * @method linearGradient - * @param {Array} colors - * @param {Array} ratios - * @param {Number} x0 - * @param {Number} y0 - * @param {Number} x1 - * @param {Number} y1 - * @return {Fill} Returns this Stroke object for chaining or assignment. - */ - p.linearGradient = G.Fill.prototype.linearGradient; - /** - * Creates a radial gradient style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}. - * See {{#crossLink "Graphics/beginRadialGradientStroke"}}{{/crossLink}} for more information. - * @method radialGradient - * @param {Array} colors - * @param {Array} ratios - * @param {Number} x0 - * @param {Number} y0 - * @param {Number} r0 - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} r1 - * @return {Fill} Returns this Stroke object for chaining or assignment. - */ - p.radialGradient = G.Fill.prototype.radialGradient; - /** - * Creates a bitmap fill style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}. - * See {{#crossLink "Graphics/beginBitmapStroke"}}{{/crossLink}} for more information. - * @method bitmap - * @param {HTMLImageElement} image - * @param {String} [repetition] One of: repeat, repeat-x, repeat-y, or no-repeat. - * @return {Fill} Returns this Stroke object for chaining or assignment. - */ - p.bitmap = G.Fill.prototype.bitmap; - p.path = false; - - /** - * Graphics command object. See {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. - * @class StrokeStyle - * @constructor - * @param {Number} width - * @param {String} [caps=butt] - * @param {String} [joints=miter] - * @param {Number} [miterLimit=10] - * @param {Boolean} [ignoreScale=false] - **/ - /** - * @property width - * @type Number - */ - /** - * One of: butt, round, square - * @property caps - * @type String - */ - /** - * One of: round, bevel, miter - * @property joints - * @type String - */ - /** - * @property miterLimit - * @type Number - */ - /** - * Execute the Graphics command in the provided Canvas context. - * @method exec - * @param {CanvasRenderingContext2D} ctx The canvas rendering context - */ - p = (G.StrokeStyle = function(width, caps, joints, miterLimit, ignoreScale) { - this.width = width; - this.caps = caps; - this.joints = joints; - this.miterLimit = miterLimit; - this.ignoreScale = ignoreScale; - }).prototype; - p.exec = function(ctx) { - ctx.lineWidth = (this.width == null ? "1" : this.width); - ctx.lineCap = (this.caps == null ? "butt" : (isNaN(this.caps) ? this.caps : Graphics.STROKE_CAPS_MAP[this.caps])); - ctx.lineJoin = (this.joints == null ? "miter" : (isNaN(this.joints) ? this.joints : Graphics.STROKE_JOINTS_MAP[this.joints])); - ctx.miterLimit = (this.miterLimit == null ? "10" : this.miterLimit); - ctx.ignoreScale = (this.ignoreScale == null ? false : this.ignoreScale); - }; - p.path = false; - - /** - * Graphics command object. See {{#crossLink "Graphics/setStrokeDash"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. - * @class StrokeDash - * @constructor - * @param {Array} [segments] - * @param {Number} [offset=0] - **/ - /** - * @property segments - * @type Array - */ - /** - * @property offset - * @type Number - */ - /** - * Execute the Graphics command in the provided Canvas context. - * @method exec - * @param {CanvasRenderingContext2D} ctx The canvas rendering context - */ - (G.StrokeDash = function(segments, offset) { - this.segments = segments; - this.offset = offset||0; - }).prototype.exec = function(ctx) { - if (ctx.setLineDash) { // feature detection. - ctx.setLineDash(this.segments|| G.StrokeDash.EMPTY_SEGMENTS); // instead of [] to reduce churn. - ctx.lineDashOffset = this.offset||0; - } - }; - /** - * The default value for segments (ie. no dash). - * @property EMPTY_SEGMENTS - * @static - * @final - * @readonly - * @protected - * @type {Array} - **/ - G.StrokeDash.EMPTY_SEGMENTS = []; - - /** - * Graphics command object. See {{#crossLink "Graphics/drawRoundRectComplex"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. - * @class RoundRect - * @constructor - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - * @param {Number} radiusTL - * @param {Number} radiusTR - * @param {Number} radiusBR - * @param {Number} radiusBL - **/ - /** - * @property x - * @type Number - */ - /** - * @property y - * @type Number - */ - /** - * @property w - * @type Number - */ - /** - * @property h - * @type Number - */ - /** - * @property radiusTL - * @type Number - */ - /** - * @property radiusTR - * @type Number - */ - /** - * @property radiusBR - * @type Number - */ - /** - * @property radiusBL - * @type Number - */ - /** - * Execute the Graphics command in the provided Canvas context. - * @method exec - * @param {CanvasRenderingContext2D} ctx The canvas rendering context - */ - (G.RoundRect = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL) { - this.x = x; this.y = y; - this.w = w; this.h = h; - this.radiusTL = radiusTL; this.radiusTR = radiusTR; - this.radiusBR = radiusBR; this.radiusBL = radiusBL; - }).prototype.exec = function(ctx) { - var max = (w max) { rTL = max; } - if (rTR < 0) { rTR *= (mTR=-1); } - if (rTR > max) { rTR = max; } - if (rBR < 0) { rBR *= (mBR=-1); } - if (rBR > max) { rBR = max; } - if (rBL < 0) { rBL *= (mBL=-1); } - if (rBL > max) { rBL = max; } - - ctx.moveTo(x+w-rTR, y); - ctx.arcTo(x+w+rTR*mTR, y-rTR*mTR, x+w, y+rTR, rTR); - ctx.lineTo(x+w, y+h-rBR); - ctx.arcTo(x+w+rBR*mBR, y+h+rBR*mBR, x+w-rBR, y+h, rBR); - ctx.lineTo(x+rBL, y+h); - ctx.arcTo(x-rBL*mBL, y+h+rBL*mBL, x, y+h-rBL, rBL); - ctx.lineTo(x, y+rTL); - ctx.arcTo(x-rTL*mTL, y-rTL*mTL, x+rTL, y, rTL); - ctx.closePath(); - }; - - /** - * Graphics command object. See {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. - * @class Circle - * @constructor - * @param {Number} x - * @param {Number} y - * @param {Number} radius - **/ - /** - * @property x - * @type Number - */ - /** - * @property y - * @type Number - */ - /** - * @property radius - * @type Number - */ - /** - * Execute the Graphics command in the provided Canvas context. - * @method exec - * @param {CanvasRenderingContext2D} ctx The canvas rendering context - */ - (G.Circle = function(x, y, radius) { - this.x = x; this.y = y; - this.radius = radius; - }).prototype.exec = function(ctx) { ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2); }; - - /** - * Graphics command object. See {{#crossLink "Graphics/drawEllipse"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. - * @class Ellipse - * @constructor - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - **/ - /** - * @property x - * @type Number - */ - /** - * @property y - * @type Number - */ - /** - * @property w - * @type Number - */ - /** - * @property h - * @type Number - */ - /** - * Execute the Graphics command in the provided Canvas context. - * @method exec - * @param {CanvasRenderingContext2D} ctx The canvas rendering context - */ - (G.Ellipse = function(x, y, w, h) { - this.x = x; this.y = y; - this.w = w; this.h = h; - }).prototype.exec = function(ctx) { - var x = this.x, y = this.y; - var w = this.w, h = this.h; - - var k = 0.5522848; - var ox = (w / 2) * k; - var oy = (h / 2) * k; - var xe = x + w; - var ye = y + h; - var xm = x + w / 2; - var ym = y + h / 2; - - ctx.moveTo(x, ym); - ctx.bezierCurveTo(x, ym-oy, xm-ox, y, xm, y); - ctx.bezierCurveTo(xm+ox, y, xe, ym-oy, xe, ym); - ctx.bezierCurveTo(xe, ym+oy, xm+ox, ye, xm, ye); - ctx.bezierCurveTo(xm-ox, ye, x, ym+oy, x, ym); - }; - - /** - * Graphics command object. See {{#crossLink "Graphics/drawPolyStar"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. - * @class PolyStar - * @constructor - * @param {Number} x - * @param {Number} y - * @param {Number} radius - * @param {Number} sides - * @param {Number} pointSize - * @param {Number} angle - **/ - /** - * @property x - * @type Number - */ - /** - * @property y - * @type Number - */ - /** - * @property radius - * @type Number - */ - /** - * @property sides - * @type Number - */ - /** - * @property pointSize - * @type Number - */ - /** - * @property angle - * @type Number - */ - /** - * Execute the Graphics command in the provided Canvas context. - * @method exec - * @param {CanvasRenderingContext2D} ctx The canvas rendering context - */ - (G.PolyStar = function(x, y, radius, sides, pointSize, angle) { - this.x = x; this.y = y; - this.radius = radius; - this.sides = sides; - this.pointSize = pointSize; - this.angle = angle; - }).prototype.exec = function(ctx) { - var x = this.x, y = this.y; - var radius = this.radius; - var angle = (this.angle||0)/180*Math.PI; - var sides = this.sides; - var ps = 1-(this.pointSize||0); - var a = Math.PI/sides; - - ctx.moveTo(x+Math.cos(angle)*radius, y+Math.sin(angle)*radius); - for (var i=0; iNote: In EaselJS 0.7.0, the mouseEnabled property will not work properly with nested Containers. Please - * check out the latest NEXT version in GitHub for an updated version with this issue resolved. The fix will be - * provided in the next release of EaselJS. - * @property mouseEnabled - * @type {Boolean} - * @default true - **/ - this.mouseEnabled = true; - - /** - * If false, the tick will not run on this display object (or its children). This can provide some performance benefits. - * In addition to preventing the "tick" event from being dispatched, it will also prevent tick related updates - * on some display objects (ex. Sprite & MovieClip frame advancing, DOMElement visibility handling). - * @property tickEnabled - * @type Boolean - * @default true - **/ - this.tickEnabled = true; - - /** - * An optional name for this display object. Included in {{#crossLink "DisplayObject/toString"}}{{/crossLink}} . Useful for - * debugging. - * @property name - * @type {String} - * @default null - **/ - this.name = null; - - /** - * A reference to the {{#crossLink "Container"}}{{/crossLink}} or {{#crossLink "Stage"}}{{/crossLink}} object that - * contains this display object, or null if it has not been added - * to one. - * @property parent - * @final - * @type {Container} - * @default null - * @readonly - **/ - this.parent = null; - - /** - * The left offset for this display object's registration point. For example, to make a 100x100px Bitmap rotate - * around its center, you would set regX and {{#crossLink "DisplayObject/regY:property"}}{{/crossLink}} to 50. - * @property regX - * @type {Number} - * @default 0 - **/ - this.regX = 0; - - /** - * The y offset for this display object's registration point. For example, to make a 100x100px Bitmap rotate around - * its center, you would set {{#crossLink "DisplayObject/regX:property"}}{{/crossLink}} and regY to 50. - * @property regY - * @type {Number} - * @default 0 - **/ - this.regY = 0; - - /** - * The rotation in degrees for this display object. - * @property rotation - * @type {Number} - * @default 0 - **/ - this.rotation = 0; - - /** - * The factor to stretch this display object horizontally. For example, setting scaleX to 2 will stretch the display - * object to twice its nominal width. To horizontally flip an object, set the scale to a negative number. - * @property scaleX - * @type {Number} - * @default 1 - **/ - this.scaleX = 1; - - /** - * The factor to stretch this display object vertically. For example, setting scaleY to 0.5 will stretch the display - * object to half its nominal height. To vertically flip an object, set the scale to a negative number. - * @property scaleY - * @type {Number} - * @default 1 - **/ - this.scaleY = 1; - - /** - * The factor to skew this display object horizontally. - * @property skewX - * @type {Number} - * @default 0 - **/ - this.skewX = 0; - - /** - * The factor to skew this display object vertically. - * @property skewY - * @type {Number} - * @default 0 - **/ - this.skewY = 0; - - /** - * A shadow object that defines the shadow to render on this display object. Set to `null` to remove a shadow. If - * null, this property is inherited from the parent container. - * @property shadow - * @type {Shadow} - * @default null - **/ - this.shadow = null; - - /** - * Indicates whether this display object should be rendered to the canvas and included when running the Stage - * {{#crossLink "Stage/getObjectsUnderPoint"}}{{/crossLink}} method. - * @property visible - * @type {Boolean} - * @default true - **/ - this.visible = true; - - /** - * The x (horizontal) position of the display object, relative to its parent. - * @property x - * @type {Number} - * @default 0 - **/ - this.x = 0; - - /** The y (vertical) position of the display object, relative to its parent. - * @property y - * @type {Number} - * @default 0 - **/ - this.y = 0; - - /** - * If set, defines the transformation for this display object, overriding all other transformation properties - * (x, y, rotation, scale, skew). - * @property transformMatrix - * @type {Matrix2D} - * @default null - **/ - this.transformMatrix = null; - - /** - * The composite operation indicates how the pixels of this display object will be composited with the elements - * behind it. If `null`, this property is inherited from the parent container. For more information, read the - * - * whatwg spec on compositing. - * @property compositeOperation - * @type {String} - * @default null - **/ - this.compositeOperation = null; - - /** - * Indicates whether the display object should be drawn to a whole pixel when - * {{#crossLink "Stage/snapToPixelEnabled"}}{{/crossLink}} is true. To enable/disable snapping on whole - * categories of display objects, set this value on the prototype (Ex. Text.prototype.snapToPixel = true). - * @property snapToPixel - * @type {Boolean} - * @default true - **/ - this.snapToPixel = true; - - /** - * An array of Filter objects to apply to this display object. Filters are only applied / updated when {{#crossLink "cache"}}{{/crossLink}} - * or {{#crossLink "updateCache"}}{{/crossLink}} is called on the display object, and only apply to the area that is - * cached. - * @property filters - * @type {Array} - * @default null - **/ - this.filters = null; - - /** - * A Shape instance that defines a vector mask (clipping path) for this display object. The shape's transformation - * will be applied relative to the display object's parent coordinates (as if it were a child of the parent). - * @property mask - * @type {Shape} - * @default null - */ - this.mask = null; - - /** - * A display object that will be tested when checking mouse interactions or testing {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}}. - * The hit area will have its transformation applied relative to this display object's coordinate space (as though - * the hit test object were a child of this display object and relative to its regX/Y). The hitArea will be tested - * using only its own `alpha` value regardless of the alpha value on the target display object, or the target's - * ancestors (parents). - * - * If set on a {{#crossLink "Container"}}{{/crossLink}}, children of the Container will not receive mouse events. - * This is similar to setting {{#crossLink "mouseChildren"}}{{/crossLink}} to false. - * - * Note that hitArea is NOT currently used by the `hitTest()` method, nor is it supported for {{#crossLink "Stage"}}{{/crossLink}}. - * @property hitArea - * @type {DisplayObject} - * @default null - */ - this.hitArea = null; - - /** - * A CSS cursor (ex. "pointer", "help", "text", etc) that will be displayed when the user hovers over this display - * object. You must enable mouseover events using the {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}} method to - * use this property. Setting a non-null cursor on a Container will override the cursor set on its descendants. - * @property cursor - * @type {String} - * @default null - */ - this.cursor = null; - - - // private properties: - /** - * @property _cacheOffsetX - * @protected - * @type {Number} - * @default 0 - **/ - this._cacheOffsetX = 0; - - /** - * @property _cacheOffsetY - * @protected - * @type {Number} - * @default 0 - **/ - this._cacheOffsetY = 0; - - /** - * @property _filterOffsetX - * @protected - * @type {Number} - * @default 0 - **/ - this._filterOffsetX = 0; - - /** - * @property _filterOffsetY - * @protected - * @type {Number} - * @default 0 - **/ - this._filterOffsetY = 0; - - /** - * @property _cacheScale - * @protected - * @type {Number} - * @default 1 - **/ - this._cacheScale = 1; - - /** - * @property _cacheDataURLID - * @protected - * @type {Number} - * @default 0 - */ - this._cacheDataURLID = 0; - - /** - * @property _cacheDataURL - * @protected - * @type {String} - * @default null - */ - this._cacheDataURL = null; - - /** - * @property _props - * @protected - * @type {DisplayObject} - * @default null - **/ - this._props = new createjs.DisplayProps(); - - /** - * @property _rectangle - * @protected - * @type {Rectangle} - * @default null - **/ - this._rectangle = new createjs.Rectangle(); - - /** - * @property _bounds - * @protected - * @type {Rectangle} - * @default null - **/ - this._bounds = null; - } - var p = createjs.extend(DisplayObject, createjs.EventDispatcher); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - -// static properties: - /** - * Listing of mouse event names. Used in _hasMouseEventListener. - * @property _MOUSE_EVENTS - * @protected - * @static - * @type {Array} - **/ - DisplayObject._MOUSE_EVENTS = ["click","dblclick","mousedown","mouseout","mouseover","pressmove","pressup","rollout","rollover"]; - - /** - * Suppresses errors generated when using features like hitTest, mouse events, and {{#crossLink "getObjectsUnderPoint"}}{{/crossLink}} - * with cross domain content. - * @property suppressCrossDomainErrors - * @static - * @type {Boolean} - * @default false - **/ - DisplayObject.suppressCrossDomainErrors = false; - - /** - * @property _snapToPixelEnabled - * @protected - * @static - * @type {Boolean} - * @default false - **/ - DisplayObject._snapToPixelEnabled = false; // stage.snapToPixelEnabled is temporarily copied here during a draw to provide global access. - - /** - * @property _hitTestCanvas - * @type {HTMLCanvasElement | Object} - * @static - * @protected - **/ - /** - * @property _hitTestContext - * @type {CanvasRenderingContext2D} - * @static - * @protected - **/ - var canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); // prevent errors on load in browsers without canvas. - if (canvas.getContext) { - DisplayObject._hitTestCanvas = canvas; - DisplayObject._hitTestContext = canvas.getContext("2d"); - canvas.width = canvas.height = 1; - } - - /** - * @property _nextCacheID - * @type {Number} - * @static - * @protected - **/ - DisplayObject._nextCacheID = 1; - - -// events: - /** - * Dispatched when the user presses their left mouse button over the display object. See the - * {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. - * @event mousedown - * @since 0.6.0 - */ - - /** - * Dispatched when the user presses their left mouse button and then releases it while over the display object. - * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. - * @event click - * @since 0.6.0 - */ - - /** - * Dispatched when the user double clicks their left mouse button over this display object. - * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. - * @event dblclick - * @since 0.6.0 - */ - - /** - * Dispatched when the user's mouse enters this display object. This event must be enabled using - * {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. See also {{#crossLink "DisplayObject/rollover:event"}}{{/crossLink}}. - * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. - * @event mouseover - * @since 0.6.0 - */ - - /** - * Dispatched when the user's mouse leaves this display object. This event must be enabled using - * {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. See also {{#crossLink "DisplayObject/rollout:event"}}{{/crossLink}}. - * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. - * @event mouseout - * @since 0.6.0 - */ - - /** - * This event is similar to {{#crossLink "DisplayObject/mouseover:event"}}{{/crossLink}}, with the following - * differences: it does not bubble, and it considers {{#crossLink "Container"}}{{/crossLink}} instances as an - * aggregate of their content. - * - * For example, myContainer contains two overlapping children: shapeA and shapeB. The user moves their mouse over - * shapeA and then directly on to shapeB. With a listener for {{#crossLink "mouseover:event"}}{{/crossLink}} on - * myContainer, two events would be received, each targeting a child element:
    - *
  1. when the mouse enters shapeA (target=shapeA)
  2. - *
  3. when the mouse enters shapeB (target=shapeB)
  4. - *
- * However, with a listener for "rollover" instead, only a single event is received when the mouse first enters - * the aggregate myContainer content (target=myContainer). - * - * This event must be enabled using {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. - * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. - * @event rollover - * @since 0.7.0 - */ - - /** - * This event is similar to {{#crossLink "DisplayObject/mouseout:event"}}{{/crossLink}}, with the following - * differences: it does not bubble, and it considers {{#crossLink "Container"}}{{/crossLink}} instances as an - * aggregate of their content. - * - * For example, myContainer contains two overlapping children: shapeA and shapeB. The user moves their mouse over - * shapeA, then directly on to shapeB, then off both. With a listener for {{#crossLink "mouseout:event"}}{{/crossLink}} - * on myContainer, two events would be received, each targeting a child element:
    - *
  1. when the mouse leaves shapeA (target=shapeA)
  2. - *
  3. when the mouse leaves shapeB (target=shapeB)
  4. - *
- * However, with a listener for "rollout" instead, only a single event is received when the mouse leaves - * the aggregate myContainer content (target=myContainer). - * - * This event must be enabled using {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. - * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. - * @event rollout - * @since 0.7.0 - */ - - /** - * After a {{#crossLink "DisplayObject/mousedown:event"}}{{/crossLink}} occurs on a display object, a pressmove - * event will be generated on that object whenever the mouse moves until the mouse press is released. This can be - * useful for dragging and similar operations. - * @event pressmove - * @since 0.7.0 - */ - - /** - * After a {{#crossLink "DisplayObject/mousedown:event"}}{{/crossLink}} occurs on a display object, a pressup event - * will be generated on that object when that mouse press is released. This can be useful for dragging and similar - * operations. - * @event pressup - * @since 0.7.0 - */ - - /** - * Dispatched when the display object is added to a parent container. - * @event added - */ - - /** - * Dispatched when the display object is removed from its parent container. - * @event removed - */ - - /** - * Dispatched on each display object on a stage whenever the stage updates. This occurs immediately before the - * rendering (draw) pass. When {{#crossLink "Stage/update"}}{{/crossLink}} is called, first all display objects on - * the stage dispatch the tick event, then all of the display objects are drawn to stage. Children will have their - * {{#crossLink "tick:event"}}{{/crossLink}} event dispatched in order of their depth prior to the event being - * dispatched on their parent. - * @event tick - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Array} params An array containing any arguments that were passed to the Stage.update() method. For - * example if you called stage.update("hello"), then the params would be ["hello"]. - * @since 0.6.0 - */ - - -// getter / setters: - /** - * Use the {{#crossLink "DisplayObject/stage:property"}}{{/crossLink}} property instead. - * @method getStage - * @return {Stage} - * @deprecated - **/ - p.getStage = function() { - // uses dynamic access to avoid circular dependencies; - var o = this, _Stage = createjs["Stage"]; - while (o.parent) { o = o.parent; } - if (o instanceof _Stage) { return o; } - return null; - }; - - /** - * Returns the Stage instance that this display object will be rendered on, or null if it has not been added to one. - * @property stage - * @type {Stage} - * @readonly - **/ - try { - Object.defineProperties(p, { - stage: { get: p.getStage } - }); - } catch (e) {} - - -// public methods: - /** - * Returns true or false indicating whether the display object would be visible if drawn to a canvas. - * This does not account for whether it would be visible within the boundaries of the stage. - * - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method isVisible - * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas - **/ - p.isVisible = function() { - return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0); - }; - - /** - * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. - * Returns true if the draw was handled (useful for overriding functionality). - * - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method draw - * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. - * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. For example, - * used for drawing the cache (to prevent it from simply drawing an existing cache back into itself). - * @return {Boolean} - **/ - p.draw = function(ctx, ignoreCache) { - var cacheCanvas = this.cacheCanvas; - if (ignoreCache || !cacheCanvas) { return false; } - var scale = this._cacheScale; - ctx.drawImage(cacheCanvas, this._cacheOffsetX+this._filterOffsetX, this._cacheOffsetY+this._filterOffsetY, cacheCanvas.width/scale, cacheCanvas.height/scale); - return true; - }; - - /** - * Applies this display object's transformation, alpha, globalCompositeOperation, clipping path (mask), and shadow - * to the specified context. This is typically called prior to {{#crossLink "DisplayObject/draw"}}{{/crossLink}}. - * @method updateContext - * @param {CanvasRenderingContext2D} ctx The canvas 2D to update. - **/ - p.updateContext = function(ctx) { - var o=this, mask=o.mask, mtx= o._props.matrix; - - if (mask && mask.graphics && !mask.graphics.isEmpty()) { - mask.getMatrix(mtx); - ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty); - - mask.graphics.drawAsPath(ctx); - ctx.clip(); - - mtx.invert(); - ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty); - } - - this.getMatrix(mtx); - var tx = mtx.tx, ty = mtx.ty; - if (DisplayObject._snapToPixelEnabled && o.snapToPixel) { - tx = tx + (tx < 0 ? -0.5 : 0.5) | 0; - ty = ty + (ty < 0 ? -0.5 : 0.5) | 0; - } - ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, tx, ty); - ctx.globalAlpha *= o.alpha; - if (o.compositeOperation) { ctx.globalCompositeOperation = o.compositeOperation; } - if (o.shadow) { this._applyShadow(ctx, o.shadow); } - }; - - /** - * Draws the display object into a new canvas, which is then used for subsequent draws. For complex content - * that does not change frequently (ex. a Container with many children that do not move, or a complex vector Shape), - * this can provide for much faster rendering because the content does not need to be re-rendered each tick. The - * cached display object can be moved, rotated, faded, etc freely, however if its content changes, you must - * manually update the cache by calling updateCache() or cache() again. You must specify - * the cache area via the x, y, w, and h parameters. This defines the rectangle that will be rendered and cached - * using this display object's coordinates. - * - *

Example

- * For example if you defined a Shape that drew a circle at 0, 0 with a radius of 25: - * - * var shape = new createjs.Shape(); - * shape.graphics.beginFill("#ff0000").drawCircle(0, 0, 25); - * myShape.cache(-25, -25, 50, 50); - * - * Note that filters need to be defined before the cache is applied. Check out the {{#crossLink "Filter"}}{{/crossLink}} - * class for more information. Some filters (ex. BlurFilter) will not work as expected in conjunction with the scale param. - * - * Usually, the resulting cacheCanvas will have the dimensions width*scale by height*scale, however some filters (ex. BlurFilter) - * will add padding to the canvas dimensions. - * - * @method cache - * @param {Number} x The x coordinate origin for the cache region. - * @param {Number} y The y coordinate origin for the cache region. - * @param {Number} width The width of the cache region. - * @param {Number} height The height of the cache region. - * @param {Number} [scale=1] The scale at which the cache will be created. For example, if you cache a vector shape using - * myShape.cache(0,0,100,100,2) then the resulting cacheCanvas will be 200x200 px. This lets you scale and rotate - * cached elements with greater fidelity. Default is 1. - **/ - p.cache = function(x, y, width, height, scale) { - // draw to canvas. - scale = scale||1; - if (!this.cacheCanvas) { this.cacheCanvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); } - this._cacheWidth = width; - this._cacheHeight = height; - this._cacheOffsetX = x; - this._cacheOffsetY = y; - this._cacheScale = scale; - this.updateCache(); - }; - - /** - * Redraws the display object to its cache. Calling updateCache without an active cache will throw an error. - * If compositeOperation is null the current cache will be cleared prior to drawing. Otherwise the display object - * will be drawn over the existing cache using the specified compositeOperation. - * - *

Example

- * Clear the current graphics of a cached shape, draw some new instructions, and then update the cache. The new line - * will be drawn on top of the old one. - * - * // Not shown: Creating the shape, and caching it. - * shapeInstance.clear(); - * shapeInstance.setStrokeStyle(3).beginStroke("#ff0000").moveTo(100, 100).lineTo(200,200); - * shapeInstance.updateCache(); - * - * @method updateCache - * @param {String} compositeOperation The compositeOperation to use, or null to clear the cache and redraw it. - * - * whatwg spec on compositing. - **/ - p.updateCache = function(compositeOperation) { - var cacheCanvas = this.cacheCanvas; - if (!cacheCanvas) { throw "cache() must be called before updateCache()"; } - var scale = this._cacheScale, offX = this._cacheOffsetX*scale, offY = this._cacheOffsetY*scale; - var w = this._cacheWidth, h = this._cacheHeight, ctx = cacheCanvas.getContext("2d"); - - var fBounds = this._getFilterBounds(); - offX += (this._filterOffsetX = fBounds.x); - offY += (this._filterOffsetY = fBounds.y); - - w = Math.ceil(w*scale) + fBounds.width; - h = Math.ceil(h*scale) + fBounds.height; - if (w != cacheCanvas.width || h != cacheCanvas.height) { - // TODO: it would be nice to preserve the content if there is a compositeOperation. - cacheCanvas.width = w; - cacheCanvas.height = h; - } else if (!compositeOperation) { - ctx.clearRect(0, 0, w+1, h+1); - } - - ctx.save(); - ctx.globalCompositeOperation = compositeOperation; - ctx.setTransform(scale, 0, 0, scale, -offX, -offY); - this.draw(ctx, true); - // TODO: filters and cache scale don't play well together at present. - this._applyFilters(); - ctx.restore(); - this.cacheID = DisplayObject._nextCacheID++; - }; - - /** - * Clears the current cache. See {{#crossLink "DisplayObject/cache"}}{{/crossLink}} for more information. - * @method uncache - **/ - p.uncache = function() { - this._cacheDataURL = this.cacheCanvas = null; - this.cacheID = this._cacheOffsetX = this._cacheOffsetY = this._filterOffsetX = this._filterOffsetY = 0; - this._cacheScale = 1; - }; - - /** - * Returns a data URL for the cache, or null if this display object is not cached. - * Uses cacheID to ensure a new data URL is not generated if the cache has not changed. - * @method getCacheDataURL - * @return {String} The image data url for the cache. - **/ - p.getCacheDataURL = function() { - if (!this.cacheCanvas) { return null; } - if (this.cacheID != this._cacheDataURLID) { this._cacheDataURL = this.cacheCanvas.toDataURL(); } - return this._cacheDataURL; - }; - - /** - * Transforms the specified x and y position from the coordinate space of the display object - * to the global (stage) coordinate space. For example, this could be used to position an HTML label - * over a specific point on a nested display object. Returns a Point instance with x and y properties - * correlating to the transformed coordinates on the stage. - * - *

Example

- * - * displayObject.x = 300; - * displayObject.y = 200; - * stage.addChild(displayObject); - * var point = displayObject.localToGlobal(100, 100); - * // Results in x=400, y=300 - * - * @method localToGlobal - * @param {Number} x The x position in the source display object to transform. - * @param {Number} y The y position in the source display object to transform. - * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. - * @return {Point} A Point instance with x and y properties correlating to the transformed coordinates - * on the stage. - **/ - p.localToGlobal = function(x, y, pt) { - return this.getConcatenatedMatrix(this._props.matrix).transformPoint(x,y, pt||new createjs.Point()); - }; - - /** - * Transforms the specified x and y position from the global (stage) coordinate space to the - * coordinate space of the display object. For example, this could be used to determine - * the current mouse position within the display object. Returns a Point instance with x and y properties - * correlating to the transformed position in the display object's coordinate space. - * - *

Example

- * - * displayObject.x = 300; - * displayObject.y = 200; - * stage.addChild(displayObject); - * var point = displayObject.globalToLocal(100, 100); - * // Results in x=-200, y=-100 - * - * @method globalToLocal - * @param {Number} x The x position on the stage to transform. - * @param {Number} y The y position on the stage to transform. - * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. - * @return {Point} A Point instance with x and y properties correlating to the transformed position in the - * display object's coordinate space. - **/ - p.globalToLocal = function(x, y, pt) { - return this.getConcatenatedMatrix(this._props.matrix).invert().transformPoint(x,y, pt||new createjs.Point()); - }; - - /** - * Transforms the specified x and y position from the coordinate space of this display object to the coordinate - * space of the target display object. Returns a Point instance with x and y properties correlating to the - * transformed position in the target's coordinate space. Effectively the same as using the following code with - * {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}} and {{#crossLink "DisplayObject/globalToLocal"}}{{/crossLink}}. - * - * var pt = this.localToGlobal(x, y); - * pt = target.globalToLocal(pt.x, pt.y); - * - * @method localToLocal - * @param {Number} x The x position in the source display object to transform. - * @param {Number} y The y position on the source display object to transform. - * @param {DisplayObject} target The target display object to which the coordinates will be transformed. - * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. - * @return {Point} Returns a Point instance with x and y properties correlating to the transformed position - * in the target's coordinate space. - **/ - p.localToLocal = function(x, y, target, pt) { - pt = this.localToGlobal(x, y, pt); - return target.globalToLocal(pt.x, pt.y, pt); - }; - - /** - * Shortcut method to quickly set the transform properties on the display object. All parameters are optional. - * Omitted parameters will have the default value set. - * - *

Example

- * - * displayObject.setTransform(100, 100, 2, 2); - * - * @method setTransform - * @param {Number} [x=0] The horizontal translation (x position) in pixels - * @param {Number} [y=0] The vertical translation (y position) in pixels - * @param {Number} [scaleX=1] The horizontal scale, as a percentage of 1 - * @param {Number} [scaleY=1] the vertical scale, as a percentage of 1 - * @param {Number} [rotation=0] The rotation, in degrees - * @param {Number} [skewX=0] The horizontal skew factor - * @param {Number} [skewY=0] The vertical skew factor - * @param {Number} [regX=0] The horizontal registration point in pixels - * @param {Number} [regY=0] The vertical registration point in pixels - * @return {DisplayObject} Returns this instance. Useful for chaining commands. - * @chainable - */ - p.setTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) { - this.x = x || 0; - this.y = y || 0; - this.scaleX = scaleX == null ? 1 : scaleX; - this.scaleY = scaleY == null ? 1 : scaleY; - this.rotation = rotation || 0; - this.skewX = skewX || 0; - this.skewY = skewY || 0; - this.regX = regX || 0; - this.regY = regY || 0; - return this; - }; - - /** - * Returns a matrix based on this object's current transform. - * @method getMatrix - * @param {Matrix2D} matrix Optional. A Matrix2D object to populate with the calculated values. If null, a new - * Matrix object is returned. - * @return {Matrix2D} A matrix representing this display object's transform. - **/ - p.getMatrix = function(matrix) { - var o = this, mtx = matrix&&matrix.identity() || new createjs.Matrix2D(); - return o.transformMatrix ? mtx.copy(o.transformMatrix) : mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY); - }; - - /** - * Generates a Matrix2D object representing the combined transform of the display object and all of its - * parent Containers up to the highest level ancestor (usually the {{#crossLink "Stage"}}{{/crossLink}}). This can - * be used to transform positions between coordinate spaces, such as with {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}} - * and {{#crossLink "DisplayObject/globalToLocal"}}{{/crossLink}}. - * @method getConcatenatedMatrix - * @param {Matrix2D} [matrix] A {{#crossLink "Matrix2D"}}{{/crossLink}} object to populate with the calculated values. - * If null, a new Matrix2D object is returned. - * @return {Matrix2D} The combined matrix. - **/ - p.getConcatenatedMatrix = function(matrix) { - var o = this, mtx = this.getMatrix(matrix); - while (o = o.parent) { - mtx.prependMatrix(o.getMatrix(o._props.matrix)); - } - return mtx; - }; - - /** - * Generates a DisplayProps object representing the combined display properties of the object and all of its - * parent Containers up to the highest level ancestor (usually the {{#crossLink "Stage"}}{{/crossLink}}). - * @method getConcatenatedDisplayProps - * @param {DisplayProps} [props] A {{#crossLink "DisplayProps"}}{{/crossLink}} object to populate with the calculated values. - * If null, a new DisplayProps object is returned. - * @return {DisplayProps} The combined display properties. - **/ - p.getConcatenatedDisplayProps = function(props) { - props = props ? props.identity() : new createjs.DisplayProps(); - var o = this, mtx = o.getMatrix(props.matrix); - do { - props.prepend(o.visible, o.alpha, o.shadow, o.compositeOperation); - - // we do this to avoid problems with the matrix being used for both operations when o._props.matrix is passed in as the props param. - // this could be simplified (ie. just done as part of the prepend above) if we switched to using a pool. - if (o != this) { mtx.prependMatrix(o.getMatrix(o._props.matrix)); } - } while (o = o.parent); - return props; - }; - - /** - * Tests whether the display object intersects the specified point in local coordinates (ie. draws a pixel - * with alpha > 0 at the specified position). This ignores the alpha, shadow, hitArea, mask, and compositeOperation - * of the display object. - * - *

Example

- * - * var myShape = new createjs.Shape(); - * myShape.graphics.beginFill("red").drawRect(100, 100, 20, 50); - * - * console.log(myShape.hitTest(10,10); // false - * console.log(myShape.hitTest(110, 25); // true - * - * Note that to use Stage coordinates (such as {{#crossLink "Stage/mouseX:property"}}{{/crossLink}}), they must - * first be converted to local coordinates: - * - * stage.addEventListener("stagemousedown", handleMouseDown); - * function handleMouseDown(event) { - * var p = myShape.globalToLocal(stage.mouseX, stage.mouseY); - * var hit = myShape.hitTest(p.x, p.y); - * } - * - * Shape-to-shape collision is not currently supported by EaselJS. - * - * @method hitTest - * @param {Number} x The x position to check in the display object's local coordinates. - * @param {Number} y The y position to check in the display object's local coordinates. - * @return {Boolean} A Boolean indicating whether a visible portion of the DisplayObject intersect the specified - * local Point. - */ - p.hitTest = function(x, y) { - var ctx = DisplayObject._hitTestContext; - ctx.setTransform(1, 0, 0, 1, -x, -y); - this.draw(ctx); - - var hit = this._testHit(ctx); - ctx.setTransform(1, 0, 0, 1, 0, 0); - ctx.clearRect(0, 0, 2, 2); - return hit; - }; - - /** - * Provides a chainable shortcut method for setting a number of properties on the instance. - * - *

Example

- * - * var myGraphics = new createjs.Graphics().beginFill("#ff0000").drawCircle(0, 0, 25); - * var shape = stage.addChild(new createjs.Shape()).set({graphics:myGraphics, x:100, y:100, alpha:0.5}); - * - * @method set - * @param {Object} props A generic object containing properties to copy to the DisplayObject instance. - * @return {DisplayObject} 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 rectangle representing this object's bounds in its local coordinate system (ie. with no transformation). - * Objects that have been cached will return the bounds of the cache. - * - * Not all display objects can calculate their own bounds (ex. Shape). For these objects, you can use - * {{#crossLink "DisplayObject/setBounds"}}{{/crossLink}} so that they are included when calculating Container - * bounds. - * - * - * - * - * - * - * - * - * - *
All - * All display objects support setting bounds manually using setBounds(). Likewise, display objects that - * have been cached using cache() will return the bounds of their cache. Manual and cache bounds will override - * the automatic calculations listed below. - *
Bitmap - * Returns the width and height of the sourceRect (if specified) or image, extending from (x=0,y=0). - *
Sprite - * Returns the bounds of the current frame. May have non-zero x/y if a frame registration point was specified - * in the spritesheet data. See also {{#crossLink "SpriteSheet/getFrameBounds"}}{{/crossLink}} - *
Container - * Returns the aggregate (combined) bounds of all children that return a non-null value from getBounds(). - *
Shape - * Does not currently support automatic bounds calculations. Use setBounds() to manually define bounds. - *
Text - * Returns approximate bounds. Horizontal values (x/width) are quite accurate, but vertical values (y/height) are - * not, especially when using textBaseline values other than "top". - *
BitmapText - * Returns approximate bounds. Values will be more accurate if spritesheet frame registration points are close - * to (x=0,y=0). - *
- * - * Bounds can be expensive to calculate for some objects (ex. text, or containers with many children), and - * are recalculated each time you call getBounds(). You can prevent recalculation on static objects by setting the - * bounds explicitly: - * - * var bounds = obj.getBounds(); - * obj.setBounds(bounds.x, bounds.y, bounds.width, bounds.height); - * // getBounds will now use the set values, instead of recalculating - * - * To reduce memory impact, the returned Rectangle instance may be reused internally; clone the instance or copy its - * values if you need to retain it. - * - * var myBounds = obj.getBounds().clone(); - * // OR: - * myRect.copy(obj.getBounds()); - * - * @method getBounds - * @return {Rectangle} A Rectangle instance representing the bounds, or null if bounds are not available for this - * object. - **/ - p.getBounds = function() { - if (this._bounds) { return this._rectangle.copy(this._bounds); } - var cacheCanvas = this.cacheCanvas; - if (cacheCanvas) { - var scale = this._cacheScale; - return this._rectangle.setValues(this._cacheOffsetX, this._cacheOffsetY, cacheCanvas.width/scale, cacheCanvas.height/scale); - } - return null; - }; - - /** - * Returns a rectangle representing this object's bounds in its parent's coordinate system (ie. with transformations applied). - * Objects that have been cached will return the transformed bounds of the cache. - * - * Not all display objects can calculate their own bounds (ex. Shape). For these objects, you can use - * {{#crossLink "DisplayObject/setBounds"}}{{/crossLink}} so that they are included when calculating Container - * bounds. - * - * To reduce memory impact, the returned Rectangle instance may be reused internally; clone the instance or copy its - * values if you need to retain it. - * - * Container instances calculate aggregate bounds for all children that return bounds via getBounds. - * @method getTransformedBounds - * @return {Rectangle} A Rectangle instance representing the bounds, or null if bounds are not available for this object. - **/ - p.getTransformedBounds = function() { - return this._getBounds(); - }; - - /** - * Allows you to manually specify the bounds of an object that either cannot calculate their own bounds (ex. Shape & - * Text) for future reference, or so the object can be included in Container bounds. Manually set bounds will always - * override calculated bounds. - * - * The bounds should be specified in the object's local (untransformed) coordinates. For example, a Shape instance - * with a 25px radius circle centered at 0,0 would have bounds of (-25, -25, 50, 50). - * @method setBounds - * @param {Number} x The x origin of the bounds. Pass null to remove the manual bounds. - * @param {Number} y The y origin of the bounds. - * @param {Number} width The width of the bounds. - * @param {Number} height The height of the bounds. - **/ - p.setBounds = function(x, y, width, height) { - if (x == null) { this._bounds = x; } - this._bounds = (this._bounds || new createjs.Rectangle()).setValues(x, y, width, height); - }; - - /** - * Returns a clone of this DisplayObject. Some properties that are specific to this instance's current context are - * reverted to their defaults (for example .parent). Caches are not maintained across clones, and some elements - * are copied by reference (masks, individual filter instances, hit area) - * @method clone - * @return {DisplayObject} A clone of the current DisplayObject instance. - **/ - p.clone = function() { - return this._cloneProps(new DisplayObject()); - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[DisplayObject (name="+ this.name +")]"; - }; - - -// private methods: - // separated so it can be used more easily in subclasses: - /** - * @method _cloneProps - * @param {DisplayObject} o The DisplayObject instance which will have properties from the current DisplayObject - * instance copied into. - * @return {DisplayObject} o - * @protected - **/ - p._cloneProps = function(o) { - o.alpha = this.alpha; - o.mouseEnabled = this.mouseEnabled; - o.tickEnabled = this.tickEnabled; - o.name = this.name; - o.regX = this.regX; - o.regY = this.regY; - o.rotation = this.rotation; - o.scaleX = this.scaleX; - o.scaleY = this.scaleY; - o.shadow = this.shadow; - o.skewX = this.skewX; - o.skewY = this.skewY; - o.visible = this.visible; - o.x = this.x; - o.y = this.y; - o.compositeOperation = this.compositeOperation; - o.snapToPixel = this.snapToPixel; - o.filters = this.filters==null?null:this.filters.slice(0); - o.mask = this.mask; - o.hitArea = this.hitArea; - o.cursor = this.cursor; - o._bounds = this._bounds; - return o; - }; - - /** - * @method _applyShadow - * @protected - * @param {CanvasRenderingContext2D} ctx - * @param {Shadow} shadow - **/ - p._applyShadow = function(ctx, shadow) { - shadow = shadow || Shadow.identity; - ctx.shadowColor = shadow.color; - ctx.shadowOffsetX = shadow.offsetX; - ctx.shadowOffsetY = shadow.offsetY; - ctx.shadowBlur = shadow.blur; - }; - - - /** - * @method _tick - * @param {Object} evtObj An event object that will be dispatched to all tick listeners. This object is reused between dispatchers to reduce construction & GC costs. - * @protected - **/ - p._tick = function(evtObj) { - // because tick can be really performance sensitive, check for listeners before calling dispatchEvent. - var ls = this._listeners; - if (ls && ls["tick"]) { - // reset & reuse the event object to avoid construction / GC costs: - evtObj.target = null; - evtObj.propagationStopped = evtObj.immediatePropagationStopped = false; - this.dispatchEvent(evtObj); - } - }; - - /** - * @method _testHit - * @protected - * @param {CanvasRenderingContext2D} ctx - * @return {Boolean} - **/ - p._testHit = function(ctx) { - try { - var hit = ctx.getImageData(0, 0, 1, 1).data[3] > 1; - } catch (e) { - if (!DisplayObject.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 hit; - }; - - /** - * @method _applyFilters - * @protected - **/ - p._applyFilters = function() { - if (!this.filters || this.filters.length == 0 || !this.cacheCanvas) { return; } - var l = this.filters.length; - var ctx = this.cacheCanvas.getContext("2d"); - var w = this.cacheCanvas.width; - var h = this.cacheCanvas.height; - for (var i=0; i maxX) { maxX = x; } - if ((x = x_a + y_c + tx) < minX) { minX = x; } else if (x > maxX) { maxX = x; } - if ((x = y_c + tx) < minX) { minX = x; } else if (x > maxX) { maxX = x; } - - if ((y = x_b + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; } - if ((y = x_b + y_d + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; } - if ((y = y_d + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; } - - return bounds.setValues(minX, minY, maxX-minX, maxY-minY); - }; - - /** - * Indicates whether the display object has any mouse event listeners or a cursor. - * @method _isMouseOpaque - * @return {Boolean} - * @protected - **/ - p._hasMouseEventListener = function() { - var evts = DisplayObject._MOUSE_EVENTS; - for (var i= 0, l=evts.length; itransform and alpha properties concatenated with their parent - * Container. - * - * For example, a {{#crossLink "Shape"}}{{/crossLink}} with x=100 and alpha=0.5, placed in a Container with x=50 - * and alpha=0.7 will be rendered to the canvas at x=150 and alpha=0.35. - * Containers have some overhead, so you generally shouldn't create a Container to hold a single child. - * - *

Example

- * - * var container = new createjs.Container(); - * container.addChild(bitmapInstance, shapeInstance); - * container.x = 100; - * - * @class Container - * @extends DisplayObject - * @constructor - **/ - function Container() { - this.DisplayObject_constructor(); - - // public properties: - /** - * The array of children in the display list. You should usually use the child management methods such as - * {{#crossLink "Container/addChild"}}{{/crossLink}}, {{#crossLink "Container/removeChild"}}{{/crossLink}}, - * {{#crossLink "Container/swapChildren"}}{{/crossLink}}, etc, rather than accessing this directly, but it is - * included for advanced uses. - * @property children - * @type Array - * @default null - **/ - this.children = []; - - /** - * Indicates whether the children of this container are independently enabled for mouse/pointer interaction. - * If false, the children will be aggregated under the container - for example, a click on a child shape would - * trigger a click event on the container. - * @property mouseChildren - * @type Boolean - * @default true - **/ - this.mouseChildren = true; - - /** - * If false, the tick will not be propagated to children of this Container. This can provide some performance benefits. - * In addition to preventing the "tick" event from being dispatched, it will also prevent tick related updates - * on some display objects (ex. Sprite & MovieClip frame advancing, DOMElement visibility handling). - * @property tickChildren - * @type Boolean - * @default true - **/ - this.tickChildren = true; - } - var p = createjs.extend(Container, createjs.DisplayObject); - - -// getter / setters: - /** - * Use the {{#crossLink "Container/numChildren:property"}}{{/crossLink}} property instead. - * @method getNumChildren - * @return {Number} - * @deprecated - **/ - p.getNumChildren = function() { - return this.children.length; - }; - - /** - * Returns the number of children in the container. - * @property numChildren - * @type {Number} - * @readonly - **/ - try { - Object.defineProperties(p, { - numChildren: { get: p.getNumChildren } - }); - } catch (e) {} - - -// public methods: - /** - * Constructor alias for backwards compatibility. This method will be removed in future versions. - * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}. - * @method initialize - * @deprecated in favour of `createjs.promote()` - **/ - p.initialize = Container; // TODO: deprecated. - - /** - * Returns true or false indicating whether the display object would be visible if drawn to a canvas. - * This does not account for whether it would be visible within the boundaries of the stage. - * - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method isVisible - * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas - **/ - p.isVisible = function() { - var hasContent = this.cacheCanvas || this.children.length; - return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); - }; - - /** - * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. - * Returns true if the draw was handled (useful for overriding functionality). - * - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method draw - * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. - * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. - * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back - * into itself). - **/ - p.draw = function(ctx, ignoreCache) { - if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } - - // this ensures we don't have issues with display list changes that occur during a draw: - var list = this.children.slice(); - for (var i=0,l=list.length; iExample - * - * container.addChild(bitmapInstance); - * - * You can also add multiple children at once: - * - * container.addChild(bitmapInstance, shapeInstance, textInstance); - * - * @method addChild - * @param {DisplayObject} child The display object to add. - * @return {DisplayObject} The child that was added, or the last child if multiple children were added. - **/ - p.addChild = function(child) { - if (child == null) { return child; } - var l = arguments.length; - if (l > 1) { - for (var i=0; iExample - * - * addChildAt(child1, index); - * - * You can also add multiple children, such as: - * - * addChildAt(child1, child2, ..., index); - * - * The index must be between 0 and numChildren. For example, to add myShape under otherShape in the display list, - * you could use: - * - * container.addChildAt(myShape, container.getChildIndex(otherShape)); - * - * This would also bump otherShape's index up by one. Fails silently if the index is out of range. - * - * @method addChildAt - * @param {DisplayObject} child The display object to add. - * @param {Number} index The index to add the child at. - * @return {DisplayObject} Returns the last child that was added, or the last child if multiple children were added. - **/ - p.addChildAt = function(child, index) { - var l = arguments.length; - var indx = arguments[l-1]; // can't use the same name as the index param or it replaces arguments[1] - if (indx < 0 || indx > this.children.length) { return arguments[l-2]; } - if (l > 2) { - for (var i=0; iExample - * - * container.removeChild(child); - * - * You can also remove multiple children: - * - * removeChild(child1, child2, ...); - * - * Returns true if the child (or children) was removed, or false if it was not in the display list. - * @method removeChild - * @param {DisplayObject} child The child to remove. - * @return {Boolean} true if the child (or children) was removed, or false if it was not in the display list. - **/ - p.removeChild = function(child) { - var l = arguments.length; - if (l > 1) { - var good = true; - for (var i=0; iExample - * - * container.removeChildAt(2); - * - * You can also remove multiple children: - * - * container.removeChild(2, 7, ...) - * - * Returns true if the child (or children) was removed, or false if any index was out of range. - * @method removeChildAt - * @param {Number} index The index of the child to remove. - * @return {Boolean} true if the child (or children) was removed, or false if any index was out of range. - **/ - p.removeChildAt = function(index) { - var l = arguments.length; - if (l > 1) { - var a = []; - for (var i=0; i this.children.length-1) { return false; } - var child = this.children[index]; - if (child) { child.parent = null; } - this.children.splice(index, 1); - child.dispatchEvent("removed"); - return true; - }; - - /** - * Removes all children from the display list. - * - *

Example

- * - * container.removeAllChildren(); - * - * @method removeAllChildren - **/ - p.removeAllChildren = function() { - var kids = this.children; - while (kids.length) { this.removeChildAt(0); } - }; - - /** - * Returns the child at the specified index. - * - *

Example

- * - * container.getChildAt(2); - * - * @method getChildAt - * @param {Number} index The index of the child to return. - * @return {DisplayObject} The child at the specified index. Returns null if there is no child at the index. - **/ - p.getChildAt = function(index) { - return this.children[index]; - }; - - /** - * Returns the child with the specified name. - * @method getChildByName - * @param {String} name The name of the child to return. - * @return {DisplayObject} The child with the specified name. - **/ - p.getChildByName = function(name) { - var kids = this.children; - for (var i=0,l=kids.length;iExample: Display children with a higher y in front. - * - * var sortFunction = function(obj1, obj2, options) { - * if (obj1.y > obj2.y) { return 1; } - * if (obj1.y < obj2.y) { return -1; } - * return 0; - * } - * container.sortChildren(sortFunction); - * - * @method sortChildren - * @param {Function} sortFunction the function to use to sort the child list. See JavaScript's Array.sort - * documentation for details. - **/ - p.sortChildren = function(sortFunction) { - this.children.sort(sortFunction); - }; - - /** - * Returns the index of the specified child in the display list, or -1 if it is not in the display list. - * - *

Example

- * - * var index = container.getChildIndex(child); - * - * @method getChildIndex - * @param {DisplayObject} child The child to return the index of. - * @return {Number} The index of the specified child. -1 if the child is not found. - **/ - p.getChildIndex = function(child) { - return createjs.indexOf(this.children, child); - }; - - /** - * Swaps the children at the specified indexes. Fails silently if either index is out of range. - * @method swapChildrenAt - * @param {Number} index1 - * @param {Number} index2 - **/ - p.swapChildrenAt = function(index1, index2) { - var kids = this.children; - var o1 = kids[index1]; - var o2 = kids[index2]; - if (!o1 || !o2) { return; } - kids[index1] = o2; - kids[index2] = o1; - }; - - /** - * Swaps the specified children's depth in the display list. Fails silently if either child is not a child of this - * Container. - * @method swapChildren - * @param {DisplayObject} child1 - * @param {DisplayObject} child2 - **/ - p.swapChildren = function(child1, child2) { - var kids = this.children; - var index1,index2; - for (var i=0,l=kids.length;i= l) { return; } - for (var i=0;i 0 at the - * specified position). This ignores the alpha, shadow and compositeOperation of the display object, and all - * transform properties including regX/Y. - * @method hitTest - * @param {Number} x The x position to check in the display object's local coordinates. - * @param {Number} y The y position to check in the display object's local coordinates. - * @return {Boolean} A Boolean indicating whether there is a visible section of a DisplayObject that overlaps the specified - * coordinates. - **/ - p.hitTest = function(x, y) { - // TODO: optimize to use the fast cache check where possible. - return (this.getObjectUnderPoint(x, y) != null); - }; - - /** - * Returns an array of all display objects under the specified coordinates that are in this container's display - * list. This routine ignores any display objects with {{#crossLink "DisplayObject/mouseEnabled:property"}}{{/crossLink}} - * set to `false`. The array will be sorted in order of visual depth, with the top-most display object at index 0. - * This uses shape based hit detection, and can be an expensive operation to run, so it is best to use it carefully. - * For example, if testing for objects under the mouse, test on tick (instead of on {{#crossLink "DisplayObject/mousemove:event"}}{{/crossLink}}), - * and only if the mouse's position has changed. - * - *
    - *
  • By default (mode=0) this method evaluates all display objects.
  • - *
  • By setting the `mode` parameter to `1`, the {{#crossLink "DisplayObject/mouseEnabled:property"}}{{/crossLink}} - * and {{#crossLink "mouseChildren:property"}}{{/crossLink}} properties will be respected.
  • - *
  • Setting the `mode` to `2` additionally excludes display objects that do not have active mouse event - * listeners or a {{#crossLink "DisplayObject:cursor:property"}}{{/crossLink}} property. That is, only objects - * that would normally intercept mouse interaction will be included. This can significantly improve performance - * in some cases by reducing the number of display objects that need to be tested.
  • - * - * - * This method accounts for both {{#crossLink "DisplayObject/hitArea:property"}}{{/crossLink}} and {{#crossLink "DisplayObject/mask:property"}}{{/crossLink}}. - * @method getObjectsUnderPoint - * @param {Number} x The x position in the container to test. - * @param {Number} y The y position in the container to test. - * @param {Number} [mode=0] The mode to use to determine which display objects to include. 0-all, 1-respect mouseEnabled/mouseChildren, 2-only mouse opaque objects. - * @return {Array} An Array of DisplayObjects under the specified coordinates. - **/ - p.getObjectsUnderPoint = function(x, y, mode) { - var arr = []; - var pt = this.localToGlobal(x, y); - this._getObjectsUnderPoint(pt.x, pt.y, arr, mode>0, mode==1); - return arr; - }; - - /** - * Similar to {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}}, but returns only the top-most display - * object. This runs significantly faster than getObjectsUnderPoint(), but is still potentially an expensive - * operation. See {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}} for more information. - * @method getObjectUnderPoint - * @param {Number} x The x position in the container to test. - * @param {Number} y The y position in the container to test. - * @param {Number} mode The mode to use to determine which display objects to include. 0-all, 1-respect mouseEnabled/mouseChildren, 2-only mouse opaque objects. - * @return {DisplayObject} The top-most display object under the specified coordinates. - **/ - p.getObjectUnderPoint = function(x, y, mode) { - var pt = this.localToGlobal(x, y); - return this._getObjectsUnderPoint(pt.x, pt.y, null, mode>0, mode==1); - }; - - /** - * Docced in superclass. - */ - p.getBounds = function() { - return this._getBounds(null, true); - }; - - - /** - * Docced in superclass. - */ - p.getTransformedBounds = function() { - return this._getBounds(); - }; - - /** - * Returns a clone of this Container. Some properties that are specific to this instance's current context are - * reverted to their defaults (for example .parent). - * @method clone - * @param {Boolean} [recursive=false] If true, all of the descendants of this container will be cloned recursively. If false, the - * properties of the container will be cloned, but the new instance will not have any children. - * @return {Container} A clone of the current Container instance. - **/ - p.clone = function(recursive) { - var o = this._cloneProps(new Container()); - if (recursive) { this._cloneChildren(o); } - return o; - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Container (name="+ this.name +")]"; - }; - - -// private methods: - /** - * @method _tick - * @param {Object} evtObj An event object that will be dispatched to all tick listeners. This object is reused between dispatchers to reduce construction & GC costs. - * @protected - **/ - p._tick = function(evtObj) { - if (this.tickChildren) { - for (var i=this.children.length-1; i>=0; i--) { - var child = this.children[i]; - if (child.tickEnabled && child._tick) { child._tick(evtObj); } - } - } - this.DisplayObject__tick(evtObj); - }; - - /** - * Recursively clones all children of this container, and adds them to the target container. - * @method cloneChildren - * @protected - * @param {Container} o The target container. - **/ - p._cloneChildren = function(o) { - if (o.children.length) { o.removeAllChildren(); } - var arr = o.children; - for (var i=0, l=this.children.length; i=0; i--) { - var child = children[i]; - var hitArea = child.hitArea; - if (!child.visible || (!hitArea && !child.isVisible()) || (mouse && !child.mouseEnabled)) { continue; } - if (!hitArea && !this._testMask(child, x, y)) { continue; } - - // if a child container has a hitArea then we only need to check its hitArea, so we can treat it as a normal DO: - if (!hitArea && child instanceof Container) { - var result = child._getObjectsUnderPoint(x, y, arr, mouse, activeListener, currentDepth+1); - if (!arr && result) { return (mouse && !this.mouseChildren) ? this : result; } - } else { - if (mouse && !activeListener && !child._hasMouseEventListener()) { continue; } - - // TODO: can we pass displayProps forward, to avoid having to calculate this backwards every time? It's kind of a mixed bag. When we're only hunting for DOs with event listeners, it may not make sense. - var props = child.getConcatenatedDisplayProps(child._props); - mtx = props.matrix; - - if (hitArea) { - mtx.appendMatrix(hitArea.getMatrix(hitArea._props.matrix)); - props.alpha = hitArea.alpha; - } - - ctx.globalAlpha = props.alpha; - ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx-x, mtx.ty-y); - (hitArea||child).draw(ctx); - if (!this._testHit(ctx)) { continue; } - ctx.setTransform(1, 0, 0, 1, 0, 0); - ctx.clearRect(0, 0, 2, 2); - if (arr) { arr.push(child); } - else { return (mouse && !this.mouseChildren) ? this : child; } - } - } - return null; - }; - - /** - * @method _testMask - * @param {DisplayObject} target - * @param {Number} x - * @param {Number} y - * @return {Boolean} Indicates whether the x/y is within the masked region. - * @protected - **/ - p._testMask = function(target, x, y) { - var mask = target.mask; - if (!mask || !mask.graphics || mask.graphics.isEmpty()) { return true; } - - var mtx = this._props.matrix, parent = target.parent; - mtx = parent ? parent.getConcatenatedMatrix(mtx) : mtx.identity(); - mtx = mask.getMatrix(mask._props.matrix).prependMatrix(mtx); - - var ctx = createjs.DisplayObject._hitTestContext; - ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx-x, mtx.ty-y); - - // draw the mask as a solid fill: - mask.graphics.drawAsPath(ctx); - ctx.fillStyle = "#000"; - ctx.fill(); - - if (!this._testHit(ctx)) { return false; } - ctx.setTransform(1, 0, 0, 1, 0, 0); - ctx.clearRect(0, 0, 2, 2); - - return true; - }; - - /** - * @method _getBounds - * @param {Matrix2D} matrix - * @param {Boolean} ignoreTransform If true, does not apply this object's transform. - * @return {Rectangle} - * @protected - **/ - p._getBounds = function(matrix, ignoreTransform) { - var bounds = this.DisplayObject_getBounds(); - if (bounds) { return this._transformBounds(bounds, matrix, ignoreTransform); } - - var mtx = this._props.matrix; - mtx = ignoreTransform ? mtx.identity() : this.getMatrix(mtx); - if (matrix) { mtx.prependMatrix(matrix); } - - var l = this.children.length, rect=null; - for (var i=0; iExample - * This example creates a stage, adds a child to it, then uses {{#crossLink "Ticker"}}{{/crossLink}} to update the child - * and redraw the stage using {{#crossLink "Stage/update"}}{{/crossLink}}. - * - * var stage = new createjs.Stage("canvasElementId"); - * var image = new createjs.Bitmap("imagePath.png"); - * stage.addChild(image); - * createjs.Ticker.addEventListener("tick", handleTick); - * function handleTick(event) { - * image.x += 10; - * stage.update(); - * } - * - * @class Stage - * @extends Container - * @constructor - * @param {HTMLCanvasElement | String | Object} canvas A canvas object that the Stage will render to, or the string id - * of a canvas object in the current document. - **/ - function Stage(canvas) { - this.Container_constructor(); - - - // public properties: - /** - * Indicates whether the stage should automatically clear the canvas before each render. You can set this to false - * to manually control clearing (for generative art, or when pointing multiple stages at the same canvas for - * example). - * - *

    Example

    - * - * var stage = new createjs.Stage("canvasId"); - * stage.autoClear = false; - * - * @property autoClear - * @type Boolean - * @default true - **/ - this.autoClear = true; - - /** - * The canvas the stage will render to. Multiple stages can share a single canvas, but you must disable autoClear for all but the - * first stage that will be ticked (or they will clear each other's render). - * - * When changing the canvas property you must disable the events on the old canvas, and enable events on the - * new canvas or mouse events will not work as expected. For example: - * - * myStage.enableDOMEvents(false); - * myStage.canvas = anotherCanvas; - * myStage.enableDOMEvents(true); - * - * @property canvas - * @type HTMLCanvasElement | Object - **/ - this.canvas = (typeof canvas == "string") ? document.getElementById(canvas) : canvas; - - /** - * The current mouse X position on the canvas. If the mouse leaves the canvas, this will indicate the most recent - * position over the canvas, and mouseInBounds will be set to false. - * @property mouseX - * @type Number - * @readonly - **/ - this.mouseX = 0; - - /** - * The current mouse Y position on the canvas. If the mouse leaves the canvas, this will indicate the most recent - * position over the canvas, and mouseInBounds will be set to false. - * @property mouseY - * @type Number - * @readonly - **/ - this.mouseY = 0; - - /** - * Specifies the area of the stage to affect when calling update. This can be use to selectively - * re-draw specific regions of the canvas. If null, the whole canvas area is drawn. - * @property drawRect - * @type {Rectangle} - */ - this.drawRect = null; - - /** - * Indicates whether display objects should be rendered on whole pixels. You can set the - * {{#crossLink "DisplayObject/snapToPixel"}}{{/crossLink}} property of - * display objects to false to enable/disable this behaviour on a per instance basis. - * @property snapToPixelEnabled - * @type Boolean - * @default false - **/ - this.snapToPixelEnabled = false; - - /** - * Indicates whether the mouse is currently within the bounds of the canvas. - * @property mouseInBounds - * @type Boolean - * @default false - **/ - this.mouseInBounds = false; - - /** - * If true, tick callbacks will be called on all display objects on the stage prior to rendering to the canvas. - * @property tickOnUpdate - * @type Boolean - * @default true - **/ - this.tickOnUpdate = true; - - /** - * If true, mouse move events will continue to be called when the mouse leaves the target canvas. See - * {{#crossLink "Stage/mouseInBounds:property"}}{{/crossLink}}, and {{#crossLink "MouseEvent"}}{{/crossLink}} - * x/y/rawX/rawY. - * @property mouseMoveOutside - * @type Boolean - * @default false - **/ - this.mouseMoveOutside = false; - - - /** - * Prevents selection of other elements in the html page if the user clicks and drags, or double clicks on the canvas. - * This works by calling `preventDefault()` on any mousedown events (or touch equivalent) originating on the canvas. - * @property preventSelection - * @type Boolean - * @default true - **/ - this.preventSelection = true; - - /** - * The hitArea property is not supported for Stage. - * @property hitArea - * @type {DisplayObject} - * @default null - */ - - - // private properties: - /** - * Holds objects with data for each active pointer id. Each object has the following properties: - * x, y, event, target, overTarget, overX, overY, inBounds, posEvtObj (native event that last updated position) - * @property _pointerData - * @type {Object} - * @private - */ - this._pointerData = {}; - - /** - * Number of active pointers. - * @property _pointerCount - * @type {Object} - * @private - */ - this._pointerCount = 0; - - /** - * The ID of the primary pointer. - * @property _primaryPointerID - * @type {Object} - * @private - */ - this._primaryPointerID = null; - - /** - * @property _mouseOverIntervalID - * @protected - * @type Number - **/ - this._mouseOverIntervalID = null; - - /** - * @property _nextStage - * @protected - * @type Stage - **/ - this._nextStage = null; - - /** - * @property _prevStage - * @protected - * @type Stage - **/ - this._prevStage = null; - - - // initialize: - this.enableDOMEvents(true); - } - var p = createjs.extend(Stage, createjs.Container); - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// events: - /** - * Dispatched when the user moves the mouse over the canvas. - * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. - * @event stagemousemove - * @since 0.6.0 - */ - - /** - * Dispatched when the user presses their left mouse button on the canvas. See the {{#crossLink "MouseEvent"}}{{/crossLink}} - * class for a listing of event properties. - * @event stagemousedown - * @since 0.6.0 - */ - - /** - * Dispatched when the user the user presses somewhere on the stage, then releases the mouse button anywhere that the page can detect it (this varies slightly between browsers). - * You can use {{#crossLink "Stage/mouseInBounds:property"}}{{/crossLink}} to check whether the mouse is currently within the stage bounds. - * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. - * @event stagemouseup - * @since 0.6.0 - */ - - /** - * Dispatched when the mouse moves from within the canvas area (mouseInBounds == true) to outside it (mouseInBounds == false). - * This is currently only dispatched for mouse input (not touch). See the {{#crossLink "MouseEvent"}}{{/crossLink}} - * class for a listing of event properties. - * @event mouseleave - * @since 0.7.0 - */ - - /** - * Dispatched when the mouse moves into the canvas area (mouseInBounds == false) from outside it (mouseInBounds == true). - * This is currently only dispatched for mouse input (not touch). See the {{#crossLink "MouseEvent"}}{{/crossLink}} - * class for a listing of event properties. - * @event mouseenter - * @since 0.7.0 - */ - - /** - * Dispatched each update immediately before the tick event is propagated through the display list. - * You can call preventDefault on the event object to cancel propagating the tick event. - * @event tickstart - * @since 0.7.0 - */ - - /** - * Dispatched each update immediately after the tick event is propagated through the display list. Does not fire if - * tickOnUpdate is false. Precedes the "drawstart" event. - * @event tickend - * @since 0.7.0 - */ - - /** - * Dispatched each update immediately before the canvas is cleared and the display list is drawn to it. - * You can call preventDefault on the event object to cancel the draw. - * @event drawstart - * @since 0.7.0 - */ - - /** - * Dispatched each update immediately after the display list is drawn to the canvas and the canvas context is restored. - * @event drawend - * @since 0.7.0 - */ - - -// getter / setters: - /** - * Specifies a target stage that will have mouse / touch interactions relayed to it after this stage handles them. - * This can be useful in cases where you have multiple layered canvases and want user interactions - * events to pass through. For example, this would relay mouse events from topStage to bottomStage: - * - * topStage.nextStage = bottomStage; - * - * To disable relaying, set nextStage to null. - * - * MouseOver, MouseOut, RollOver, and RollOut interactions are also passed through using the mouse over settings - * of the top-most stage, but are only processed if the target stage has mouse over interactions enabled. - * Considerations when using roll over in relay targets:
      - *
    1. The top-most (first) stage must have mouse over interactions enabled (via enableMouseOver)
    2. - *
    3. All stages that wish to participate in mouse over interaction must enable them via enableMouseOver
    4. - *
    5. All relay targets will share the frequency value of the top-most stage
    6. - *
    - * To illustrate, in this example the targetStage would process mouse over interactions at 10hz (despite passing - * 30 as it's desired frequency): - * topStage.nextStage = targetStage; - * topStage.enableMouseOver(10); - * targetStage.enableMouseOver(30); - * - * If the target stage's canvas is completely covered by this stage's canvas, you may also want to disable its - * DOM events using: - * - * targetStage.enableDOMEvents(false); - * - * @property nextStage - * @type {Stage} - **/ - p._get_nextStage = function() { - return this._nextStage; - }; - p._set_nextStage = function(value) { - if (this._nextStage) { this._nextStage._prevStage = null; } - if (value) { value._prevStage = this; } - this._nextStage = value; - }; - - try { - Object.defineProperties(p, { - nextStage: { get: p._get_nextStage, set: p._set_nextStage } - }); - } catch (e) {} // TODO: use Log - - -// public methods: - /** - * Each time the update method is called, the stage will call {{#crossLink "Stage/tick"}}{{/crossLink}} - * unless {{#crossLink "Stage/tickOnUpdate:property"}}{{/crossLink}} is set to false, - * and then render the display list to the canvas. - * - * @method update - * @param {Object} [props] Props object to pass to `tick()`. Should usually be a {{#crossLink "Ticker"}}{{/crossLink}} event object, or similar object with a delta property. - **/ - p.update = function(props) { - if (!this.canvas) { return; } - if (this.tickOnUpdate) { this.tick(props); } - if (this.dispatchEvent("drawstart", false, true) === false) { return; } - createjs.DisplayObject._snapToPixelEnabled = this.snapToPixelEnabled; - var r = this.drawRect, ctx = this.canvas.getContext("2d"); - ctx.setTransform(1, 0, 0, 1, 0, 0); - if (this.autoClear) { - if (r) { ctx.clearRect(r.x, r.y, r.width, r.height); } - else { ctx.clearRect(0, 0, this.canvas.width+1, this.canvas.height+1); } - } - ctx.save(); - if (this.drawRect) { - ctx.beginPath(); - ctx.rect(r.x, r.y, r.width, r.height); - ctx.clip(); - } - this.updateContext(ctx); - this.draw(ctx, false); - ctx.restore(); - this.dispatchEvent("drawend"); - }; - - /** - * Propagates a tick event through the display list. This is automatically called by {{#crossLink "Stage/update"}}{{/crossLink}} - * unless {{#crossLink "Stage/tickOnUpdate:property"}}{{/crossLink}} is set to false. - * - * If a props object is passed to `tick()`, then all of its properties will be copied to the event object that is - * propagated to listeners. - * - * Some time-based features in EaselJS (for example {{#crossLink "Sprite/framerate"}}{{/crossLink}} require that - * a {{#crossLink "Ticker/tick:event"}}{{/crossLink}} event object (or equivalent object with a delta property) be - * passed as the `props` parameter to `tick()`. For example: - * - * Ticker.on("tick", handleTick); - * function handleTick(evtObj) { - * // clone the event object from Ticker, and add some custom data to it: - * var evt = evtObj.clone().set({greeting:"hello", name:"world"}); - * - * // pass it to stage.update(): - * myStage.update(evt); // subsequently calls tick() with the same param - * } - * - * // ... - * myDisplayObject.on("tick", handleDisplayObjectTick); - * function handleDisplayObjectTick(evt) { - * console.log(evt.delta); // the delta property from the Ticker tick event object - * console.log(evt.greeting, evt.name); // custom data: "hello world" - * } - * - * @method tick - * @param {Object} [props] An object with properties that should be copied to the event object. Should usually be a Ticker event object, or similar object with a delta property. - **/ - p.tick = function(props) { - if (!this.tickEnabled || this.dispatchEvent("tickstart", false, true) === false) { return; } - var evtObj = new createjs.Event("tick"); - if (props) { - for (var n in props) { - if (props.hasOwnProperty(n)) { evtObj[n] = props[n]; } - } - } - this._tick(evtObj); - this.dispatchEvent("tickend"); - }; - - /** - * Default event handler that calls the Stage {{#crossLink "Stage/update"}}{{/crossLink}} method when a {{#crossLink "DisplayObject/tick:event"}}{{/crossLink}} - * event is received. This allows you to register a Stage instance as a event listener on {{#crossLink "Ticker"}}{{/crossLink}} - * directly, using: - * - * Ticker.addEventListener("tick", myStage"); - * - * Note that if you subscribe to ticks using this pattern, then the tick event object will be passed through to - * display object tick handlers, instead of delta and paused parameters. - * @property handleEvent - * @type Function - **/ - p.handleEvent = function(evt) { - if (evt.type == "tick") { this.update(evt); } - }; - - /** - * Clears the target canvas. Useful if {{#crossLink "Stage/autoClear:property"}}{{/crossLink}} is set to `false`. - * @method clear - **/ - p.clear = function() { - if (!this.canvas) { return; } - var ctx = this.canvas.getContext("2d"); - ctx.setTransform(1, 0, 0, 1, 0, 0); - ctx.clearRect(0, 0, this.canvas.width+1, this.canvas.height+1); - }; - - /** - * Returns a data url that contains a Base64-encoded image of the contents of the stage. The returned data url can - * be specified as the src value of an image element. - * @method toDataURL - * @param {String} [backgroundColor] The background color to be used for the generated image. Any valid CSS color - * value is allowed. The default value is a transparent background. - * @param {String} [mimeType="image/png"] The MIME type of the image format to be create. The default is "image/png". If an unknown MIME type - * is passed in, or if the browser does not support the specified MIME type, the default value will be used. - * @return {String} a Base64 encoded image. - **/ - p.toDataURL = function(backgroundColor, mimeType) { - var data, ctx = this.canvas.getContext('2d'), w = this.canvas.width, h = this.canvas.height; - - if (backgroundColor) { - data = ctx.getImageData(0, 0, w, h); - var compositeOperation = ctx.globalCompositeOperation; - ctx.globalCompositeOperation = "destination-over"; - - ctx.fillStyle = backgroundColor; - ctx.fillRect(0, 0, w, h); - } - - var dataURL = this.canvas.toDataURL(mimeType||"image/png"); - - if(backgroundColor) { - ctx.putImageData(data, 0, 0); - ctx.globalCompositeOperation = compositeOperation; - } - - return dataURL; - }; - - /** - * Enables or disables (by passing a frequency of 0) mouse over ({{#crossLink "DisplayObject/mouseover:event"}}{{/crossLink}} - * and {{#crossLink "DisplayObject/mouseout:event"}}{{/crossLink}}) and roll over events ({{#crossLink "DisplayObject/rollover:event"}}{{/crossLink}} - * and {{#crossLink "DisplayObject/rollout:event"}}{{/crossLink}}) for this stage's display list. These events can - * be expensive to generate, so they are disabled by default. The frequency of the events can be controlled - * independently of mouse move events via the optional `frequency` parameter. - * - *

    Example

    - * - * var stage = new createjs.Stage("canvasId"); - * stage.enableMouseOver(10); // 10 updates per second - * - * @method enableMouseOver - * @param {Number} [frequency=20] Optional param specifying the maximum number of times per second to broadcast - * mouse over/out events. Set to 0 to disable mouse over events completely. Maximum is 50. A lower frequency is less - * responsive, but uses less CPU. - **/ - p.enableMouseOver = function(frequency) { - if (this._mouseOverIntervalID) { - clearInterval(this._mouseOverIntervalID); - this._mouseOverIntervalID = null; - if (frequency == 0) { - this._testMouseOver(true); - } - } - if (frequency == null) { frequency = 20; } - else if (frequency <= 0) { return; } - var o = this; - this._mouseOverIntervalID = setInterval(function(){ o._testMouseOver(); }, 1000/Math.min(50,frequency)); - }; - - /** - * Enables or disables the event listeners that stage adds to DOM elements (window, document and canvas). It is good - * practice to disable events when disposing of a Stage instance, otherwise the stage will continue to receive - * events from the page. - * - * When changing the canvas property you must disable the events on the old canvas, and enable events on the - * new canvas or mouse events will not work as expected. For example: - * - * myStage.enableDOMEvents(false); - * myStage.canvas = anotherCanvas; - * myStage.enableDOMEvents(true); - * - * @method enableDOMEvents - * @param {Boolean} [enable=true] Indicates whether to enable or disable the events. Default is true. - **/ - p.enableDOMEvents = function(enable) { - if (enable == null) { enable = true; } - var n, o, ls = this._eventListeners; - if (!enable && ls) { - for (n in ls) { - o = ls[n]; - o.t.removeEventListener(n, o.f, false); - } - this._eventListeners = null; - } else if (enable && !ls && this.canvas) { - var t = window.addEventListener ? window : document; - var _this = this; - ls = this._eventListeners = {}; - ls["mouseup"] = {t:t, f:function(e) { _this._handleMouseUp(e)} }; - ls["mousemove"] = {t:t, f:function(e) { _this._handleMouseMove(e)} }; - ls["dblclick"] = {t:this.canvas, f:function(e) { _this._handleDoubleClick(e)} }; - ls["mousedown"] = {t:this.canvas, f:function(e) { _this._handleMouseDown(e)} }; - - for (n in ls) { - o = ls[n]; - o.t.addEventListener(n, o.f, false); - } - } - }; - - /** - * Stage instances cannot be cloned. - * @method clone - **/ - p.clone = function() { - throw("Stage cannot be cloned."); - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Stage (name="+ this.name +")]"; - }; - - -// private methods: - /** - * @method _getElementRect - * @protected - * @param {HTMLElement} e - **/ - p._getElementRect = function(e) { - var bounds; - try { bounds = e.getBoundingClientRect(); } // this can fail on disconnected DOM elements in IE9 - catch (err) { bounds = {top: e.offsetTop, left: e.offsetLeft, width:e.offsetWidth, height:e.offsetHeight}; } - - var offX = (window.pageXOffset || document.scrollLeft || 0) - (document.clientLeft || document.body.clientLeft || 0); - var offY = (window.pageYOffset || document.scrollTop || 0) - (document.clientTop || document.body.clientTop || 0); - - var styles = window.getComputedStyle ? getComputedStyle(e,null) : e.currentStyle; // IE <9 compatibility. - var padL = parseInt(styles.paddingLeft)+parseInt(styles.borderLeftWidth); - var padT = parseInt(styles.paddingTop)+parseInt(styles.borderTopWidth); - var padR = parseInt(styles.paddingRight)+parseInt(styles.borderRightWidth); - var padB = parseInt(styles.paddingBottom)+parseInt(styles.borderBottomWidth); - - // note: in some browsers bounds properties are read only. - return { - left: bounds.left+offX+padL, - right: bounds.right+offX-padR, - top: bounds.top+offY+padT, - bottom: bounds.bottom+offY-padB - } - }; - - /** - * @method _getPointerData - * @protected - * @param {Number} id - **/ - p._getPointerData = function(id) { - var data = this._pointerData[id]; - if (!data) { data = this._pointerData[id] = {x:0,y:0}; } - return data; - }; - - /** - * @method _handleMouseMove - * @protected - * @param {MouseEvent} e - **/ - p._handleMouseMove = function(e) { - if(!e){ e = window.event; } - this._handlePointerMove(-1, e, e.pageX, e.pageY); - }; - - /** - * @method _handlePointerMove - * @protected - * @param {Number} id - * @param {Event} e - * @param {Number} pageX - * @param {Number} pageY - * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage. - **/ - p._handlePointerMove = function(id, e, pageX, pageY, owner) { - if (this._prevStage && owner === undefined) { return; } // redundant listener. - if (!this.canvas) { return; } - var nextStage=this._nextStage, o=this._getPointerData(id); - - var inBounds = o.inBounds; - this._updatePointerPosition(id, e, pageX, pageY); - if (inBounds || o.inBounds || this.mouseMoveOutside) { - if (id === -1 && o.inBounds == !inBounds) { - this._dispatchMouseEvent(this, (inBounds ? "mouseleave" : "mouseenter"), false, id, o, e); - } - - this._dispatchMouseEvent(this, "stagemousemove", false, id, o, e); - this._dispatchMouseEvent(o.target, "pressmove", true, id, o, e); - } - - nextStage&&nextStage._handlePointerMove(id, e, pageX, pageY, null); - }; - - /** - * @method _updatePointerPosition - * @protected - * @param {Number} id - * @param {Event} e - * @param {Number} pageX - * @param {Number} pageY - **/ - p._updatePointerPosition = function(id, e, pageX, pageY) { - var rect = this._getElementRect(this.canvas); - pageX -= rect.left; - pageY -= rect.top; - - var w = this.canvas.width; - var h = this.canvas.height; - pageX /= (rect.right-rect.left)/w; - pageY /= (rect.bottom-rect.top)/h; - var o = this._getPointerData(id); - if (o.inBounds = (pageX >= 0 && pageY >= 0 && pageX <= w-1 && pageY <= h-1)) { - o.x = pageX; - o.y = pageY; - } else if (this.mouseMoveOutside) { - o.x = pageX < 0 ? 0 : (pageX > w-1 ? w-1 : pageX); - o.y = pageY < 0 ? 0 : (pageY > h-1 ? h-1 : pageY); - } - - o.posEvtObj = e; - o.rawX = pageX; - o.rawY = pageY; - - if (id === this._primaryPointerID || id === -1) { - this.mouseX = o.x; - this.mouseY = o.y; - this.mouseInBounds = o.inBounds; - } - }; - - /** - * @method _handleMouseUp - * @protected - * @param {MouseEvent} e - **/ - p._handleMouseUp = function(e) { - this._handlePointerUp(-1, e, false); - }; - - /** - * @method _handlePointerUp - * @protected - * @param {Number} id - * @param {Event} e - * @param {Boolean} clear - * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage. - **/ - p._handlePointerUp = function(id, e, clear, owner) { - var nextStage = this._nextStage, o = this._getPointerData(id); - if (this._prevStage && owner === undefined) { return; } // redundant listener. - - var target=null, oTarget = o.target; - if (!owner && (oTarget || nextStage)) { target = this._getObjectsUnderPoint(o.x, o.y, null, true); } - - if (o.down) { this._dispatchMouseEvent(this, "stagemouseup", false, id, o, e, target); o.down = false; } - - if (target == oTarget) { this._dispatchMouseEvent(oTarget, "click", true, id, o, e); } - this._dispatchMouseEvent(oTarget, "pressup", true, id, o, e); - - if (clear) { - if (id==this._primaryPointerID) { this._primaryPointerID = null; } - delete(this._pointerData[id]); - } else { o.target = null; } - - nextStage&&nextStage._handlePointerUp(id, e, clear, owner || target && this); - }; - - /** - * @method _handleMouseDown - * @protected - * @param {MouseEvent} e - **/ - p._handleMouseDown = function(e) { - this._handlePointerDown(-1, e, e.pageX, e.pageY); - }; - - /** - * @method _handlePointerDown - * @protected - * @param {Number} id - * @param {Event} e - * @param {Number} pageX - * @param {Number} pageY - * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage. - **/ - p._handlePointerDown = function(id, e, pageX, pageY, owner) { - if (this.preventSelection) { e.preventDefault(); } - if (this._primaryPointerID == null || id === -1) { this._primaryPointerID = id; } // mouse always takes over. - - if (pageY != null) { this._updatePointerPosition(id, e, pageX, pageY); } - var target = null, nextStage = this._nextStage, o = this._getPointerData(id); - if (!owner) { target = o.target = this._getObjectsUnderPoint(o.x, o.y, null, true); } - - if (o.inBounds) { this._dispatchMouseEvent(this, "stagemousedown", false, id, o, e, target); o.down = true; } - this._dispatchMouseEvent(target, "mousedown", true, id, o, e); - - nextStage&&nextStage._handlePointerDown(id, e, pageX, pageY, owner || target && this); - }; - - /** - * @method _testMouseOver - * @param {Boolean} clear If true, clears the mouseover / rollover (ie. no target) - * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage. - * @param {Stage} eventTarget The stage that the cursor is actively over. - * @protected - **/ - p._testMouseOver = function(clear, owner, eventTarget) { - if (this._prevStage && owner === undefined) { return; } // redundant listener. - - var nextStage = this._nextStage; - if (!this._mouseOverIntervalID) { - // not enabled for mouseover, but should still relay the event. - nextStage&&nextStage._testMouseOver(clear, owner, eventTarget); - return; - } - var o = this._getPointerData(-1); - // only update if the mouse position has changed. This provides a lot of optimization, but has some trade-offs. - if (!o || (!clear && this.mouseX == this._mouseOverX && this.mouseY == this._mouseOverY && this.mouseInBounds)) { return; } - - var e = o.posEvtObj; - var isEventTarget = eventTarget || e&&(e.target == this.canvas); - var target=null, common = -1, cursor="", t, i, l; - - if (!owner && (clear || this.mouseInBounds && isEventTarget)) { - target = this._getObjectsUnderPoint(this.mouseX, this.mouseY, null, true); - this._mouseOverX = this.mouseX; - this._mouseOverY = this.mouseY; - } - - var oldList = this._mouseOverTarget||[]; - var oldTarget = oldList[oldList.length-1]; - var list = this._mouseOverTarget = []; - - // generate ancestor list and check for cursor: - t = target; - while (t) { - list.unshift(t); - if (!cursor) { cursor = t.cursor; } - t = t.parent; - } - this.canvas.style.cursor = cursor; - if (!owner && eventTarget) { eventTarget.canvas.style.cursor = cursor; } - - // find common ancestor: - for (i=0,l=list.length; icommon; i--) { - this._dispatchMouseEvent(oldList[i], "rollout", false, -1, o, e, target); - } - - for (i=list.length-1; i>common; i--) { - this._dispatchMouseEvent(list[i], "rollover", false, -1, o, e, oldTarget); - } - - if (oldTarget != target) { - this._dispatchMouseEvent(target, "mouseover", true, -1, o, e, oldTarget); - } - - nextStage&&nextStage._testMouseOver(clear, owner || target && this, eventTarget || isEventTarget && this); - }; - - /** - * @method _handleDoubleClick - * @protected - * @param {MouseEvent} e - * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage. - **/ - p._handleDoubleClick = function(e, owner) { - var target=null, nextStage=this._nextStage, o=this._getPointerData(-1); - if (!owner) { - target = this._getObjectsUnderPoint(o.x, o.y, null, true); - this._dispatchMouseEvent(target, "dblclick", true, -1, o, e); - } - nextStage&&nextStage._handleDoubleClick(e, owner || target && this); - }; - - /** - * @method _dispatchMouseEvent - * @protected - * @param {DisplayObject} target - * @param {String} type - * @param {Boolean} bubbles - * @param {Number} pointerId - * @param {Object} o - * @param {MouseEvent} [nativeEvent] - * @param {DisplayObject} [relatedTarget] - **/ - p._dispatchMouseEvent = function(target, type, bubbles, pointerId, o, nativeEvent, relatedTarget) { - // TODO: might be worth either reusing MouseEvent instances, or adding a willTrigger method to avoid GC. - if (!target || (!bubbles && !target.hasEventListener(type))) { return; } - /* - // TODO: account for stage transformations? - this._mtx = this.getConcatenatedMatrix(this._mtx).invert(); - var pt = this._mtx.transformPoint(o.x, o.y); - var evt = new createjs.MouseEvent(type, bubbles, false, pt.x, pt.y, nativeEvent, pointerId, pointerId==this._primaryPointerID || pointerId==-1, o.rawX, o.rawY); - */ - var evt = new createjs.MouseEvent(type, bubbles, false, o.x, o.y, nativeEvent, pointerId, pointerId === this._primaryPointerID || pointerId === -1, o.rawX, o.rawY, relatedTarget); - target.dispatchEvent(evt); - }; - - - createjs.Stage = createjs.promote(Stage, "Container"); -}()); - -//############################################################################## -// Bitmap.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - - /** - * A Bitmap represents an Image, Canvas, or Video in the display list. A Bitmap can be instantiated using an existing - * HTML element, or a string. - * - *

    Example

    - * - * var bitmap = new createjs.Bitmap("imagePath.jpg"); - * - * Notes: - *
      - *
    1. When a string path or image tag that is not yet loaded is used, the stage may need to be redrawn before it - * will be displayed.
    2. - *
    3. Bitmaps with an SVG source currently will not respect an alpha value other than 0 or 1. To get around this, - * the Bitmap can be cached.
    4. - *
    5. Bitmaps with an SVG source will taint the canvas with cross-origin data, which prevents interactivity. This - * happens in all browsers except recent Firefox builds.
    6. - *
    7. Images loaded cross-origin will throw cross-origin security errors when interacted with using a mouse, using - * methods such as `getObjectUnderPoint`, or using filters, or caching. You can get around this by setting - * `crossOrigin` flags on your images before passing them to EaselJS, eg: `img.crossOrigin="Anonymous";`
    8. - *
    - * - * @class Bitmap - * @extends DisplayObject - * @constructor - * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | String} imageOrUri The source object or URI to an image to - * display. This can be either an Image, Canvas, or Video object, or a string URI to an image file to load and use. - * If it is a URI, a new Image object will be constructed and assigned to the .image property. - **/ - function Bitmap(imageOrUri) { - this.DisplayObject_constructor(); - - - // public properties: - /** - * The image to render. This can be an Image, a Canvas, or a Video. Not all browsers (especially - * mobile browsers) support drawing video to a canvas. - * @property image - * @type HTMLImageElement | HTMLCanvasElement | HTMLVideoElement - **/ - if (typeof imageOrUri == "string") { - this.image = document.createElement("img"); - this.image.src = imageOrUri; - } else { - this.image = imageOrUri; - } - - /** - * Specifies an area of the source image to draw. If omitted, the whole image will be drawn. - * Note that video sources must have a width / height set to work correctly with `sourceRect`. - * @property sourceRect - * @type Rectangle - * @default null - */ - this.sourceRect = null; - } - var p = createjs.extend(Bitmap, createjs.DisplayObject); - - -// public methods: - /** - * Constructor alias for backwards compatibility. This method will be removed in future versions. - * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}. - * @method initialize - * @deprecated in favour of `createjs.promote()` - **/ - p.initialize = Bitmap; // TODO: deprecated. - - /** - * Returns true or false indicating whether the display object would be visible if drawn to a canvas. - * This does not account for whether it would be visible within the boundaries of the stage. - * - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method isVisible - * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas - **/ - p.isVisible = function() { - var image = this.image; - var hasContent = this.cacheCanvas || (image && (image.naturalWidth || image.getContext || image.readyState >= 2)); - return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); - }; - - /** - * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. - * Returns true if the draw was handled (useful for overriding functionality). - * - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method draw - * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. - * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. - * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back - * into itself). - * @return {Boolean} - **/ - p.draw = function(ctx, ignoreCache) { - if (this.DisplayObject_draw(ctx, ignoreCache) || !this.image) { return true; } - var img = this.image, rect = this.sourceRect; - if (rect) { - // some browsers choke on out of bound values, so we'll fix them: - var x1 = rect.x, y1 = rect.y, x2 = x1 + rect.width, y2 = y1 + rect.height, x = 0, y = 0, w = img.width, h = img.height; - if (x1 < 0) { x -= x1; x1 = 0; } - if (x2 > w) { x2 = w; } - if (y1 < 0) { y -= y1; y1 = 0; } - if (y2 > h) { y2 = h; } - ctx.drawImage(img, x1, y1, x2-x1, y2-y1, x, y, x2-x1, y2-y1); - } else { - ctx.drawImage(img, 0, 0); - } - return true; - }; - - //Note, the doc sections below document using the specified APIs (from DisplayObject) from - //Bitmap. This is why they have no method implementations. - - /** - * Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances. - * You should not cache Bitmap instances as it can degrade performance. - * - * However: If you want to use a filter on a Bitmap, you MUST cache it, or it will not work. - * To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}} - * method. - * @method cache - **/ - - /** - * Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances. - * You should not cache Bitmap instances as it can degrade performance. - * - * However: If you want to use a filter on a Bitmap, you MUST cache it, or it will not work. - * To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}} - * method. - * @method updateCache - **/ - - /** - * Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances. - * You should not cache Bitmap instances as it can degrade performance. - * - * However: If you want to use a filter on a Bitmap, you MUST cache it, or it will not work. - * To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}} - * method. - * @method uncache - **/ - - /** - * Docced in superclass. - */ - p.getBounds = function() { - var rect = this.DisplayObject_getBounds(); - if (rect) { return rect; } - var image = this.image, o = this.sourceRect || image; - var hasContent = (image && (image.naturalWidth || image.getContext || image.readyState >= 2)); - return hasContent ? this._rectangle.setValues(0, 0, o.width, o.height) : null; - }; - - /** - * Returns a clone of the Bitmap instance. - * @method clone - * @return {Bitmap} a clone of the Bitmap instance. - **/ - p.clone = function() { - var o = new Bitmap(this.image); - if (this.sourceRect) { o.sourceRect = this.sourceRect.clone(); } - this._cloneProps(o); - return o; - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Bitmap (name="+ this.name +")]"; - }; - - - createjs.Bitmap = createjs.promote(Bitmap, "DisplayObject"); -}()); - -//############################################################################## -// Sprite.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Displays a frame or sequence of frames (ie. an animation) from a SpriteSheet instance. A sprite sheet is a series of - * images (usually animation frames) combined into a single image. For example, an animation consisting of 8 100x100 - * images could be combined into a 400x200 sprite sheet (4 frames across by 2 high). You can display individual frames, - * play frames as an animation, and even sequence animations together. - * - * See the {{#crossLink "SpriteSheet"}}{{/crossLink}} class for more information on setting up frames and animations. - * - *

    Example

    - * - * var instance = new createjs.Sprite(spriteSheet); - * instance.gotoAndStop("frameName"); - * - * Until {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} or {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}} is called, - * only the first defined frame defined in the sprite sheet will be displayed. - * - * @class Sprite - * @extends DisplayObject - * @constructor - * @param {SpriteSheet} spriteSheet The SpriteSheet instance to play back. This includes the source image(s), frame - * dimensions, and frame data. See {{#crossLink "SpriteSheet"}}{{/crossLink}} for more information. - * @param {String|Number} [frameOrAnimation] The frame number or animation to play initially. - **/ - function Sprite(spriteSheet, frameOrAnimation) { - this.DisplayObject_constructor(); - - - // public properties: - /** - * The frame index that will be drawn when draw is called. Note that with some {{#crossLink "SpriteSheet"}}{{/crossLink}} - * definitions, this will advance non-sequentially. This will always be an integer value. - * @property currentFrame - * @type {Number} - * @default 0 - * @readonly - **/ - this.currentFrame = 0; - - /** - * Returns the name of the currently playing animation. - * @property currentAnimation - * @type {String} - * @final - * @readonly - **/ - this.currentAnimation = null; - - /** - * Prevents the animation from advancing each tick automatically. For example, you could create a sprite - * sheet of icons, set paused to true, and display the appropriate icon by setting currentFrame. - * @property paused - * @type {Boolean} - * @default false - **/ - this.paused = true; - - /** - * The SpriteSheet instance to play back. This includes the source image, frame dimensions, and frame - * data. See {{#crossLink "SpriteSheet"}}{{/crossLink}} for more information. - * @property spriteSheet - * @type {SpriteSheet} - * @readonly - **/ - this.spriteSheet = spriteSheet; - - /** - * Specifies the current frame index within the currently playing animation. When playing normally, this will increase - * from 0 to n-1, where n is the number of frames in the current animation. - * - * This could be a non-integer value if - * using time-based playback (see {{#crossLink "Sprite/framerate"}}{{/crossLink}}, or if the animation's speed is - * not an integer. - * @property currentAnimationFrame - * @type {Number} - * @default 0 - **/ - this.currentAnimationFrame = 0; - - /** - * By default Sprite instances advance one frame per tick. Specifying a framerate for the Sprite (or its related - * SpriteSheet) will cause it to advance based on elapsed time between ticks as appropriate to maintain the target - * framerate. - * - * For example, if a Sprite with a framerate of 10 is placed on a Stage being updated at 40fps, then the Sprite will - * advance roughly one frame every 4 ticks. This will not be exact, because the time between each tick will - * vary slightly between frames. - * - * This feature is dependent on the tick event object (or an object with an appropriate "delta" property) being - * passed into {{#crossLink "Stage/update"}}{{/crossLink}}. - * @property framerate - * @type {Number} - * @default 0 - **/ - this.framerate = 0; - - - // private properties: - /** - * Current animation object. - * @property _animation - * @protected - * @type {Object} - * @default null - **/ - this._animation = null; - - /** - * Current frame index. - * @property _currentFrame - * @protected - * @type {Number} - * @default null - **/ - this._currentFrame = null; - - /** - * Skips the next auto advance. Used by gotoAndPlay to avoid immediately jumping to the next frame - * @property _skipAdvance - * @protected - * @type {Boolean} - * @default false - **/ - this._skipAdvance = false; - - - if (frameOrAnimation != null) { this.gotoAndPlay(frameOrAnimation); } - } - var p = createjs.extend(Sprite, createjs.DisplayObject); - - /** - * Constructor alias for backwards compatibility. This method will be removed in future versions. - * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}. - * @method initialize - * @deprecated in favour of `createjs.promote()` - **/ - p.initialize = Sprite; // TODO: Deprecated. This is for backwards support of FlashCC spritesheet export. - - -// events: - /** - * Dispatched when an animation reaches its ends. - * @event animationend - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {String} name The name of the animation that just ended. - * @param {String} next The name of the next animation that will be played, or null. This will be the same as name if the animation is looping. - * @since 0.6.0 - */ - - /** - * Dispatched any time the current frame changes. For example, this could be due to automatic advancement on a tick, - * or calling gotoAndPlay() or gotoAndStop(). - * @event change - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - */ - - -// public methods: - /** - * Returns true or false indicating whether the display object would be visible if drawn to a canvas. - * This does not account for whether it would be visible within the boundaries of the stage. - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method isVisible - * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas - **/ - p.isVisible = function() { - var hasContent = this.cacheCanvas || this.spriteSheet.complete; - return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); - }; - - /** - * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. - * Returns true if the draw was handled (useful for overriding functionality). - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method draw - * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. - * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache. - * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back - * into itself). - **/ - p.draw = function(ctx, ignoreCache) { - if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } - this._normalizeFrame(); - var o = this.spriteSheet.getFrame(this._currentFrame|0); - if (!o) { return false; } - var rect = o.rect; - if (rect.width && rect.height) { ctx.drawImage(o.image, rect.x, rect.y, rect.width, rect.height, -o.regX, -o.regY, rect.width, rect.height); } - return true; - }; - - //Note, the doc sections below document using the specified APIs (from DisplayObject) from - //Bitmap. This is why they have no method implementations. - - /** - * Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances. - * You should not cache Sprite instances as it can degrade performance. - * @method cache - **/ - - /** - * Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances. - * You should not cache Sprite instances as it can degrade performance. - * @method updateCache - **/ - - /** - * Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances. - * You should not cache Sprite instances as it can degrade performance. - * @method uncache - **/ - - /** - * Play (unpause) the current animation. The Sprite will be paused if either {{#crossLink "Sprite/stop"}}{{/crossLink}} - * or {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} is called. Single frame animations will remain - * unchanged. - * @method play - **/ - p.play = function() { - this.paused = false; - }; - - /** - * Stop playing a running animation. The Sprite will be playing if {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}} - * is called. Note that calling {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}} or {{#crossLink "Sprite/play"}}{{/crossLink}} - * will resume playback. - * @method stop - **/ - p.stop = function() { - this.paused = true; - }; - - /** - * Sets paused to false and plays the specified animation name, named frame, or frame number. - * @method gotoAndPlay - * @param {String|Number} frameOrAnimation The frame number or animation name that the playhead should move to - * and begin playing. - **/ - p.gotoAndPlay = function(frameOrAnimation) { - this.paused = false; - this._skipAdvance = true; - this._goto(frameOrAnimation); - }; - - /** - * Sets paused to true and seeks to the specified animation name, named frame, or frame number. - * @method gotoAndStop - * @param {String|Number} frameOrAnimation The frame number or animation name that the playhead should move to - * and stop. - **/ - p.gotoAndStop = function(frameOrAnimation) { - this.paused = true; - this._goto(frameOrAnimation); - }; - - /** - * Advances the playhead. This occurs automatically each tick by default. - * @param [time] {Number} The amount of time in ms to advance by. Only applicable if framerate is set on the Sprite - * or its SpriteSheet. - * @method advance - */ - p.advance = function(time) { - var fps = this.framerate || this.spriteSheet.framerate; - var t = (fps && time != null) ? time/(1000/fps) : 1; - this._normalizeFrame(t); - }; - - /** - * Returns a {{#crossLink "Rectangle"}}{{/crossLink}} instance defining the bounds of the current frame relative to - * the origin. For example, a 90 x 70 frame with regX=50 and regY=40 would return a - * rectangle with [x=-50, y=-40, width=90, height=70]. This ignores transformations on the display object. - * - * Also see the SpriteSheet {{#crossLink "SpriteSheet/getFrameBounds"}}{{/crossLink}} method. - * @method getBounds - * @return {Rectangle} A Rectangle instance. Returns null if the frame does not exist, or the image is not fully - * loaded. - **/ - p.getBounds = function() { - // TODO: should this normalizeFrame? - return this.DisplayObject_getBounds() || this.spriteSheet.getFrameBounds(this.currentFrame, this._rectangle); - }; - - /** - * Returns a clone of the Sprite instance. Note that the same SpriteSheet is shared between cloned - * instances. - * @method clone - * @return {Sprite} a clone of the Sprite instance. - **/ - p.clone = function() { - return this._cloneProps(new Sprite(this.spriteSheet)); - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Sprite (name="+ this.name +")]"; - }; - -// private methods: - /** - * @method _cloneProps - * @param {Sprite} o - * @return {Sprite} o - * @protected - **/ - p._cloneProps = function(o) { - this.DisplayObject__cloneProps(o); - o.currentFrame = this.currentFrame; - o.currentAnimation = this.currentAnimation; - o.paused = this.paused; - o.currentAnimationFrame = this.currentAnimationFrame; - o.framerate = this.framerate; - - o._animation = this._animation; - o._currentFrame = this._currentFrame; - o._skipAdvance = this._skipAdvance; - return o; - }; - - /** - * Advances the currentFrame if paused is not true. This is called automatically when the {{#crossLink "Stage"}}{{/crossLink}} - * ticks. - * @param {Object} evtObj An event object that will be dispatched to all tick listeners. This object is reused between dispatchers to reduce construction & GC costs. - * @protected - * @method _tick - **/ - p._tick = function(evtObj) { - if (!this.paused) { - if (!this._skipAdvance) { this.advance(evtObj&&evtObj.delta); } - this._skipAdvance = false; - } - this.DisplayObject__tick(evtObj); - }; - - - /** - * Normalizes the current frame, advancing animations and dispatching callbacks as appropriate. - * @protected - * @method _normalizeFrame - **/ - p._normalizeFrame = function(frameDelta) { - frameDelta = frameDelta || 0; - var animation = this._animation; - var paused = this.paused; - var frame = this._currentFrame; - var l; - - if (animation) { - var speed = animation.speed || 1; - var animFrame = this.currentAnimationFrame; - l = animation.frames.length; - if (animFrame + frameDelta * speed >= l) { - var next = animation.next; - if (this._dispatchAnimationEnd(animation, frame, paused, next, l - 1)) { - // something changed in the event stack, so we shouldn't make any more changes here. - return; - } else if (next) { - // sequence. Automatically calls _normalizeFrame again with the remaining frames. - return this._goto(next, frameDelta - (l - animFrame) / speed); - } else { - // end. - this.paused = true; - animFrame = animation.frames.length - 1; - } - } else { - animFrame += frameDelta * speed; - } - this.currentAnimationFrame = animFrame; - this._currentFrame = animation.frames[animFrame | 0] - } else { - frame = (this._currentFrame += frameDelta); - l = this.spriteSheet.getNumFrames(); - if (frame >= l && l > 0) { - if (!this._dispatchAnimationEnd(animation, frame, paused, l - 1)) { - // looped. - if ((this._currentFrame -= l) >= l) { return this._normalizeFrame(); } - } - } - } - frame = this._currentFrame | 0; - if (this.currentFrame != frame) { - this.currentFrame = frame; - this.dispatchEvent("change"); - } - }; - - /** - * Dispatches the "animationend" event. Returns true if a handler changed the animation (ex. calling {{#crossLink "Sprite/stop"}}{{/crossLink}}, - * {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}}, etc.) - * @property _dispatchAnimationEnd - * @private - * @type {Function} - **/ - p._dispatchAnimationEnd = function(animation, frame, paused, next, end) { - var name = animation ? animation.name : null; - if (this.hasEventListener("animationend")) { - var evt = new createjs.Event("animationend"); - evt.name = name; - evt.next = next; - this.dispatchEvent(evt); - } - // did the animation get changed in the event stack?: - var changed = (this._animation != animation || this._currentFrame != frame); - // if the animation hasn't changed, but the sprite was paused, then we want to stick to the last frame: - if (!changed && !paused && this.paused) { this.currentAnimationFrame = end; changed = true; } - return changed; - }; - - /** - * Moves the playhead to the specified frame number or animation. - * @method _goto - * @param {String|Number} frameOrAnimation The frame number or animation that the playhead should move to. - * @param {Boolean} [frame] The frame of the animation to go to. Defaults to 0. - * @protected - **/ - p._goto = function(frameOrAnimation, frame) { - this.currentAnimationFrame = 0; - if (isNaN(frameOrAnimation)) { - var data = this.spriteSheet.getAnimation(frameOrAnimation); - if (data) { - this._animation = data; - this.currentAnimation = frameOrAnimation; - this._normalizeFrame(frame); - } - } else { - this.currentAnimation = this._animation = null; - this._currentFrame = frameOrAnimation; - this._normalizeFrame(); - } - }; - - - createjs.Sprite = createjs.promote(Sprite, "DisplayObject"); -}()); - -//############################################################################## -// Shape.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * A Shape allows you to display vector art in the display list. It composites a {{#crossLink "Graphics"}}{{/crossLink}} - * instance which exposes all of the vector drawing methods. The Graphics instance can be shared between multiple Shape - * instances to display the same vector graphics with different positions or transforms. - * - * If the vector art will not - * change between draws, you may want to use the {{#crossLink "DisplayObject/cache"}}{{/crossLink}} method to reduce the - * rendering cost. - * - *

    Example

    - * - * var graphics = new createjs.Graphics().beginFill("#ff0000").drawRect(0, 0, 100, 100); - * var shape = new createjs.Shape(graphics); - * - * //Alternatively use can also use the graphics property of the Shape class to renderer the same as above. - * var shape = new createjs.Shape(); - * shape.graphics.beginFill("#ff0000").drawRect(0, 0, 100, 100); - * - * @class Shape - * @extends DisplayObject - * @constructor - * @param {Graphics} graphics Optional. The graphics instance to display. If null, a new Graphics instance will be created. - **/ - function Shape(graphics) { - this.DisplayObject_constructor(); - - - // public properties: - /** - * The graphics instance to display. - * @property graphics - * @type Graphics - **/ - this.graphics = graphics ? graphics : new createjs.Graphics(); - } - var p = createjs.extend(Shape, createjs.DisplayObject); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// public methods: - /** - * Returns true or false indicating whether the Shape would be visible if drawn to a canvas. - * This does not account for whether it would be visible within the boundaries of the stage. - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method isVisible - * @return {Boolean} Boolean indicating whether the Shape would be visible if drawn to a canvas - **/ - p.isVisible = function() { - var hasContent = this.cacheCanvas || (this.graphics && !this.graphics.isEmpty()); - return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); - }; - - /** - * Draws the Shape into the specified context ignoring its visible, alpha, shadow, and transform. Returns true if - * the draw was handled (useful for overriding functionality). - * - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method draw - * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. - * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. For example, - * used for drawing the cache (to prevent it from simply drawing an existing cache back into itself). - * @return {Boolean} - **/ - p.draw = function(ctx, ignoreCache) { - if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } - this.graphics.draw(ctx, this); - return true; - }; - - /** - * Returns a clone of this Shape. Some properties that are specific to this instance's current context are reverted to - * their defaults (for example .parent). - * @method clone - * @param {Boolean} recursive If true, this Shape's {{#crossLink "Graphics"}}{{/crossLink}} instance will also be - * cloned. If false, the Graphics instance will be shared with the new Shape. - **/ - p.clone = function(recursive) { - var g = (recursive && this.graphics) ? this.graphics.clone() : this.graphics; - return this._cloneProps(new Shape(g)); - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Shape (name="+ this.name +")]"; - }; - - - createjs.Shape = createjs.promote(Shape, "DisplayObject"); -}()); - -//############################################################################## -// Text.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Display one or more lines of dynamic text (not user editable) in the display list. Line wrapping support (using the - * lineWidth) is very basic, wrapping on spaces and tabs only. Note that as an alternative to Text, you can position HTML - * text above or below the canvas relative to items in the display list using the {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}} - * method, or using {{#crossLink "DOMElement"}}{{/crossLink}}. - * - * Please note that Text does not support HTML text, and can only display one font style at a time. To use - * multiple font styles, you will need to create multiple text instances, and position them manually. - * - *

    Example

    - * - * var text = new createjs.Text("Hello World", "20px Arial", "#ff7700"); - * text.x = 100; - * text.textBaseline = "alphabetic"; - * - * CreateJS Text supports web fonts (the same rules as Canvas). The font must be loaded and supported by the browser - * before it can be displayed. - * - * Note: Text can be expensive to generate, so cache instances where possible. Be aware that not all - * browsers will render Text exactly the same. - * @class Text - * @extends DisplayObject - * @constructor - * @param {String} [text] The text to display. - * @param {String} [font] The font style to use. Any valid value for the CSS font attribute is acceptable (ex. "bold - * 36px Arial"). - * @param {String} [color] The color to draw the text in. Any valid value for the CSS color attribute is acceptable (ex. - * "#F00", "red", or "#FF0000"). - **/ - function Text(text, font, color) { - this.DisplayObject_constructor(); - - - // public properties: - /** - * The text to display. - * @property text - * @type String - **/ - this.text = text; - - /** - * The font style to use. Any valid value for the CSS font attribute is acceptable (ex. "bold 36px Arial"). - * @property font - * @type String - **/ - this.font = font; - - /** - * The color to draw the text in. Any valid value for the CSS color attribute is acceptable (ex. "#F00"). Default is "#000". - * It will also accept valid canvas fillStyle values. - * @property color - * @type String - **/ - this.color = color; - - /** - * The horizontal text alignment. Any of "start", "end", "left", "right", and "center". For detailed - * information view the - * - * whatwg spec. Default is "left". - * @property textAlign - * @type String - **/ - this.textAlign = "left"; - - /** - * The vertical alignment point on the font. Any of "top", "hanging", "middle", "alphabetic", "ideographic", or - * "bottom". For detailed information view the - * whatwg spec. Default is "top". - * @property textBaseline - * @type String - */ - this.textBaseline = "top"; - - /** - * The maximum width to draw the text. If maxWidth is specified (not null), the text will be condensed or - * shrunk to make it fit in this width. For detailed information view the - * - * whatwg spec. - * @property maxWidth - * @type Number - */ - this.maxWidth = null; - - /** - * If greater than 0, the text will be drawn as a stroke (outline) of the specified width. - * @property outline - * @type Number - **/ - this.outline = 0; - - /** - * Indicates the line height (vertical distance between baselines) for multi-line text. If null or 0, - * the value of getMeasuredLineHeight is used. - * @property lineHeight - * @type Number - **/ - this.lineHeight = 0; - - /** - * Indicates the maximum width for a line of text before it is wrapped to multiple lines. If null, - * the text will not be wrapped. - * @property lineWidth - * @type Number - **/ - this.lineWidth = null; - } - var p = createjs.extend(Text, createjs.DisplayObject); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// static properties: - /** - * @property _workingContext - * @type CanvasRenderingContext2D - * @private - **/ - var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")); - if (canvas.getContext) { Text._workingContext = canvas.getContext("2d"); canvas.width = canvas.height = 1; } - - -// constants: - /** - * Lookup table for the ratio to offset bounds x calculations based on the textAlign property. - * @property H_OFFSETS - * @type Object - * @protected - * @static - **/ - Text.H_OFFSETS = {start: 0, left: 0, center: -0.5, end: -1, right: -1}; - - /** - * Lookup table for the ratio to offset bounds y calculations based on the textBaseline property. - * @property H_OFFSETS - * @type Object - * @protected - * @static - **/ - Text.V_OFFSETS = {top: 0, hanging: -0.01, middle: -0.4, alphabetic: -0.8, ideographic: -0.85, bottom: -1}; - - -// public methods: - /** - * Returns true or false indicating whether the display object would be visible if drawn to a canvas. - * This does not account for whether it would be visible within the boundaries of the stage. - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method isVisible - * @return {Boolean} Whether the display object would be visible if drawn to a canvas - **/ - p.isVisible = function() { - var hasContent = this.cacheCanvas || (this.text != null && this.text !== ""); - return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); - }; - - /** - * Draws the Text into the specified context ignoring its visible, alpha, shadow, and transform. - * Returns true if the draw was handled (useful for overriding functionality). - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method draw - * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. - * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache. - * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back - * into itself). - **/ - p.draw = function(ctx, ignoreCache) { - if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } - - var col = this.color || "#000"; - if (this.outline) { ctx.strokeStyle = col; ctx.lineWidth = this.outline*1; } - else { ctx.fillStyle = col; } - - this._drawText(this._prepContext(ctx)); - return true; - }; - - /** - * Returns the measured, untransformed width of the text without wrapping. Use getBounds for a more robust value. - * @method getMeasuredWidth - * @return {Number} The measured, untransformed width of the text. - **/ - p.getMeasuredWidth = function() { - return this._getMeasuredWidth(this.text); - }; - - /** - * Returns an approximate line height of the text, ignoring the lineHeight property. This is based on the measured - * width of a "M" character multiplied by 1.2, which provides an approximate line height for most fonts. - * @method getMeasuredLineHeight - * @return {Number} an approximate line height of the text, ignoring the lineHeight property. This is - * based on the measured width of a "M" character multiplied by 1.2, which approximates em for most fonts. - **/ - p.getMeasuredLineHeight = function() { - return this._getMeasuredWidth("M")*1.2; - }; - - /** - * Returns the approximate height of multi-line text by multiplying the number of lines against either the - * lineHeight (if specified) or {{#crossLink "Text/getMeasuredLineHeight"}}{{/crossLink}}. Note that - * this operation requires the text flowing logic to run, which has an associated CPU cost. - * @method getMeasuredHeight - * @return {Number} The approximate height of the untransformed multi-line text. - **/ - p.getMeasuredHeight = function() { - return this._drawText(null,{}).height; - }; - - /** - * Docced in superclass. - */ - p.getBounds = function() { - var rect = this.DisplayObject_getBounds(); - if (rect) { return rect; } - if (this.text == null || this.text === "") { return null; } - var o = this._drawText(null, {}); - var w = (this.maxWidth && this.maxWidth < o.width) ? this.maxWidth : o.width; - var x = w * Text.H_OFFSETS[this.textAlign||"left"]; - var lineHeight = this.lineHeight||this.getMeasuredLineHeight(); - var y = lineHeight * Text.V_OFFSETS[this.textBaseline||"top"]; - return this._rectangle.setValues(x, y, w, o.height); - }; - - /** - * Returns an object with width, height, and lines properties. The width and height are the visual width and height - * of the drawn text. The lines property contains an array of strings, one for - * each line of text that will be drawn, accounting for line breaks and wrapping. These strings have trailing - * whitespace removed. - * @method getMetrics - * @return {Object} An object with width, height, and lines properties. - **/ - p.getMetrics = function() { - var o = {lines:[]}; - o.lineHeight = this.lineHeight || this.getMeasuredLineHeight(); - o.vOffset = o.lineHeight * Text.V_OFFSETS[this.textBaseline||"top"]; - return this._drawText(null, o, o.lines); - }; - - /** - * Returns a clone of the Text instance. - * @method clone - * @return {Text} a clone of the Text instance. - **/ - p.clone = function() { - return this._cloneProps(new Text(this.text, this.font, this.color)); - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Text (text="+ (this.text.length > 20 ? this.text.substr(0, 17)+"..." : this.text) +")]"; - }; - - -// private methods: - /** - * @method _cloneProps - * @param {Text} o - * @protected - * @return {Text} o - **/ - p._cloneProps = function(o) { - this.DisplayObject__cloneProps(o); - o.textAlign = this.textAlign; - o.textBaseline = this.textBaseline; - o.maxWidth = this.maxWidth; - o.outline = this.outline; - o.lineHeight = this.lineHeight; - o.lineWidth = this.lineWidth; - return o; - }; - - /** - * @method _getWorkingContext - * @param {CanvasRenderingContext2D} ctx - * @return {CanvasRenderingContext2D} - * @protected - **/ - p._prepContext = function(ctx) { - ctx.font = this.font||"10px sans-serif"; - ctx.textAlign = this.textAlign||"left"; - ctx.textBaseline = this.textBaseline||"top"; - return ctx; - }; - - /** - * Draws multiline text. - * @method _drawText - * @param {CanvasRenderingContext2D} ctx - * @param {Object} o - * @param {Array} lines - * @return {Object} - * @protected - **/ - p._drawText = function(ctx, o, lines) { - var paint = !!ctx; - if (!paint) { - ctx = Text._workingContext; - ctx.save(); - this._prepContext(ctx); - } - var lineHeight = this.lineHeight||this.getMeasuredLineHeight(); - - var maxW = 0, count = 0; - var hardLines = String(this.text).split(/(?:\r\n|\r|\n)/); - for (var i=0, l=hardLines.length; i this.lineWidth) { - // text wrapping: - var words = str.split(/(\s)/); - str = words[0]; - w = ctx.measureText(str).width; - - for (var j=1, jl=words.length; j this.lineWidth) { - if (paint) { this._drawTextLine(ctx, str, count*lineHeight); } - if (lines) { lines.push(str); } - if (w > maxW) { maxW = w; } - str = words[j+1]; - w = ctx.measureText(str).width; - count++; - } else { - str += words[j] + words[j+1]; - w += wordW; - } - } - } - - if (paint) { this._drawTextLine(ctx, str, count*lineHeight); } - if (lines) { lines.push(str); } - if (o && w == null) { w = ctx.measureText(str).width; } - if (w > maxW) { maxW = w; } - count++; - } - - if (o) { - o.width = maxW; - o.height = count*lineHeight; - } - if (!paint) { ctx.restore(); } - return o; - }; - - /** - * @method _drawTextLine - * @param {CanvasRenderingContext2D} ctx - * @param {String} text - * @param {Number} y - * @protected - **/ - p._drawTextLine = function(ctx, text, y) { - // Chrome 17 will fail to draw the text if the last param is included but null, so we feed it a large value instead: - if (this.outline) { ctx.strokeText(text, 0, y, this.maxWidth||0xFFFF); } - else { ctx.fillText(text, 0, y, this.maxWidth||0xFFFF); } - }; - - - /** - * @method _getMeasuredWidth - * @param {String} text - * @protected - **/ - p._getMeasuredWidth = function(text) { - var ctx = Text._workingContext; - ctx.save(); - var w = this._prepContext(ctx).measureText(text).width; - ctx.restore(); - return w; - }; - - - createjs.Text = createjs.promote(Text, "DisplayObject"); -}()); - -//############################################################################## -// BitmapText.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - -// constructor: - /** - * Displays text using bitmap glyphs defined in a sprite sheet. Multi-line text is supported - * using new line characters, but automatic wrapping is not supported. See the - * {{#crossLink "BitmapText/spriteSheet:property"}}{{/crossLink}} - * property for more information on defining glyphs. - * - * Important: BitmapText extends Container, but is not designed to be used as one. - * As such, methods like addChild and removeChild are disabled. - * @class BitmapText - * @extends DisplayObject - * @param {String} [text=""] The text to display. - * @param {SpriteSheet} [spriteSheet=null] The spritesheet that defines the character glyphs. - * @constructor - **/ - function BitmapText(text, spriteSheet) { - this.Container_constructor(); - - - // public properties: - /** - * The text to display. - * @property text - * @type String - * @default "" - **/ - this.text = text||""; - - /** - * A SpriteSheet instance that defines the glyphs for this bitmap text. Each glyph/character - * should have a single frame animation defined in the sprite sheet named the same as - * corresponding character. For example, the following animation definition: - * - * "A": {frames: [0]} - * - * would indicate that the frame at index 0 of the spritesheet should be drawn for the "A" character. The short form - * is also acceptable: - * - * "A": 0 - * - * Note that if a character in the text is not found in the sprite sheet, it will also - * try to use the alternate case (upper or lower). - * - * See SpriteSheet for more information on defining sprite sheet data. - * @property spriteSheet - * @type SpriteSheet - * @default null - **/ - this.spriteSheet = spriteSheet; - - /** - * The height of each line of text. If 0, then it will use a line height calculated - * by checking for the height of the "1", "T", or "L" character (in that order). If - * those characters are not defined, it will use the height of the first frame of the - * sprite sheet. - * @property lineHeight - * @type Number - * @default 0 - **/ - this.lineHeight = 0; - - /** - * This spacing (in pixels) will be added after each character in the output. - * @property letterSpacing - * @type Number - * @default 0 - **/ - this.letterSpacing = 0; - - /** - * If a space character is not defined in the sprite sheet, then empty pixels equal to - * spaceWidth will be inserted instead. If 0, then it will use a value calculated - * by checking for the width of the "1", "l", "E", or "A" character (in that order). If - * those characters are not defined, it will use the width of the first frame of the - * sprite sheet. - * @property spaceWidth - * @type Number - * @default 0 - **/ - this.spaceWidth = 0; - - - // private properties: - /** - * @property _oldProps - * @type Object - * @protected - **/ - this._oldProps = {text:0,spriteSheet:0,lineHeight:0,letterSpacing:0,spaceWidth:0}; - } - var p = createjs.extend(BitmapText, createjs.Container); - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - -// static properties: - /** - * BitmapText uses Sprite instances to draw text. To reduce the creation and destruction of instances (and thus garbage collection), it maintains - * an internal object pool of sprite instances to reuse. Increasing this value can cause more sprites to be - * retained, slightly increasing memory use, but reducing instantiation. - * @property maxPoolSize - * @type Number - * @static - * @default 100 - **/ - BitmapText.maxPoolSize = 100; - - /** - * Sprite object pool. - * @type {Array} - * @static - * @private - */ - BitmapText._spritePool = []; - - -// public methods: - /** - * Docced in superclass. - **/ - p.draw = function(ctx, ignoreCache) { - if (this.DisplayObject_draw(ctx, ignoreCache)) { return; } - this._updateText(); - this.Container_draw(ctx, ignoreCache); - }; - - /** - * Docced in superclass. - **/ - p.getBounds = function() { - this._updateText(); - return this.Container_getBounds(); - }; - - /** - * Returns true or false indicating whether the display object would be visible if drawn to a canvas. - * This does not account for whether it would be visible within the boundaries of the stage. - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method isVisible - * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas - **/ - p.isVisible = function() { - var hasContent = this.cacheCanvas || (this.spriteSheet && this.spriteSheet.complete && this.text); - return !!(this.visible && this.alpha > 0 && this.scaleX !== 0 && this.scaleY !== 0 && hasContent); - }; - - p.clone = function() { - return this._cloneProps(new BitmapText(this.text, this.spriteSheet)); - }; - - /** - * Disabled in BitmapText. - * @method addChild - **/ - /** - * Disabled in BitmapText. - * @method addChildAt - **/ - /** - * Disabled in BitmapText. - * @method removeChild - **/ - /** - * Disabled in BitmapText. - * @method removeChildAt - **/ - /** - * Disabled in BitmapText. - * @method removeAllChildren - **/ - p.addChild = p.addChildAt = p.removeChild = p.removeChildAt = p.removeAllChildren = function() {}; - - -// private methods: - /** - * @method _cloneProps - * @param {BitmapText} o - * @return {BitmapText} o - * @protected - **/ - p._cloneProps = function(o) { - this.Container__cloneProps(o); - o.lineHeight = this.lineHeight; - o.letterSpacing = this.letterSpacing; - o.spaceWidth = this.spaceWidth; - return o; - }; - - /** - * @method _getFrameIndex - * @param {String} character - * @param {SpriteSheet} spriteSheet - * @return {Number} - * @protected - **/ - p._getFrameIndex = function(character, spriteSheet) { - var c, o = spriteSheet.getAnimation(character); - if (!o) { - (character != (c = character.toUpperCase())) || (character != (c = character.toLowerCase())) || (c=null); - if (c) { o = spriteSheet.getAnimation(c); } - } - return o && o.frames[0]; - }; - - /** - * @method _getFrame - * @param {String} character - * @param {SpriteSheet} spriteSheet - * @return {Object} - * @protected - **/ - p._getFrame = function(character, spriteSheet) { - var index = this._getFrameIndex(character, spriteSheet); - return index == null ? index : spriteSheet.getFrame(index); - }; - - /** - * @method _getLineHeight - * @param {SpriteSheet} ss - * @return {Number} - * @protected - **/ - p._getLineHeight = function(ss) { - var frame = this._getFrame("1",ss) || this._getFrame("T",ss) || this._getFrame("L",ss) || ss.getFrame(0); - return frame ? frame.rect.height : 1; - }; - /** - * @method _getSpaceWidth - * @param {SpriteSheet} ss - * @return {Number} - * @protected - **/ - p._getSpaceWidth = function(ss) { - var frame = this._getFrame("1",ss) || this._getFrame("l",ss) || this._getFrame("e",ss) || this._getFrame("a",ss) || ss.getFrame(0); - return frame ? frame.rect.width : 1; - }; - - /** - * @method _drawText - * @protected - **/ - p._updateText = function() { - var x=0, y=0, o=this._oldProps, change=false, spaceW=this.spaceWidth, lineH=this.lineHeight, ss=this.spriteSheet; - var pool=BitmapText._spritePool, kids=this.children, childIndex=0, numKids=kids.length, sprite; - - for (var n in o) { - if (o[n] != this[n]) { - o[n] = this[n]; - change = true; - } - } - if (!change) { return; } - - var hasSpace = !!this._getFrame(" ", ss); - if (!hasSpace && !spaceW) { spaceW = this._getSpaceWidth(ss); } - if (!lineH) { lineH = this._getLineHeight(ss); } - - for(var i=0, l=this.text.length; i childIndex) { - // faster than removeChild. - pool.push(sprite = kids.pop()); - sprite.parent = null; - numKids--; - } - if (pool.length > BitmapText.maxPoolSize) { pool.length = BitmapText.maxPoolSize; } - }; - - - createjs.BitmapText = createjs.promote(BitmapText, "Container"); -}()); - -//############################################################################## -// MovieClip.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * The MovieClip class associates a TweenJS Timeline with an EaselJS {{#crossLink "Container"}}{{/crossLink}}. It allows - * you to create objects which encapsulate timeline animations, state changes, and synched actions. Due to the - * complexities inherent in correctly setting up a MovieClip, it is largely intended for tool output and is not included - * in the main EaselJS library. - * - * Currently MovieClip only works properly if it is tick based (as opposed to time based) though some concessions have - * been made to support time-based timelines in the future. - * - *

    Example

    - * This example animates two shapes back and forth. The grey shape starts on the left, but we jump to a mid-point in - * the animation using {{#crossLink "MovieClip/gotoAndPlay"}}{{/crossLink}}. - * - * var stage = new createjs.Stage("canvas"); - * createjs.Ticker.addEventListener("tick", stage); - * - * var mc = new createjs.MovieClip(null, 0, true, {start:20}); - * stage.addChild(mc); - * - * var child1 = new createjs.Shape( - * new createjs.Graphics().beginFill("#999999") - * .drawCircle(30,30,30)); - * var child2 = new createjs.Shape( - * new createjs.Graphics().beginFill("#5a9cfb") - * .drawCircle(30,30,30)); - * - * mc.timeline.addTween( - * createjs.Tween.get(child1) - * .to({x:0}).to({x:60}, 50).to({x:0}, 50)); - * mc.timeline.addTween( - * createjs.Tween.get(child2) - * .to({x:60}).to({x:0}, 50).to({x:60}, 50)); - * - * mc.gotoAndPlay("start"); - * - * It is recommended to use tween.to() to animate and set properties (use no duration to have it set - * immediately), and the tween.wait() method to create delays between animations. Note that using the - * tween.set() method to affect properties will likely not provide the desired result. - * - * @class MovieClip - * @main MovieClip - * @extends Container - * @constructor - * @param {String} [mode=independent] Initial value for the mode property. One of {{#crossLink "MovieClip/INDEPENDENT:property"}}{{/crossLink}}, - * {{#crossLink "MovieClip/SINGLE_FRAME:property"}}{{/crossLink}}, or {{#crossLink "MovieClip/SYNCHED:property"}}{{/crossLink}}. - * The default is {{#crossLink "MovieClip/INDEPENDENT:property"}}{{/crossLink}}. - * @param {Number} [startPosition=0] Initial value for the {{#crossLink "MovieClip/startPosition:property"}}{{/crossLink}} - * property. - * @param {Boolean} [loop=true] Initial value for the {{#crossLink "MovieClip/loop:property"}}{{/crossLink}} - * property. The default is `true`. - * @param {Object} [labels=null] A hash of labels to pass to the {{#crossLink "MovieClip/timeline:property"}}{{/crossLink}} - * instance associated with this MovieClip. Labels only need to be passed if they need to be used. - **/ - function MovieClip(mode, startPosition, loop, labels) { - this.Container_constructor(); - !MovieClip.inited&&MovieClip.init(); // static init - - - // public properties: - /** - * Controls how this MovieClip advances its time. Must be one of 0 (INDEPENDENT), 1 (SINGLE_FRAME), or 2 (SYNCHED). - * See each constant for a description of the behaviour. - * @property mode - * @type String - * @default null - **/ - this.mode = mode||MovieClip.INDEPENDENT; - - /** - * Specifies what the first frame to play in this movieclip, or the only frame to display if mode is SINGLE_FRAME. - * @property startPosition - * @type Number - * @default 0 - */ - this.startPosition = startPosition || 0; - - /** - * Indicates whether this MovieClip should loop when it reaches the end of its timeline. - * @property loop - * @type Boolean - * @default true - */ - this.loop = loop; - - /** - * The current frame of the movieclip. - * @property currentFrame - * @type Number - * @default 0 - * @readonly - */ - this.currentFrame = 0; - - /** - * The TweenJS Timeline that is associated with this MovieClip. This is created automatically when the MovieClip - * instance is initialized. Animations are created by adding TweenJS Tween - * instances to the timeline. - * - *

    Example

    - * - * var tween = createjs.Tween.get(target).to({x:0}).to({x:100}, 30); - * var mc = new createjs.MovieClip(); - * mc.timeline.addTween(tween); - * - * Elements can be added and removed from the timeline by toggling an "_off" property - * using the tweenInstance.to() method. Note that using Tween.set is not recommended to - * create MovieClip animations. The following example will toggle the target off on frame 0, and then back on for - * frame 1. You can use the "visible" property to achieve the same effect. - * - * var tween = createjs.Tween.get(target).to({_off:false}) - * .wait(1).to({_off:true}) - * .wait(1).to({_off:false}); - * - * @property timeline - * @type Timeline - * @default null - */ - this.timeline = new createjs.Timeline(null, labels, {paused:true, position:startPosition, useTicks:true}); - - /** - * If true, the MovieClip's position will not advance when ticked. - * @property paused - * @type Boolean - * @default false - */ - this.paused = false; - - /** - * If true, actions in this MovieClip's tweens will be run when the playhead advances. - * @property actionsEnabled - * @type Boolean - * @default true - */ - this.actionsEnabled = true; - - /** - * If true, the MovieClip will automatically be reset to its first frame whenever the timeline adds - * it back onto the display list. This only applies to MovieClip instances with mode=INDEPENDENT. - *

    - * For example, if you had a character animation with a "body" child MovieClip instance - * with different costumes on each frame, you could set body.autoReset = false, so that - * you can manually change the frame it is on, without worrying that it will be reset - * automatically. - * @property autoReset - * @type Boolean - * @default true - */ - this.autoReset = true; - - /** - * An array of bounds for each frame in the MovieClip. This is mainly intended for tool output. - * @property frameBounds - * @type Array - * @default null - */ - this.frameBounds = this.frameBounds||null; // TODO: Deprecated. This is for backwards support of FlashCC - - /** - * By default MovieClip instances advance one frame per tick. Specifying a framerate for the MovieClip - * will cause it to advance based on elapsed time between ticks as appropriate to maintain the target - * framerate. - * - * For example, if a MovieClip with a framerate of 10 is placed on a Stage being updated at 40fps, then the MovieClip will - * advance roughly one frame every 4 ticks. This will not be exact, because the time between each tick will - * vary slightly between frames. - * - * This feature is dependent on the tick event object (or an object with an appropriate "delta" property) being - * passed into {{#crossLink "Stage/update"}}{{/crossLink}}. - * @property framerate - * @type {Number} - * @default null - **/ - this.framerate = null; - - - // private properties: - /** - * @property _synchOffset - * @type Number - * @default 0 - * @private - */ - this._synchOffset = 0; - - /** - * @property _prevPos - * @type Number - * @default -1 - * @private - */ - this._prevPos = -1; // TODO: evaluate using a ._reset Boolean prop instead of -1. - - /** - * @property _prevPosition - * @type Number - * @default 0 - * @private - */ - this._prevPosition = 0; - - /** - * The time remaining from the previous tick, only applicable when .framerate is set. - * @property _t - * @type Number - * @private - */ - this._t = 0; - - /** - * List of display objects that are actively being managed by the MovieClip. - * @property _managed - * @type Object - * @private - */ - this._managed = {}; - } - var p = createjs.extend(MovieClip, createjs.Container); - - -// constants: - /** - * The MovieClip will advance independently of its parent, even if its parent is paused. - * This is the default mode. - * @property INDEPENDENT - * @static - * @type String - * @default "independent" - * @readonly - **/ - MovieClip.INDEPENDENT = "independent"; - - /** - * The MovieClip will only display a single frame (as determined by the startPosition property). - * @property SINGLE_FRAME - * @static - * @type String - * @default "single" - * @readonly - **/ - MovieClip.SINGLE_FRAME = "single"; - - /** - * The MovieClip will be advanced only when its parent advances and will be synched to the position of - * the parent MovieClip. - * @property SYNCHED - * @static - * @type String - * @default "synched" - * @readonly - **/ - MovieClip.SYNCHED = "synched"; - - -// static properties: - MovieClip.inited = false; - - -// static methods: - MovieClip.init = function() { - if (MovieClip.inited) { return; } - // plugins introduce some overhead to Tween, so we only install this if an MC is instantiated. - MovieClipPlugin.install(); - MovieClip.inited = true; - }; - - -// getter / setters: - /** - * Use the {{#crossLink "MovieClip/labels:property"}}{{/crossLink}} property instead. - * @method getLabels - * @return {Array} - * @deprecated - **/ - p.getLabels = function() { - return this.timeline.getLabels(); - }; - - /** - * Use the {{#crossLink "MovieClip/currentLabel:property"}}{{/crossLink}} property instead. - * @method getCurrentLabel - * @return {String} - * @deprecated - **/ - p.getCurrentLabel = function() { - this._updateTimeline(); - return this.timeline.getCurrentLabel(); - }; - - /** - * Use the {{#crossLink "MovieClip/duration:property"}}{{/crossLink}} property instead. - * @method getDuration - * @return {Number} - * @protected - **/ - p.getDuration = function() { - return this.timeline.duration; - }; - - /** - * Returns an array of objects with label and position (aka frame) properties, sorted by position. - * Shortcut to TweenJS: Timeline.getLabels(); - * @property labels - * @type {Array} - * @readonly - **/ - - /** - * Returns the name of the label on or immediately before the current frame. See TweenJS: Timeline.getCurrentLabel() - * for more information. - * @property currentLabel - * @type {String} - * @readonly - **/ - - /** - * Returns the duration of this MovieClip in seconds or ticks. Identical to {{#crossLink "MovieClip/duration:property"}}{{/crossLink}} - * and provided for Flash API compatibility. - * @property totalFrames - * @type {Number} - * @readonly - **/ - - /** - * Returns the duration of this MovieClip in seconds or ticks. - * @property duration - * @type {Number} - * @readonly - **/ - try { - Object.defineProperties(p, { - labels: { get: p.getLabels }, - currentLabel: { get: p.getCurrentLabel }, - totalFrames: { get: p.getDuration }, - duration: { get: p.getDuration } - }); - } catch (e) {} - - -// public methods: - /** - * Constructor alias for backwards compatibility. This method will be removed in future versions. - * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}. - * @method initialize - * @deprecated in favour of `createjs.promote()` - **/ - p.initialize = MovieClip; // TODO: Deprecated. This is for backwards support of FlashCC - - /** - * Returns true or false indicating whether the display object would be visible if drawn to a canvas. - * This does not account for whether it would be visible within the boundaries of the stage. - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method isVisible - * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas - **/ - p.isVisible = function() { - // children are placed in draw, so we can't determine if we have content. - return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0); - }; - - /** - * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. - * Returns true if the draw was handled (useful for overriding functionality). - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method draw - * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. - * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache. - * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back - * into itself). - **/ - p.draw = function(ctx, ignoreCache) { - // draw to cache first: - if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } - this._updateTimeline(); - this.Container_draw(ctx, ignoreCache); - return true; - }; - - /** - * Sets paused to false. - * @method play - **/ - p.play = function() { - this.paused = false; - }; - - /** - * Sets paused to true. - * @method stop - **/ - p.stop = function() { - this.paused = true; - }; - - /** - * Advances this movie clip to the specified position or label and sets paused to false. - * @method gotoAndPlay - * @param {String|Number} positionOrLabel The animation name or frame number to go to. - **/ - p.gotoAndPlay = function(positionOrLabel) { - this.paused = false; - this._goto(positionOrLabel); - }; - - /** - * Advances this movie clip to the specified position or label and sets paused to true. - * @method gotoAndStop - * @param {String|Number} positionOrLabel The animation or frame name to go to. - **/ - p.gotoAndStop = function(positionOrLabel) { - this.paused = true; - this._goto(positionOrLabel); - }; - - /** - * Advances the playhead. This occurs automatically each tick by default. - * @param [time] {Number} The amount of time in ms to advance by. Only applicable if framerate is set. - * @method advance - */ - p.advance = function(time) { - // TODO: should we worry at all about clips who change their own modes via frame scripts? - var independent = MovieClip.INDEPENDENT; - if (this.mode != independent) { return; } - - var o=this, fps = o.framerate; - while ((o = o.parent) && fps == null) { - if (o.mode == independent) { fps = o._framerate; } - } - this._framerate = fps; - - var t = (fps != null && fps != -1 && time != null) ? time/(1000/fps) + this._t : 1; - var frames = t|0; - this._t = t-frames; // leftover time - - while (!this.paused && frames--) { - this._prevPosition = (this._prevPos < 0) ? 0 : this._prevPosition+1; - this._updateTimeline(); - } - }; - - /** - * MovieClip instances cannot be cloned. - * @method clone - **/ - p.clone = function() { - // TODO: add support for this? Need to clone the Timeline & retarget tweens - pretty complex. - throw("MovieClip cannot be cloned.") - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[MovieClip (name="+ this.name +")]"; - }; - - -// private methods: - /** - * @method _tick - * @param {Object} evtObj An event object that will be dispatched to all tick listeners. This object is reused between dispatchers to reduce construction & GC costs. - * function. - * @protected - **/ - p._tick = function(evtObj) { - this.advance(evtObj&&evtObj.delta); - this.Container__tick(evtObj); - }; - - /** - * @method _goto - * @param {String|Number} positionOrLabel The animation name or frame number to go to. - * @protected - **/ - p._goto = function(positionOrLabel) { - var pos = this.timeline.resolve(positionOrLabel); - if (pos == null) { return; } - // prevent _updateTimeline from overwriting the new position because of a reset: - if (this._prevPos == -1) { this._prevPos = NaN; } - this._prevPosition = pos; - this._t = 0; - this._updateTimeline(); - }; - - /** - * @method _reset - * @private - **/ - p._reset = function() { - this._prevPos = -1; - this._t = this.currentFrame = 0; - this.paused = false; - }; - - /** - * @method _updateTimeline - * @protected - **/ - p._updateTimeline = function() { - var tl = this.timeline; - var synched = this.mode != MovieClip.INDEPENDENT; - tl.loop = (this.loop==null) ? true : this.loop; - - var pos = synched ? this.startPosition + (this.mode==MovieClip.SINGLE_FRAME?0:this._synchOffset) : (this._prevPos < 0 ? 0 : this._prevPosition); - var mode = synched || !this.actionsEnabled ? createjs.Tween.NONE : null; - - // pre-assign currentFrame so it is available to frame scripts: - this.currentFrame = tl._calcPosition(pos); - - // update timeline position, ignoring actions if this is a graphic. - tl.setPosition(pos, mode); - - this._prevPosition = tl._prevPosition; - if (this._prevPos == tl._prevPos) { return; } - this.currentFrame = this._prevPos = tl._prevPos; - - for (var n in this._managed) { this._managed[n] = 1; } - - var tweens = tl._tweens; - for (var i=0, l=tweens.length; i=0; i--) { - var id = kids[i].id; - if (this._managed[id] == 1) { - this.removeChildAt(i); - delete(this._managed[id]); - } - } - }; - - /** - * @method _setState - * @param {Array} state - * @param {Number} offset - * @protected - **/ - p._setState = function(state, offset) { - if (!state) { return; } - for (var i=state.length-1;i>=0;i--) { - var o = state[i]; - var target = o.t; - var props = o.p; - for (var n in props) { target[n] = props[n]; } - this._addManagedChild(target, offset); - } - }; - - /** - * Adds a child to the timeline, and sets it up as a managed child. - * @method _addManagedChild - * @param {MovieClip} child The child MovieClip to manage - * @param {Number} offset - * @private - **/ - p._addManagedChild = function(child, offset) { - if (child._off) { return; } - this.addChildAt(child,0); - - if (child instanceof MovieClip) { - child._synchOffset = offset; - // TODO: this does not precisely match Flash. Flash loses track of the clip if it is renamed or removed from the timeline, which causes it to reset. - if (child.mode == MovieClip.INDEPENDENT && child.autoReset && !this._managed[child.id]) { child._reset(); } - } - this._managed[child.id] = 2; - }; - - /** - * @method _getBounds - * @param {Matrix2D} matrix - * @param {Boolean} ignoreTransform - * @return {Rectangle} - * @protected - **/ - p._getBounds = function(matrix, ignoreTransform) { - var bounds = this.DisplayObject_getBounds(); - if (!bounds) { - this._updateTimeline(); - if (this.frameBounds) { bounds = this._rectangle.copy(this.frameBounds[this.currentFrame]); } - } - if (bounds) { return this._transformBounds(bounds, matrix, ignoreTransform); } - return this.Container__getBounds(matrix, ignoreTransform); - }; - - - createjs.MovieClip = createjs.promote(MovieClip, "Container"); - - - -// MovieClipPlugin for TweenJS: - /** - * This plugin works with TweenJS to prevent the startPosition - * property from tweening. - * @private - * @class MovieClipPlugin - * @constructor - **/ - function MovieClipPlugin() { - throw("MovieClipPlugin cannot be instantiated.") - } - - /** - * @method priority - * @private - **/ - MovieClipPlugin.priority = 100; // very high priority, should run first - - /** - * @method install - * @private - **/ - MovieClipPlugin.install = function() { - createjs.Tween.installPlugin(MovieClipPlugin, ["startPosition"]); - }; - - /** - * @method init - * @param {Tween} tween - * @param {String} prop - * @param {String|Number|Boolean} value - * @private - **/ - MovieClipPlugin.init = function(tween, prop, value) { - return value; - }; - - /** - * @method step - * @private - **/ - MovieClipPlugin.step = function() { - // unused. - }; - - /** - * @method tween - * @param {Tween} tween - * @param {String} prop - * @param {String | Number | Boolean} value - * @param {Array} startValues - * @param {Array} endValues - * @param {Number} ratio - * @param {Object} wait - * @param {Object} end - * @return {*} - */ - MovieClipPlugin.tween = function(tween, prop, value, startValues, endValues, ratio, wait, end) { - if (!(tween.target instanceof MovieClip)) { return value; } - return (ratio == 1 ? endValues[prop] : startValues[prop]); - }; - -}()); - -//############################################################################## -// SpriteSheetUtils.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * The SpriteSheetUtils class is a collection of static methods for working with {{#crossLink "SpriteSheet"}}{{/crossLink}}s. - * A sprite sheet is a series of images (usually animation frames) combined into a single image on a regular grid. For - * example, an animation consisting of 8 100x100 images could be combined into a 400x200 sprite sheet (4 frames across - * by 2 high). The SpriteSheetUtils class uses a static interface and should not be instantiated. - * @class SpriteSheetUtils - * @static - **/ - function SpriteSheetUtils() { - throw "SpriteSheetUtils cannot be instantiated"; - } - - -// private static properties: - /** - * @property _workingCanvas - * @static - * @type HTMLCanvasElement | Object - * @protected - */ - /** - * @property _workingContext - * @static - * @type CanvasRenderingContext2D - * @protected - */ - var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")); - if (canvas.getContext) { - SpriteSheetUtils._workingCanvas = canvas; - SpriteSheetUtils._workingContext = canvas.getContext("2d"); - canvas.width = canvas.height = 1; - } - - -// public static methods: - /** - * This is an experimental method, and may be buggy. Please report issues.

    - * Extends the existing sprite sheet by flipping the original frames horizontally, vertically, or both, - * and adding appropriate animation & frame data. The flipped animations will have a suffix added to their names - * (_h, _v, _hv as appropriate). Make sure the sprite sheet images are fully loaded before using this method. - *

    - * For example:
    - * SpriteSheetUtils.addFlippedFrames(mySpriteSheet, true, true); - * The above would add frames that are flipped horizontally AND frames that are flipped vertically. - *

    - * Note that you can also flip any display object by setting its scaleX or scaleY to a negative value. On some - * browsers (especially those without hardware accelerated canvas) this can result in slightly degraded performance, - * which is why addFlippedFrames is available. - * @method addFlippedFrames - * @static - * @param {SpriteSheet} spriteSheet - * @param {Boolean} horizontal If true, horizontally flipped frames will be added. - * @param {Boolean} vertical If true, vertically flipped frames will be added. - * @param {Boolean} both If true, frames that are flipped both horizontally and vertically will be added. - * @deprecated Modern browsers perform better when flipping via a transform (ex. scaleX=-1) rendering this obsolete. - **/ - SpriteSheetUtils.addFlippedFrames = function(spriteSheet, horizontal, vertical, both) { - if (!horizontal && !vertical && !both) { return; } - - var count = 0; - if (horizontal) { SpriteSheetUtils._flip(spriteSheet,++count,true,false); } - if (vertical) { SpriteSheetUtils._flip(spriteSheet,++count,false,true); } - if (both) { SpriteSheetUtils._flip(spriteSheet,++count,true,true); } - }; - - /** - * Returns a single frame of the specified sprite sheet as a new PNG image. An example of when this may be useful is - * to use a spritesheet frame as the source for a bitmap fill. - * - * WARNING: In almost all cases it is better to display a single frame using a {{#crossLink "Sprite"}}{{/crossLink}} - * with a {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} call than it is to slice out a frame using this - * method and display it with a Bitmap instance. You can also crop an image using the {{#crossLink "Bitmap/sourceRect"}}{{/crossLink}} - * property of {{#crossLink "Bitmap"}}{{/crossLink}}. - * - * The extractFrame method may cause cross-domain warnings since it accesses pixels directly on the canvas. - * @method extractFrame - * @static - * @param {SpriteSheet} spriteSheet The SpriteSheet instance to extract a frame from. - * @param {Number|String} frameOrAnimation The frame number or animation name to extract. If an animation - * name is specified, only the first frame of the animation will be extracted. - * @return {HTMLImageElement} a single frame of the specified sprite sheet as a new PNG image. - */ - SpriteSheetUtils.extractFrame = function(spriteSheet, frameOrAnimation) { - if (isNaN(frameOrAnimation)) { - frameOrAnimation = spriteSheet.getAnimation(frameOrAnimation).frames[0]; - } - var data = spriteSheet.getFrame(frameOrAnimation); - if (!data) { return null; } - var r = data.rect; - var canvas = SpriteSheetUtils._workingCanvas; - canvas.width = r.width; - canvas.height = r.height; - SpriteSheetUtils._workingContext.drawImage(data.image, r.x, r.y, r.width, r.height, 0, 0, r.width, r.height); - var img = document.createElement("img"); - img.src = canvas.toDataURL("image/png"); - return img; - }; - - /** - * Merges the rgb channels of one image with the alpha channel of another. This can be used to combine a compressed - * JPEG image containing color data with a PNG32 monochromatic image containing alpha data. With certain types of - * images (those with detail that lend itself to JPEG compression) this can provide significant file size savings - * versus a single RGBA PNG32. This method is very fast (generally on the order of 1-2 ms to run). - * @method mergeAlpha - * @static - * @param {HTMLImageElement} rbgImage The image (or canvas) containing the RGB channels to use. - * @param {HTMLImageElement} alphaImage The image (or canvas) containing the alpha channel to use. - * @param {HTMLCanvasElement} canvas Optional. If specified, this canvas will be used and returned. If not, a new canvas will be created. - * @return {HTMLCanvasElement} A canvas with the combined image data. This can be used as a source for Bitmap or SpriteSheet. - * @deprecated Tools such as ImageAlpha generally provide better results. This will be moved to sandbox in the future. - */ - SpriteSheetUtils.mergeAlpha = function(rgbImage, alphaImage, canvas) { - if (!canvas) { canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); } - canvas.width = Math.max(alphaImage.width, rgbImage.width); - canvas.height = Math.max(alphaImage.height, rgbImage.height); - var ctx = canvas.getContext("2d"); - ctx.save(); - ctx.drawImage(rgbImage,0,0); - ctx.globalCompositeOperation = "destination-in"; - ctx.drawImage(alphaImage,0,0); - ctx.restore(); - return canvas; - }; - - -// private static methods: - SpriteSheetUtils._flip = function(spriteSheet, count, h, v) { - var imgs = spriteSheet._images; - var canvas = SpriteSheetUtils._workingCanvas; - var ctx = SpriteSheetUtils._workingContext; - var il = imgs.length/count; - for (var i=0;iREMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// constants: - SpriteSheetBuilder.ERR_DIMENSIONS = "frame dimensions exceed max spritesheet dimensions"; - SpriteSheetBuilder.ERR_RUNNING = "a build is already running"; - -// events: - /** - * Dispatched when a build completes. - * @event complete - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.6.0 - */ - - /** - * Dispatched when an asynchronous build has progress. - * @event progress - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {Number} progress The current progress value (0-1). - * @since 0.6.0 - */ - - -// public methods: - /** - * Adds a frame to the {{#crossLink "SpriteSheet"}}{{/crossLink}}. Note that the frame will not be drawn until you - * call {{#crossLink "SpriteSheetBuilder/build"}}{{/crossLink}} method. The optional setup params allow you to have - * a function run immediately before the draw occurs. For example, this allows you to add a single source multiple - * times, but manipulate it or its children to change it to generate different frames. - * - * Note that the source's transformations (x, y, scale, rotate, alpha) will be ignored, except for regX/Y. To apply - * transforms to a source object and have them captured in the SpriteSheet, simply place it into a {{#crossLink "Container"}}{{/crossLink}} - * and pass in the Container as the source. - * @method addFrame - * @param {DisplayObject} source The source {{#crossLink "DisplayObject"}}{{/crossLink}} to draw as the frame. - * @param {Rectangle} [sourceRect] A {{#crossLink "Rectangle"}}{{/crossLink}} defining the portion of the - * source to draw to the frame. If not specified, it will look for a `getBounds` method, bounds property, or - * `nominalBounds` property on the source to use. If one is not found, the frame will be skipped. - * @param {Number} [scale=1] Optional. The scale to draw this frame at. Default is 1. - * @param {Function} [setupFunction] A function to call immediately before drawing this frame. It will be called with two parameters: the source, and setupData. - * @param {Object} [setupData] Arbitrary setup data to pass to setupFunction as the second parameter. - * @return {Number} The index of the frame that was just added, or null if a sourceRect could not be determined. - **/ - p.addFrame = function(source, sourceRect, scale, setupFunction, setupData) { - if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; } - var rect = sourceRect||source.bounds||source.nominalBounds; - if (!rect&&source.getBounds) { rect = source.getBounds(); } - if (!rect) { return null; } - scale = scale||1; - return this._frames.push({source:source, sourceRect:rect, scale:scale, funct:setupFunction, data:setupData, index:this._frames.length, height:rect.height*scale})-1; - }; - - /** - * Adds an animation that will be included in the created {{#crossLink "SpriteSheet"}}{{/crossLink}}. - * @method addAnimation - * @param {String} name The name for the animation. - * @param {Array} frames An array of frame indexes that comprise the animation. Ex. [3,6,5] would describe an animation - * that played frame indexes 3, 6, and 5 in that order. - * @param {String} [next] Specifies the name of the animation to continue to after this animation ends. You can - * also pass false to have the animation stop when it ends. By default it will loop to the start of the same animation. - * @param {Number} [speed] Specifies a frame advance speed for this animation. For example, a value of 0.5 would - * cause the animation to advance every second tick. Note that earlier versions used `frequency` instead, which had - * the opposite effect. - **/ - p.addAnimation = function(name, frames, next, speed) { - if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; } - this._animations[name] = {frames:frames, next:next, speed:speed}; - }; - - /** - * This will take a {{#crossLink "MovieClip"}}{{/crossLink}} instance, and add its frames and labels to this - * builder. Labels will be added as an animation running from the label index to the next label. For example, if - * there is a label named "foo" at frame 0 and a label named "bar" at frame 10, in a MovieClip with 15 frames, it - * will add an animation named "foo" that runs from frame index 0 to 9, and an animation named "bar" that runs from - * frame index 10 to 14. - * - * Note that this will iterate through the full MovieClip with {{#crossLink "MovieClip/actionsEnabled:property"}}{{/crossLink}} - * set to `false`, ending on the last frame. - * @method addMovieClip - * @param {MovieClip} source The source MovieClip instance to add to the SpriteSheet. - * @param {Rectangle} [sourceRect] A {{#crossLink "Rectangle"}}{{/crossLink}} defining the portion of the source to - * draw to the frame. If not specified, it will look for a {{#crossLink "DisplayObject/getBounds"}}{{/crossLink}} - * method, `frameBounds` Array, `bounds` property, or `nominalBounds` property on the source to use. If one is not - * found, the MovieClip will be skipped. - * @param {Number} [scale=1] The scale to draw the movie clip at. - * @param {Function} [setupFunction] A function to call immediately before drawing each frame. It will be called - * with three parameters: the source, setupData, and the frame index. - * @param {Object} [setupData] Arbitrary setup data to pass to setupFunction as the second parameter. - * @param {Function} [labelFunction] This method will be called for each MovieClip label that is added with four - * parameters: the label name, the source MovieClip instance, the starting frame index (in the movieclip timeline) - * and the end index. It must return a new name for the label/animation, or `false` to exclude the label. - **/ - p.addMovieClip = function(source, sourceRect, scale, setupFunction, setupData, labelFunction) { - if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; } - var rects = source.frameBounds; - var rect = sourceRect||source.bounds||source.nominalBounds; - if (!rect&&source.getBounds) { rect = source.getBounds(); } - if (!rect && !rects) { return; } - - var i, l, baseFrameIndex = this._frames.length; - var duration = source.timeline.duration; - for (i=0; i this.maxHeight) { throw SpriteSheetBuilder.ERR_DIMENSIONS; } - var y=0, x=0; - var img = 0; - while (frames.length) { - var o = this._fillRow(frames, y, img, dataFrames, pad); - if (o.w > x) { x = o.w; } - y += o.h; - if (!o.h || !frames.length) { - var canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); - canvas.width = this._getSize(x,this.maxWidth); - canvas.height = this._getSize(y,this.maxHeight); - this._data.images[img] = canvas; - if (!o.h) { - x=y=0; - img++; - } - } - } - }; - - /** - * @method _setupMovieClipFrame - * @protected - * @return {Number} The width & height of the row. - **/ - p._setupMovieClipFrame = function(source, data) { - var ae = source.actionsEnabled; - source.actionsEnabled = false; - source.gotoAndStop(data.i); - source.actionsEnabled = ae; - data.f&&data.f(source, data.d, data.i); - }; - - /** - * @method _getSize - * @protected - * @return {Number} The width & height of the row. - **/ - p._getSize = function(size,max) { - var pow = 4; - while (Math.pow(2,++pow) < size){} - return Math.min(max,Math.pow(2,pow)); - }; - - /** - * @method _fillRow - * @param {Array} frames - * @param {Number} y - * @param {HTMLImageElement} img - * @param {Object} dataFrames - * @param {Number} pad - * @protected - * @return {Number} The width & height of the row. - **/ - p._fillRow = function(frames, y, img, dataFrames, pad) { - var w = this.maxWidth; - var maxH = this.maxHeight; - y += pad; - var h = maxH-y; - var x = pad; - var height = 0; - for (var i=frames.length-1; i>=0; i--) { - var frame = frames[i]; - var sc = this._scale*frame.scale; - var rect = frame.sourceRect; - var source = frame.source; - var rx = Math.floor(sc*rect.x-pad); - var ry = Math.floor(sc*rect.y-pad); - var rh = Math.ceil(sc*rect.height+pad*2); - var rw = Math.ceil(sc*rect.width+pad*2); - if (rw > w) { throw SpriteSheetBuilder.ERR_DIMENSIONS; } - if (rh > h || x+rw > w) { continue; } - frame.img = img; - frame.rect = new createjs.Rectangle(x,y,rw,rh); - height = height || rh; - frames.splice(i,1); - dataFrames[frame.index] = [x,y,rw,rh,img,Math.round(-rx+sc*source.regX-pad),Math.round(-ry+sc*source.regY-pad)]; - x += rw; - } - return {w:x, h:height}; - }; - - /** - * @method _endBuild - * @protected - **/ - p._endBuild = function() { - this.spriteSheet = new createjs.SpriteSheet(this._data); - this._data = null; - this.progress = 1; - this.dispatchEvent("complete"); - }; - - /** - * @method _run - * @protected - **/ - p._run = function() { - var ts = Math.max(0.01, Math.min(0.99, this.timeSlice||0.3))*50; - var t = (new Date()).getTime()+ts; - var complete = false; - while (t > (new Date()).getTime()) { - if (!this._drawNext()) { complete = true; break; } - } - if (complete) { - this._endBuild(); - } else { - var _this = this; - this._timerID = setTimeout(function() { _this._run(); }, 50-ts); - } - var p = this.progress = this._index/this._frames.length; - if (this.hasEventListener("progress")) { - var evt = new createjs.Event("progress"); - evt.progress = p; - this.dispatchEvent(evt); - } - }; - - /** - * @method _drawNext - * @protected - * @return Boolean Returns false if this is the last draw. - **/ - p._drawNext = function() { - var frame = this._frames[this._index]; - var sc = frame.scale*this._scale; - var rect = frame.rect; - var sourceRect = frame.sourceRect; - var canvas = this._data.images[frame.img]; - var ctx = canvas.getContext("2d"); - frame.funct&&frame.funct(frame.source, frame.data); - ctx.save(); - ctx.beginPath(); - ctx.rect(rect.x, rect.y, rect.width, rect.height); - ctx.clip(); - ctx.translate(Math.ceil(rect.x-sourceRect.x*sc), Math.ceil(rect.y-sourceRect.y*sc)); - ctx.scale(sc,sc); - frame.source.draw(ctx); // display object will draw itself. - ctx.restore(); - return (++this._index) < this._frames.length; - }; - - - createjs.SpriteSheetBuilder = createjs.promote(SpriteSheetBuilder, "EventDispatcher"); -}()); - -//############################################################################## -// DOMElement.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * This class is still experimental, and more advanced use is likely to be buggy. Please report bugs. - * - * A DOMElement allows you to associate a HTMLElement with the display list. It will be transformed - * within the DOM as though it is child of the {{#crossLink "Container"}}{{/crossLink}} it is added to. However, it is - * not rendered to canvas, and as such will retain whatever z-index it has relative to the canvas (ie. it will be - * drawn in front of or behind the canvas). - * - * The position of a DOMElement is relative to their parent node in the DOM. It is recommended that - * the DOM Object be added to a div that also contains the canvas so that they share the same position - * on the page. - * - * DOMElement is useful for positioning HTML elements over top of canvas content, and for elements - * that you want to display outside the bounds of the canvas. For example, a tooltip with rich HTML - * content. - * - *

    Mouse Interaction

    - * - * DOMElement instances are not full EaselJS display objects, and do not participate in EaselJS mouse - * events or support methods like hitTest. To get mouse events from a DOMElement, you must instead add handlers to - * the htmlElement (note, this does not support EventDispatcher) - * - * var domElement = new createjs.DOMElement(htmlElement); - * domElement.htmlElement.onclick = function() { - * console.log("clicked"); - * } - * - * @class DOMElement - * @extends DisplayObject - * @constructor - * @param {HTMLElement} htmlElement A reference or id for the DOM element to manage. - */ - function DOMElement(htmlElement) { - this.DisplayObject_constructor(); - - if (typeof(htmlElement)=="string") { htmlElement = document.getElementById(htmlElement); } - this.mouseEnabled = false; - - var style = htmlElement.style; - style.position = "absolute"; - style.transformOrigin = style.WebkitTransformOrigin = style.msTransformOrigin = style.MozTransformOrigin = style.OTransformOrigin = "0% 0%"; - - - // public properties: - /** - * The DOM object to manage. - * @property htmlElement - * @type HTMLElement - */ - this.htmlElement = htmlElement; - - - // private properties: - /** - * @property _oldMtx - * @type Matrix2D - * @protected - */ - this._oldProps = null; - } - var p = createjs.extend(DOMElement, createjs.DisplayObject); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// public methods: - /** - * Returns true or false indicating whether the display object would be visible if drawn to a canvas. - * This does not account for whether it would be visible within the boundaries of the stage. - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method isVisible - * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas - */ - p.isVisible = function() { - return this.htmlElement != null; - }; - - /** - * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. - * Returns true if the draw was handled (useful for overriding functionality). - * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. - * @method draw - * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. - * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache. - * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back - * into itself). - * @return {Boolean} - */ - p.draw = function(ctx, ignoreCache) { - // this relies on the _tick method because draw isn't called if the parent is not visible. - // the actual update happens in _handleDrawEnd - return true; - }; - - /** - * Not applicable to DOMElement. - * @method cache - */ - p.cache = function() {}; - - /** - * Not applicable to DOMElement. - * @method uncache - */ - p.uncache = function() {}; - - /** - * Not applicable to DOMElement. - * @method updateCache - */ - p.updateCache = function() {}; - - /** - * Not applicable to DOMElement. - * @method hitTest - */ - p.hitTest = function() {}; - - /** - * Not applicable to DOMElement. - * @method localToGlobal - */ - p.localToGlobal = function() {}; - - /** - * Not applicable to DOMElement. - * @method globalToLocal - */ - p.globalToLocal = function() {}; - - /** - * Not applicable to DOMElement. - * @method localToLocal - */ - p.localToLocal = function() {}; - - /** - * DOMElement cannot be cloned. Throws an error. - * @method clone - */ - p.clone = function() { - throw("DOMElement cannot be cloned.") - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - */ - p.toString = function() { - return "[DOMElement (name="+ this.name +")]"; - }; - - /** - * Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances - * are not full EaselJS display objects and do not participate in EaselJS mouse events. - * @event click - */ - - /** - * Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances - * are not full EaselJS display objects and do not participate in EaselJS mouse events. - * @event dblClick - */ - - /** - * Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances - * are not full EaselJS display objects and do not participate in EaselJS mouse events. - * @event mousedown - */ - - /** - * The HTMLElement can listen for the mouseover event, not the DOMElement instance. - * Since DOMElement instances are not full EaselJS display objects and do not participate in EaselJS mouse events. - * @event mouseover - */ - - /** - * Not applicable to DOMElement. - * @event tick - */ - - -// private methods: - /** - * @method _tick - * @param {Object} evtObj An event object that will be dispatched to all tick listeners. This object is reused between dispatchers to reduce construction & GC costs. - * function. - * @protected - */ - p._tick = function(evtObj) { - var stage = this.getStage(); - stage&&stage.on("drawend", this._handleDrawEnd, this, true); - this.DisplayObject__tick(evtObj); - }; - - /** - * @method _handleDrawEnd - * @param {Event} evt - * @protected - */ - p._handleDrawEnd = function(evt) { - var o = this.htmlElement; - if (!o) { return; } - var style = o.style; - - var props = this.getConcatenatedDisplayProps(this._props), mtx = props.matrix; - - var visibility = props.visible ? "visible" : "hidden"; - if (visibility != style.visibility) { style.visibility = visibility; } - if (!props.visible) { return; } - - var oldProps = this._oldProps, oldMtx = oldProps&&oldProps.matrix; - var n = 10000; // precision - - if (!oldMtx || !oldMtx.equals(mtx)) { - var str = "matrix(" + (mtx.a*n|0)/n +","+ (mtx.b*n|0)/n +","+ (mtx.c*n|0)/n +","+ (mtx.d*n|0)/n +","+ (mtx.tx+0.5|0); - style.transform = style.WebkitTransform = style.OTransform = style.msTransform = str +","+ (mtx.ty+0.5|0) +")"; - style.MozTransform = str +"px,"+ (mtx.ty+0.5|0) +"px)"; - if (!oldProps) { oldProps = this._oldProps = new createjs.DisplayProps(true, NaN); } - oldProps.matrix.copy(mtx); - } - - if (oldProps.alpha != props.alpha) { - style.opacity = ""+(props.alpha*n|0)/n; - oldProps.alpha = props.alpha; - } - }; - - - createjs.DOMElement = createjs.promote(DOMElement, "DisplayObject"); -}()); - -//############################################################################## -// Filter.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Base class that all filters should inherit from. Filters need to be applied to objects that have been cached using - * the {{#crossLink "DisplayObject/cache"}}{{/crossLink}} method. If an object changes, please cache it again, or use - * {{#crossLink "DisplayObject/updateCache"}}{{/crossLink}}. Note that the filters must be applied before caching. - * - *

    Example

    - * - * myInstance.filters = [ - * new createjs.ColorFilter(0, 0, 0, 1, 255, 0, 0), - * new createjs.BlurFilter(5, 5, 10) - * ]; - * myInstance.cache(0,0, 100, 100); - * - * Note that each filter can implement a {{#crossLink "Filter/getBounds"}}{{/crossLink}} method, which returns the - * margins that need to be applied in order to fully display the filter. For example, the {{#crossLink "BlurFilter"}}{{/crossLink}} - * will cause an object to feather outwards, resulting in a margin around the shape. - * - *

    EaselJS Filters

    - * EaselJS comes with a number of pre-built filters: - *
    • {{#crossLink "AlphaMapFilter"}}{{/crossLink}} : Map a greyscale image to the alpha channel of a display object
    • - *
    • {{#crossLink "AlphaMaskFilter"}}{{/crossLink}}: Map an image's alpha channel to the alpha channel of a display object
    • - *
    • {{#crossLink "BlurFilter"}}{{/crossLink}}: Apply vertical and horizontal blur to a display object
    • - *
    • {{#crossLink "ColorFilter"}}{{/crossLink}}: Color transform a display object
    • - *
    • {{#crossLink "ColorMatrixFilter"}}{{/crossLink}}: Transform an image using a {{#crossLink "ColorMatrix"}}{{/crossLink}}
    • - *
    - * - * @class Filter - * @constructor - **/ - function Filter() {} - var p = Filter.prototype; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// public methods: - /** - * Provides padding values for this filter. That is, how much the filter will extend the visual bounds of an object it is applied to. - * @method getBounds - * @param {Rectangle} [rect] If specified, the provided Rectangle instance will be expanded by the padding amounts and returned. - * @return {Rectangle} If a `rect` param was provided, it is returned. If not, either a new rectangle with the padding values, or null if no padding is required for this filter. - **/ - p.getBounds = function(rect) { - return rect; - }; - - /** - * Applies the filter to the specified context. - * @method applyFilter - * @param {CanvasRenderingContext2D} ctx The 2D context to use as the source. - * @param {Number} x The x position to use for the source rect. - * @param {Number} y The y position to use for the source rect. - * @param {Number} width The width to use for the source rect. - * @param {Number} height The height to use for the source rect. - * @param {CanvasRenderingContext2D} [targetCtx] The 2D context to draw the result to. Defaults to the context passed to ctx. - * @param {Number} [targetX] The x position to draw the result to. Defaults to the value passed to x. - * @param {Number} [targetY] The y position to draw the result to. Defaults to the value passed to y. - * @return {Boolean} If the filter was applied successfully. - **/ - p.applyFilter = function(ctx, x, y, width, height, targetCtx, targetX, targetY) { - // this is the default behaviour because most filters access pixel data. It is overridden when not needed. - targetCtx = targetCtx || ctx; - if (targetX == null) { targetX = x; } - if (targetY == null) { targetY = y; } - try { - var imageData = ctx.getImageData(x, y, width, height); - } catch (e) { - return false; - } - if (this._applyFilter(imageData)) { - targetCtx.putImageData(imageData, targetX, targetY); - return true; - } - return false; - }; - - /** - * Returns a string representation of this object. - * @method toString - * @return {String} a string representation of the instance. - **/ - p.toString = function() { - return "[Filter]"; - }; - - /** - * Returns a clone of this Filter instance. - * @method clone - * @return {Filter} A clone of the current Filter instance. - **/ - p.clone = function() { - return new Filter(); - }; - -// private methods: - /** - * @method _applyFilter - * @param {ImageData} imageData Target ImageData instance. - * @return {Boolean} - **/ - p._applyFilter = function(imageData) { return true; }; - - - createjs.Filter = Filter; -}()); - -//############################################################################## -// BlurFilter.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Applies a box blur to DisplayObjects. Note that this filter is fairly CPU intensive, particularly if the quality is - * set higher than 1. - * - *

    Example

    - * This example creates a red circle, and then applies a 5 pixel blur to it. It uses the {{#crossLink "Filter/getBounds"}}{{/crossLink}} - * method to account for the spread that the blur causes. - * - * var shape = new createjs.Shape().set({x:100,y:100}); - * shape.graphics.beginFill("#ff0000").drawCircle(0,0,50); - * - * var blurFilter = new createjs.BlurFilter(5, 5, 1); - * shape.filters = [blurFilter]; - * var bounds = blurFilter.getBounds(); - * - * shape.cache(-50+bounds.x, -50+bounds.y, 100+bounds.width, 100+bounds.height); - * - * See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters. - * @class BlurFilter - * @extends Filter - * @constructor - * @param {Number} [blurX=0] The horizontal blur radius in pixels. - * @param {Number} [blurY=0] The vertical blur radius in pixels. - * @param {Number} [quality=1] The number of blur iterations. - **/ - function BlurFilter( blurX, blurY, quality) { - if ( isNaN(blurX) || blurX < 0 ) blurX = 0; - if ( isNaN(blurY) || blurY < 0 ) blurY = 0; - if ( isNaN(quality) || quality < 1 ) quality = 1; - - - // public properties: - /** - * Horizontal blur radius in pixels - * @property blurX - * @default 0 - * @type Number - **/ - this.blurX = blurX | 0; - - /** - * Vertical blur radius in pixels - * @property blurY - * @default 0 - * @type Number - **/ - this.blurY = blurY | 0; - - /** - * Number of blur iterations. For example, a value of 1 will produce a rough blur. A value of 2 will produce a - * smoother blur, but take twice as long to run. - * @property quality - * @default 1 - * @type Number - **/ - this.quality = quality | 0; - } - var p = createjs.extend(BlurFilter, createjs.Filter); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// constants: - /** - * Array of multiply values for blur calculations. - * @property MUL_TABLE - * @type Array - * @protected - * @static - **/ - BlurFilter.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]; - - /** - * Array of shift values for blur calculations. - * @property SHG_TABLE - * @type Array - * @protected - * @static - **/ - BlurFilter.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]; - -// public methods: - /** docced in super class **/ - p.getBounds = function (rect) { - var x = this.blurX|0, y = this.blurY| 0; - if (x <= 0 && y <= 0) { return rect; } - var q = Math.pow(this.quality, 0.2); - return (rect || new createjs.Rectangle()).pad(x*q+1,y*q+1,x*q+1,y*q+1); - }; - - /** docced in super class **/ - p.clone = function() { - return new BlurFilter(this.blurX, this.blurY, this.quality); - }; - - /** docced in super class **/ - p.toString = function() { - return "[BlurFilter]"; - }; - - -// private methods: - - /** docced in super class **/ - p._applyFilter = function (imageData) { - - var radiusX = this.blurX >> 1; - if (isNaN(radiusX) || radiusX < 0) return false; - var radiusY = this.blurY >> 1; - if (isNaN(radiusY) || radiusY < 0) return false; - if (radiusX == 0 && radiusY == 0) return false; - - var iterations = this.quality; - if (isNaN(iterations) || iterations < 1) iterations = 1; - iterations |= 0; - if (iterations > 3) iterations = 3; - if (iterations < 1) iterations = 1; - - var px = imageData.data; - var x=0, y=0, i=0, p=0, yp=0, yi=0, yw=0, r=0, g=0, b=0, a=0, pr=0, pg=0, pb=0, pa=0; - - var divx = (radiusX + radiusX + 1) | 0; - var divy = (radiusY + radiusY + 1) | 0; - var w = imageData.width | 0; - var h = imageData.height | 0; - - var w1 = (w - 1) | 0; - var h1 = (h - 1) | 0; - var rxp1 = (radiusX + 1) | 0; - var ryp1 = (radiusY + 1) | 0; - - var ssx = {r:0,b:0,g:0,a:0}; - var sx = ssx; - for ( i = 1; i < divx; i++ ) - { - sx = sx.n = {r:0,b:0,g:0,a:0}; - } - sx.n = ssx; - - var ssy = {r:0,b:0,g:0,a:0}; - var sy = ssy; - for ( i = 1; i < divy; i++ ) - { - sy = sy.n = {r:0,b:0,g:0,a:0}; - } - sy.n = ssy; - - var si = null; - - - var mtx = BlurFilter.MUL_TABLE[radiusX] | 0; - var stx = BlurFilter.SHG_TABLE[radiusX] | 0; - var mty = BlurFilter.MUL_TABLE[radiusY] | 0; - var sty = BlurFilter.SHG_TABLE[radiusY] | 0; - - while (iterations-- > 0) { - - yw = yi = 0; - var ms = mtx; - var ss = stx; - for (y = h; --y > -1;) { - r = rxp1 * (pr = px[(yi) | 0]); - g = rxp1 * (pg = px[(yi + 1) | 0]); - b = rxp1 * (pb = px[(yi + 2) | 0]); - a = rxp1 * (pa = px[(yi + 3) | 0]); - - sx = ssx; - - for( i = rxp1; --i > -1; ) - { - sx.r = pr; - sx.g = pg; - sx.b = pb; - sx.a = pa; - sx = sx.n; - } - - for( i = 1; i < rxp1; i++ ) - { - p = (yi + ((w1 < i ? w1 : i) << 2)) | 0; - r += ( sx.r = px[p]); - g += ( sx.g = px[p+1]); - b += ( sx.b = px[p+2]); - a += ( sx.a = px[p+3]); - - sx = sx.n; - } - - si = ssx; - for ( x = 0; x < w; x++ ) - { - px[yi++] = (r * ms) >>> ss; - px[yi++] = (g * ms) >>> ss; - px[yi++] = (b * ms) >>> ss; - px[yi++] = (a * ms) >>> ss; - - p = ((yw + ((p = x + radiusX + 1) < w1 ? p : w1)) << 2); - - r -= si.r - ( si.r = px[p]); - g -= si.g - ( si.g = px[p+1]); - b -= si.b - ( si.b = px[p+2]); - a -= si.a - ( si.a = px[p+3]); - - si = si.n; - - } - yw += w; - } - - ms = mty; - ss = sty; - for (x = 0; x < w; x++) { - yi = (x << 2) | 0; - - r = (ryp1 * (pr = px[yi])) | 0; - g = (ryp1 * (pg = px[(yi + 1) | 0])) | 0; - b = (ryp1 * (pb = px[(yi + 2) | 0])) | 0; - a = (ryp1 * (pa = px[(yi + 3) | 0])) | 0; - - sy = ssy; - for( i = 0; i < ryp1; i++ ) - { - sy.r = pr; - sy.g = pg; - sy.b = pb; - sy.a = pa; - sy = sy.n; - } - - yp = w; - - for( i = 1; i <= radiusY; i++ ) - { - yi = ( yp + x ) << 2; - - r += ( sy.r = px[yi]); - g += ( sy.g = px[yi+1]); - b += ( sy.b = px[yi+2]); - a += ( sy.a = px[yi+3]); - - sy = sy.n; - - if( i < h1 ) - { - yp += w; - } - } - - yi = x; - si = ssy; - if ( iterations > 0 ) - { - for ( y = 0; y < h; y++ ) - { - p = yi << 2; - px[p+3] = pa =(a * ms) >>> ss; - if ( pa > 0 ) - { - px[p] = ((r * ms) >>> ss ); - px[p+1] = ((g * ms) >>> ss ); - px[p+2] = ((b * ms) >>> ss ); - } else { - px[p] = px[p+1] = px[p+2] = 0 - } - - p = ( x + (( ( p = y + ryp1) < h1 ? p : h1 ) * w )) << 2; - - r -= si.r - ( si.r = px[p]); - g -= si.g - ( si.g = px[p+1]); - b -= si.b - ( si.b = px[p+2]); - a -= si.a - ( si.a = px[p+3]); - - si = si.n; - - yi += w; - } - } else { - for ( y = 0; y < h; y++ ) - { - p = yi << 2; - px[p+3] = pa =(a * ms) >>> ss; - if ( pa > 0 ) - { - pa = 255 / pa; - px[p] = ((r * ms) >>> ss ) * pa; - px[p+1] = ((g * ms) >>> ss ) * pa; - px[p+2] = ((b * ms) >>> ss ) * pa; - } else { - px[p] = px[p+1] = px[p+2] = 0 - } - - p = ( x + (( ( p = y + ryp1) < h1 ? p : h1 ) * w )) << 2; - - r -= si.r - ( si.r = px[p]); - g -= si.g - ( si.g = px[p+1]); - b -= si.b - ( si.b = px[p+2]); - a -= si.a - ( si.a = px[p+3]); - - si = si.n; - - yi += w; - } - } - } - - } - return true; - }; - - createjs.BlurFilter = createjs.promote(BlurFilter, "Filter"); -}()); - -//############################################################################## -// AlphaMapFilter.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - -// constructor: - /** - * Applies a greyscale alpha map image (or canvas) to the target, such that the alpha channel of the result will - * be copied from the red channel of the map, and the RGB channels will be copied from the target. - * - * Generally, it is recommended that you use {{#crossLink "AlphaMaskFilter"}}{{/crossLink}}, because it has much - * better performance. - * - *

    Example

    - * This example draws a red->blue box, caches it, and then uses the cache canvas as an alpha map on a 100x100 image. - * - * var box = new createjs.Shape(); - * box.graphics.beginLinearGradientFill(["#ff0000", "#0000ff"], [0, 1], 0, 0, 0, 100) - * box.graphics.drawRect(0, 0, 100, 100); - * box.cache(0, 0, 100, 100); - * - * var bmp = new createjs.Bitmap("path/to/image.jpg"); - * bmp.filters = [ - * new createjs.AlphaMapFilter(box.cacheCanvas) - * ]; - * bmp.cache(0, 0, 100, 100); - * stage.addChild(bmp); - * - * See {{#crossLink "Filter"}}{{/crossLink}} for more information on applying filters. - * @class AlphaMapFilter - * @extends Filter - * @constructor - * @param {HTMLImageElement|HTMLCanvasElement} alphaMap The greyscale image (or canvas) to use as the alpha value for the - * result. This should be exactly the same dimensions as the target. - **/ - function AlphaMapFilter(alphaMap) { - - - // public properties: - /** - * The greyscale image (or canvas) to use as the alpha value for the result. This should be exactly the same - * dimensions as the target. - * @property alphaMap - * @type HTMLImageElement|HTMLCanvasElement - **/ - this.alphaMap = alphaMap; - - - // private properties: - /** - * @property _alphaMap - * @protected - * @type HTMLImageElement|HTMLCanvasElement - **/ - this._alphaMap = null; - - /** - * @property _mapData - * @protected - * @type Uint8ClampedArray - **/ - this._mapData = null; - } - var p = createjs.extend(AlphaMapFilter, createjs.Filter); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// public methods: - /** docced in super class **/ - p.clone = function () { - var o = new AlphaMapFilter(this.alphaMap); - o._alphaMap = this._alphaMap; - o._mapData = this._mapData; - return o; - }; - - /** docced in super class **/ - p.toString = function () { - return "[AlphaMapFilter]"; - }; - - -// private methods: - /** docced in super class **/ - p._applyFilter = function (imageData) { - if (!this.alphaMap) { return true; } - if (!this._prepAlphaMap()) { return false; } - - // TODO: update to support scenarios where the target has different dimensions. - var data = imageData.data; - var map = this._mapData; - for(var i=0, l=data.length; iIMPORTANT NOTE: This filter currently does not support the targetCtx, or targetX/Y parameters correctly. - * - *

    Example

    - * This example draws a gradient box, then caches it and uses the "cacheCanvas" as the alpha mask on a 100x100 image. - * - * var box = new createjs.Shape(); - * box.graphics.beginLinearGradientFill(["#000000", "rgba(0, 0, 0, 0)"], [0, 1], 0, 0, 100, 100) - * box.graphics.drawRect(0, 0, 100, 100); - * box.cache(0, 0, 100, 100); - * - * var bmp = new createjs.Bitmap("path/to/image.jpg"); - * bmp.filters = [ - * new createjs.AlphaMaskFilter(box.cacheCanvas) - * ]; - * bmp.cache(0, 0, 100, 100); - * - * See {{#crossLink "Filter"}}{{/crossLink}} for more information on applying filters. - * @class AlphaMaskFilter - * @extends Filter - * @constructor - * @param {HTMLImageElement|HTMLCanvasElement} mask - **/ - function AlphaMaskFilter(mask) { - - - // public properties: - /** - * The image (or canvas) to use as the mask. - * @property mask - * @type HTMLImageElement|HTMLCanvasElement - **/ - this.mask = mask; - } - var p = createjs.extend(AlphaMaskFilter, createjs.Filter); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// public methods: - /** - * Applies the filter to the specified context. - * - * IMPORTANT NOTE: This filter currently does not support the targetCtx, or targetX/Y parameters - * correctly. - * @method applyFilter - * @param {CanvasRenderingContext2D} ctx The 2D context to use as the source. - * @param {Number} x The x position to use for the source rect. - * @param {Number} y The y position to use for the source rect. - * @param {Number} width The width to use for the source rect. - * @param {Number} height The height to use for the source rect. - * @param {CanvasRenderingContext2D} [targetCtx] NOT SUPPORTED IN THIS FILTER. The 2D context to draw the result to. Defaults to the context passed to ctx. - * @param {Number} [targetX] NOT SUPPORTED IN THIS FILTER. The x position to draw the result to. Defaults to the value passed to x. - * @param {Number} [targetY] NOT SUPPORTED IN THIS FILTER. The y position to draw the result to. Defaults to the value passed to y. - * @return {Boolean} If the filter was applied successfully. - **/ - p.applyFilter = function (ctx, x, y, width, height, targetCtx, targetX, targetY) { - if (!this.mask) { return true; } - targetCtx = targetCtx || ctx; - if (targetX == null) { targetX = x; } - if (targetY == null) { targetY = y; } - - targetCtx.save(); - if (ctx != targetCtx) { - // TODO: support targetCtx and targetX/Y - // clearRect, then draw the ctx in? - return false; - } - - targetCtx.globalCompositeOperation = "destination-in"; - targetCtx.drawImage(this.mask, targetX, targetY); - targetCtx.restore(); - return true; - }; - - /** docced in super class **/ - p.clone = function () { - return new AlphaMaskFilter(this.mask); - }; - - /** docced in super class **/ - p.toString = function () { - return "[AlphaMaskFilter]"; - }; - - - createjs.AlphaMaskFilter = createjs.promote(AlphaMaskFilter, "Filter"); -}()); - -//############################################################################## -// ColorFilter.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Applies a color transform to DisplayObjects. - * - *

    Example

    - * This example draws a red circle, and then transforms it to Blue. This is accomplished by multiplying all the channels - * to 0 (except alpha, which is set to 1), and then adding 255 to the blue channel. - * - * var shape = new createjs.Shape().set({x:100,y:100}); - * shape.graphics.beginFill("#ff0000").drawCircle(0,0,50); - * - * shape.filters = [ - * new createjs.ColorFilter(0,0,0,1, 0,0,255,0) - * ]; - * shape.cache(-50, -50, 100, 100); - * - * See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters. - * @class ColorFilter - * @param {Number} [redMultiplier=1] The amount to multiply against the red channel. This is a range between 0 and 1. - * @param {Number} [greenMultiplier=1] The amount to multiply against the green channel. This is a range between 0 and 1. - * @param {Number} [blueMultiplier=1] The amount to multiply against the blue channel. This is a range between 0 and 1. - * @param {Number} [alphaMultiplier=1] The amount to multiply against the alpha channel. This is a range between 0 and 1. - * @param {Number} [redOffset=0] The amount to add to the red channel after it has been multiplied. This is a range - * between -255 and 255. - * @param {Number} [greenOffset=0] The amount to add to the green channel after it has been multiplied. This is a range - * between -255 and 255. - * @param {Number} [blueOffset=0] The amount to add to the blue channel after it has been multiplied. This is a range - * between -255 and 255. - * @param {Number} [alphaOffset=0] The amount to add to the alpha channel after it has been multiplied. This is a range - * between -255 and 255. - * @constructor - * @extends Filter - **/ - function ColorFilter(redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier, redOffset, greenOffset, blueOffset, alphaOffset) { - - - // public properties: - /** - * Red channel multiplier. - * @property redMultiplier - * @type Number - **/ - this.redMultiplier = redMultiplier != null ? redMultiplier : 1; - - /** - * Green channel multiplier. - * @property greenMultiplier - * @type Number - **/ - this.greenMultiplier = greenMultiplier != null ? greenMultiplier : 1; - - /** - * Blue channel multiplier. - * @property blueMultiplier - * @type Number - **/ - this.blueMultiplier = blueMultiplier != null ? blueMultiplier : 1; - - /** - * Alpha channel multiplier. - * @property alphaMultiplier - * @type Number - **/ - this.alphaMultiplier = alphaMultiplier != null ? alphaMultiplier : 1; - - /** - * Red channel offset (added to value). - * @property redOffset - * @type Number - **/ - this.redOffset = redOffset || 0; - - /** - * Green channel offset (added to value). - * @property greenOffset - * @type Number - **/ - this.greenOffset = greenOffset || 0; - - /** - * Blue channel offset (added to value). - * @property blueOffset - * @type Number - **/ - this.blueOffset = blueOffset || 0; - - /** - * Alpha channel offset (added to value). - * @property alphaOffset - * @type Number - **/ - this.alphaOffset = alphaOffset || 0; - } - var p = createjs.extend(ColorFilter, createjs.Filter); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// public methods: - /** docced in super class **/ - p.toString = function() { - return "[ColorFilter]"; - }; - - /** docced in super class **/ - p.clone = function() { - return new ColorFilter(this.redMultiplier, this.greenMultiplier, this.blueMultiplier, this.alphaMultiplier, this.redOffset, this.greenOffset, this.blueOffset, this.alphaOffset); - }; - - -// private methods: - /** docced in super class **/ - p._applyFilter = function(imageData) { - var data = imageData.data; - var l = data.length; - for (var i=0; iExample - * - * myColorMatrix.adjustHue(20).adjustBrightness(50); - * - * See {{#crossLink "Filter"}}{{/crossLink}} for an example of how to apply filters, or {{#crossLink "ColorMatrixFilter"}}{{/crossLink}} - * for an example of how to use ColorMatrix to change a DisplayObject's color. - * @class ColorMatrix - * @param {Number} brightness - * @param {Number} contrast - * @param {Number} saturation - * @param {Number} hue - * @constructor - **/ - function ColorMatrix(brightness, contrast, saturation, hue) { - this.setColor(brightness, contrast, saturation, hue); - } - var p = ColorMatrix.prototype; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// constants: - /** - * Array of delta values for contrast calculations. - * @property DELTA_INDEX - * @type Array - * @protected - * @static - **/ - ColorMatrix.DELTA_INDEX = [ - 0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11, - 0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24, - 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42, - 0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, - 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98, - 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54, - 1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25, - 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8, - 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0, - 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8, - 10.0 - ]; - - /** - * Identity matrix values. - * @property IDENTITY_MATRIX - * @type Array - * @protected - * @static - **/ - ColorMatrix.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 - ]; - - /** - * The constant length of a color matrix. - * @property LENGTH - * @type Number - * @protected - * @static - **/ - ColorMatrix.LENGTH = ColorMatrix.IDENTITY_MATRIX.length; - - -// public methods: - /** - * Resets the instance with the specified values. - * @method setColor - * @param {Number} brightness - * @param {Number} contrast - * @param {Number} saturation - * @param {Number} hue - * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) - * @chainable - */ - p.setColor = function(brightness,contrast,saturation,hue) { - return this.reset().adjustColor(brightness,contrast,saturation,hue); - }; - - /** - * Resets the matrix to identity values. - * @method reset - * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) - * @chainable - */ - p.reset = function() { - return this.copy(ColorMatrix.IDENTITY_MATRIX); - }; - - /** - * Shortcut method to adjust brightness, contrast, saturation and hue. - * Equivalent to calling adjustHue(hue), adjustContrast(contrast), - * adjustBrightness(brightness), adjustSaturation(saturation), in that order. - * @method adjustColor - * @param {Number} brightness - * @param {Number} contrast - * @param {Number} saturation - * @param {Number} hue - * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.adjustColor = function(brightness,contrast,saturation,hue) { - this.adjustHue(hue); - this.adjustContrast(contrast); - this.adjustBrightness(brightness); - return this.adjustSaturation(saturation); - }; - - /** - * Adjusts the brightness of pixel color by adding the specified value to the red, green and blue channels. - * Positive values will make the image brighter, negative values will make it darker. - * @method adjustBrightness - * @param {Number} value A value between -255 & 255 that will be added to the RGB channels. - * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.adjustBrightness = function(value) { - if (value == 0 || isNaN(value)) { return this; } - value = this._cleanValue(value,255); - this._multiplyMatrix([ - 1,0,0,0,value, - 0,1,0,0,value, - 0,0,1,0,value, - 0,0,0,1,0, - 0,0,0,0,1 - ]); - return this; - }; - - /** - * Adjusts the contrast of pixel color. - * Positive values will increase contrast, negative values will decrease contrast. - * @method adjustContrast - * @param {Number} value A value between -100 & 100. - * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.adjustContrast = function(value) { - if (value == 0 || isNaN(value)) { return this; } - value = this._cleanValue(value,100); - var x; - if (value<0) { - x = 127+value/100*127; - } else { - x = value%1; - if (x == 0) { - x = ColorMatrix.DELTA_INDEX[value]; - } else { - x = ColorMatrix.DELTA_INDEX[(value<<0)]*(1-x)+ColorMatrix.DELTA_INDEX[(value<<0)+1]*x; // use linear interpolation for more granularity. - } - x = x*127+127; - } - this._multiplyMatrix([ - x/127,0,0,0,0.5*(127-x), - 0,x/127,0,0,0.5*(127-x), - 0,0,x/127,0,0.5*(127-x), - 0,0,0,1,0, - 0,0,0,0,1 - ]); - return this; - }; - - /** - * Adjusts the color saturation of the pixel. - * Positive values will increase saturation, negative values will decrease saturation (trend towards greyscale). - * @method adjustSaturation - * @param {Number} value A value between -100 & 100. - * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.adjustSaturation = function(value) { - if (value == 0 || isNaN(value)) { return this; } - value = this._cleanValue(value,100); - var x = 1+((value > 0) ? 3*value/100 : value/100); - var lumR = 0.3086; - var lumG = 0.6094; - var lumB = 0.0820; - this._multiplyMatrix([ - lumR*(1-x)+x,lumG*(1-x),lumB*(1-x),0,0, - lumR*(1-x),lumG*(1-x)+x,lumB*(1-x),0,0, - lumR*(1-x),lumG*(1-x),lumB*(1-x)+x,0,0, - 0,0,0,1,0, - 0,0,0,0,1 - ]); - return this; - }; - - - /** - * Adjusts the hue of the pixel color. - * @method adjustHue - * @param {Number} value A value between -180 & 180. - * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.adjustHue = function(value) { - if (value == 0 || isNaN(value)) { return this; } - value = this._cleanValue(value,180)/180*Math.PI; - var cosVal = Math.cos(value); - var sinVal = Math.sin(value); - var lumR = 0.213; - var lumG = 0.715; - var lumB = 0.072; - this._multiplyMatrix([ - lumR+cosVal*(1-lumR)+sinVal*(-lumR),lumG+cosVal*(-lumG)+sinVal*(-lumG),lumB+cosVal*(-lumB)+sinVal*(1-lumB),0,0, - lumR+cosVal*(-lumR)+sinVal*(0.143),lumG+cosVal*(1-lumG)+sinVal*(0.140),lumB+cosVal*(-lumB)+sinVal*(-0.283),0,0, - lumR+cosVal*(-lumR)+sinVal*(-(1-lumR)),lumG+cosVal*(-lumG)+sinVal*(lumG),lumB+cosVal*(1-lumB)+sinVal*(lumB),0,0, - 0,0,0,1,0, - 0,0,0,0,1 - ]); - return this; - }; - - /** - * Concatenates (multiplies) the specified matrix with this one. - * @method concat - * @param {Array} matrix An array or ColorMatrix instance. - * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) - * @chainable - **/ - p.concat = function(matrix) { - matrix = this._fixMatrix(matrix); - if (matrix.length != ColorMatrix.LENGTH) { return this; } - this._multiplyMatrix(matrix); - return this; - }; - - /** - * Returns a clone of this ColorMatrix. - * @method clone - * @return {ColorMatrix} A clone of this ColorMatrix. - **/ - p.clone = function() { - return (new ColorMatrix()).copy(this); - }; - - /** - * Return a length 25 (5x5) array instance containing this matrix's values. - * @method toArray - * @return {Array} An array holding this matrix's values. - **/ - p.toArray = function() { - var arr = []; - for (var i= 0, l=ColorMatrix.LENGTH; i ColorMatrix.LENGTH) { - matrix = matrix.slice(0,ColorMatrix.LENGTH); - } - return matrix; - }; - - - createjs.ColorMatrix = ColorMatrix; -}()); - -//############################################################################## -// ColorMatrixFilter.js -//############################################################################## - -this.createjs = this.createjs||{}; - -(function() { - "use strict"; - - -// constructor: - /** - * Allows you to carry out complex color operations such as modifying saturation, brightness, or inverting. See the - * {{#crossLink "ColorMatrix"}}{{/crossLink}} for more information on changing colors. For an easier color transform, - * consider the {{#crossLink "ColorFilter"}}{{/crossLink}}. - * - *

    Example

    - * This example creates a red circle, inverts its hue, and then saturates it to brighten it up. - * - * var shape = new createjs.Shape().set({x:100,y:100}); - * shape.graphics.beginFill("#ff0000").drawCircle(0,0,50); - * - * var matrix = new createjs.ColorMatrix().adjustHue(180).adjustSaturation(100); - * shape.filters = [ - * new createjs.ColorMatrixFilter(matrix) - * ]; - * - * shape.cache(-50, -50, 100, 100); - * - * See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters. - * @class ColorMatrixFilter - * @constructor - * @extends Filter - * @param {Array | ColorMatrix} matrix A 4x5 matrix describing the color operation to perform. See also the {{#crossLink "ColorMatrix"}}{{/crossLink}} - * class. - **/ - function ColorMatrixFilter(matrix) { - - - // public properties: - /** - * A 4x5 matrix describing the color operation to perform. See also the {{#crossLink "ColorMatrix"}}{{/crossLink}} - * @property matrix - * @type Array | ColorMatrix - **/ - this.matrix = matrix; - } - var p = createjs.extend(ColorMatrixFilter, createjs.Filter); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// public methods: - /** docced in super class **/ - p.toString = function() { - return "[ColorMatrixFilter]"; - }; - - /** docced in super class **/ - p.clone = function() { - return new ColorMatrixFilter(this.matrix); - }; - -// private methods: - /** docced in super class **/ - p._applyFilter = function(imageData) { - var data = imageData.data; - var l = data.length; - var r,g,b,a; - var mtx = this.matrix; - var m0 = mtx[0], m1 = mtx[1], m2 = mtx[2], m3 = mtx[3], m4 = mtx[4]; - var m5 = mtx[5], m6 = mtx[6], m7 = mtx[7], m8 = mtx[8], m9 = mtx[9]; - var m10 = mtx[10], m11 = mtx[11], m12 = mtx[12], m13 = mtx[13], m14 = mtx[14]; - var m15 = mtx[15], m16 = mtx[16], m17 = mtx[17], m18 = mtx[18], m19 = mtx[19]; - - for (var i=0; iExample - * - * var stage = new createjs.Stage("canvasId"); - * createjs.Touch.enable(stage); - * - * Note: It is important to disable Touch on a stage that you are no longer using: - * - * createjs.Touch.disable(stage); - * - * @class Touch - * @static - **/ - function Touch() { - throw "Touch cannot be instantiated"; - } - - -// public static methods: - /** - * Returns `true` if touch is supported in the current browser. - * @method isSupported - * @return {Boolean} Indicates whether touch is supported in the current browser. - * @static - **/ - Touch.isSupported = function() { - return !!(('ontouchstart' in window) // iOS & Android - || (window.navigator['msPointerEnabled'] && window.navigator['msMaxTouchPoints'] > 0) // IE10 - || (window.navigator['pointerEnabled'] && window.navigator['maxTouchPoints'] > 0)); // IE11+ - }; - - /** - * Enables touch interaction for the specified EaselJS {{#crossLink "Stage"}}{{/crossLink}}. Currently supports iOS - * (and compatible browsers, such as modern Android browsers), and IE10/11. Supports both single touch and - * multi-touch modes. Extends the EaselJS {{#crossLink "MouseEvent"}}{{/crossLink}} model, but without support for - * double click or over/out events. See the MouseEvent {{#crossLink "MouseEvent/pointerId:property"}}{{/crossLink}} - * for more information. - * @method enable - * @param {Stage} stage The {{#crossLink "Stage"}}{{/crossLink}} to enable touch on. - * @param {Boolean} [singleTouch=false] If `true`, only a single touch will be active at a time. - * @param {Boolean} [allowDefault=false] If `true`, then default gesture actions (ex. scrolling, zooming) will be - * allowed when the user is interacting with the target canvas. - * @return {Boolean} Returns `true` if touch was successfully enabled on the target stage. - * @static - **/ - Touch.enable = function(stage, singleTouch, allowDefault) { - if (!stage || !stage.canvas || !Touch.isSupported()) { return false; } - if (stage.__touch) { return true; } - - // inject required properties on stage: - stage.__touch = {pointers:{}, multitouch:!singleTouch, preventDefault:!allowDefault, count:0}; - - // note that in the future we may need to disable the standard mouse event model before adding - // these to prevent duplicate calls. It doesn't seem to be an issue with iOS devices though. - if ('ontouchstart' in window) { Touch._IOS_enable(stage); } - else if (window.navigator['msPointerEnabled'] || window.navigator["pointerEnabled"]) { Touch._IE_enable(stage); } - return true; - }; - - /** - * Removes all listeners that were set up when calling `Touch.enable()` on a stage. - * @method disable - * @param {Stage} stage The {{#crossLink "Stage"}}{{/crossLink}} to disable touch on. - * @static - **/ - Touch.disable = function(stage) { - if (!stage) { return; } - if ('ontouchstart' in window) { Touch._IOS_disable(stage); } - else if (window.navigator['msPointerEnabled'] || window.navigator["pointerEnabled"]) { Touch._IE_disable(stage); } - - delete stage.__touch; - }; - - -// Private static methods: - /** - * @method _IOS_enable - * @protected - * @param {Stage} stage - * @static - **/ - Touch._IOS_enable = function(stage) { - var canvas = stage.canvas; - var f = stage.__touch.f = function(e) { Touch._IOS_handleEvent(stage,e); }; - canvas.addEventListener("touchstart", f, false); - canvas.addEventListener("touchmove", f, false); - canvas.addEventListener("touchend", f, false); - canvas.addEventListener("touchcancel", f, false); - }; - - /** - * @method _IOS_disable - * @protected - * @param {Stage} stage - * @static - **/ - Touch._IOS_disable = function(stage) { - var canvas = stage.canvas; - if (!canvas) { return; } - var f = stage.__touch.f; - canvas.removeEventListener("touchstart", f, false); - canvas.removeEventListener("touchmove", f, false); - canvas.removeEventListener("touchend", f, false); - canvas.removeEventListener("touchcancel", f, false); - }; - - /** - * @method _IOS_handleEvent - * @param {Stage} stage - * @param {Object} e The event to handle - * @protected - * @static - **/ - Touch._IOS_handleEvent = function(stage, e) { - if (!stage) { return; } - if (stage.__touch.preventDefault) { e.preventDefault&&e.preventDefault(); } - var touches = e.changedTouches; - var type = e.type; - for (var i= 0,l=touches.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; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - -// public methods: - /** - * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true 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; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// static public methods: - /** - * Static initializer to mix EventDispatcher methods into a target object or prototype. - * - * EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class - * EventDispatcher.initialize(myObject); // add to a specific instance - * - * @method initialize - * @static - * @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a - * prototype. - **/ - EventDispatcher.initialize = function(target) { - target.addEventListener = p.addEventListener; - target.on = p.on; - target.removeEventListener = target.off = p.removeEventListener; - target.removeAllEventListeners = p.removeAllEventListeners; - target.hasEventListener = p.hasEventListener; - target.dispatchEvent = p.dispatchEvent; - target._dispatchEvent = p._dispatchEvent; - target.willTrigger = p.willTrigger; - }; - - -// public methods: - /** - * Adds the specified event listener. Note that adding multiple listeners to the same function will result in - * multiple callbacks getting fired. - * - *

    Example

    - * - * displayObject.addEventListener("click", handleClick); - * function handleClick(event) { - * // Click happened. - * } - * - * @method addEventListener - * @param {String} type The string type of the event. - * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when - * the event is dispatched. - * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. - * @return {Function | Object} Returns the listener for chaining or assignment. - **/ - p.addEventListener = function(type, listener, useCapture) { - var listeners; - if (useCapture) { - listeners = this._captureListeners = this._captureListeners||{}; - } else { - listeners = this._listeners = this._listeners||{}; - } - var arr = listeners[type]; - if (arr) { this.removeEventListener(type, listener, useCapture); } - arr = listeners[type]; // remove may have deleted the array - if (!arr) { listeners[type] = [listener]; } - else { arr.push(listener); } - return listener; - }; - - /** - * A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener - * only run once, associate arbitrary data with the listener, and remove the listener. - * - * This method works by creating an anonymous wrapper function and subscribing it with addEventListener. - * The 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); - -//############################################################################## -// DomUtils.js -//############################################################################## - -(function () { - - /** - * A few utilities for interacting with the dom. - * @class DomUtils - */ - var s = {}; - - s.appendToHead = function (el) { - s.getHead().appendChild(el) - } - - s.getHead = function () { - return document.head || document.getElementsByTagName("head")[0]; - } - - s.getBody = function () { - return document.body || document.getElementsByTagName("body")[0]; - } - - 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. - * @param {String} type The mime type of the XML. Use "text/xml" for XML, and "image/svg+xml" for SVG parsing. - * @return {XML} An XML document - * @static - */ - s.parseXML = function (text, type) { - 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, type); - } - } 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; - -}()); - -//############################################################################## -// 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 "AbstractLoader/GET:property"}}{{/crossLink}} or - * {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} request types are supported, and are defined as - * constants on {{#crossLink "AbstractLoader"}}{{/crossLink}}. - * @property method - * @type {String} - * @default get - */ - this.method = createjs.LoadItem.GET; - - /** - * An object hash of name/value pairs to send to the server. - * @property values - * @type {Object} - * @default null - */ - this.values = null; - - /** - * An object hash of headers to attach to an XHR request. PreloadJS will automatically attach some default - * headers when required, including "Origin", "Content-Type", and "X-Requested-With". You may override the - * default headers by including them in your headers object. - * @property headers - * @type {Object} - * @default null - */ - this.headers = null; - - /** - * Enable credentials for XHR requests. - * @property withCredentials - * @type {Boolean} - * @default false - */ - this.withCredentials = false; - - /** - * Set the mime type of XHR-based requests. This is automatically set to "text/plain; charset=utf-8" for text - * based files (json, xml, text, css, js). - * @property mimeType - * @type {String} - * @default null - */ - this.mimeType = null; - - /** - * Sets the crossOrigin attribute for CORS-enabled images loading cross-domain. - * @property crossOrigin - * @type {boolean} - * @default Anonymous - */ - this.crossOrigin = null; - - /** - * The duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR - * (level one) loading, as XHR (level 2) provides its own timeout event. - * @property loadTimeout - * @type {Number} - * @default 8000 (8 seconds) - */ - this.loadTimeout = s.LOAD_TIMEOUT_DEFAULT; - }; - - var p = LoadItem.prototype = {}; - var s = LoadItem; - - /** - * Default duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR - * (level one) loading, as XHR (level 2) provides its own timeout event. - * @property LOAD_TIMEOUT_DEFAULT - * @type {number} - * @static - */ - s.LOAD_TIMEOUT_DEFAULT = 8000; - - /** - * Create a LoadItem. - *
      - *
    • String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
    • - *
    • LoadItem instances are returned as-is
    • - *
    • Objects are returned with any needed properties added
    • - *
    - * @method create - * @param {LoadItem|String|Object} value The load item value - * @returns {LoadItem|Object} - * @static - */ - s.create = function (value) { - if (typeof value == "string") { - var item = new LoadItem(); - item.src = value; - return item; - } else if (value instanceof s) { - return value; - } else if (value instanceof Object && value.src) { - if (value.loadTimeout == null) { - value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT; - } - return value; - } else { - throw new Error("Type not recognized."); - } - }; - - /** - * Provides a chainable shortcut method for setting a number of properties on the instance. - * - *

    Example

    - * - * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true}); - * - * @method set - * @param {Object} props A generic object containing properties to copy to the LoadItem instance. - * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.) - */ - p.set = function(props) { - for (var n in props) { this[n] = props[n]; } - return this; - }; - - createjs.LoadItem = s; - -}()); - -//############################################################################## -// RequestUtils.js -//############################################################################## - -(function () { - - /** - * Utilities that assist with parsing load items, and determining file types, etc. - * @class RequestUtils - */ - var s = {}; - - /** - * The Regular Expression used to test file URLS for an absolute path. - * @property ABSOLUTE_PATH - * @type {RegExp} - * @static - */ - s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i; - - /** - * The Regular Expression used to test file URLS for a relative path. - * @property RELATIVE_PATH - * @type {RegExp} - * @static - */ - s.RELATIVE_PATT = (/^[./]*?\//i); - - /** - * The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string - * removed. - * @property EXTENSION_PATT - * @type {RegExp} - * @static - */ - s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i; - - /** - * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know: - *
      - *
    • If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or - * `//networkPath`)
    • - *
    • If the path is relative. Relative paths start with `../` or `/path` (or similar)
    • - *
    • The file extension. This is determined by the filename with an extension. Query strings are dropped, and - * the file path is expected to follow the format `name.ext`.
    • - *
    - * @method parseURI - * @param {String} path - * @returns {Object} An Object with an `absolute` and `relative` Boolean values, as well as an optional 'extension` - * property, which is the lowercase extension. - * @static - */ - s.parseURI = function (path) { - var info = {absolute: false, relative: false}; - if (path == null) { return info; } - - // Drop the query string - var queryIndex = path.indexOf("?"); - if (queryIndex > -1) { - path = path.substr(0, queryIndex); - } - - // Absolute - var match; - if (s.ABSOLUTE_PATT.test(path)) { - info.absolute = true; - - // Relative - } else if (s.RELATIVE_PATT.test(path)) { - info.relative = true; - } - - // Extension - if (match = path.match(s.EXTENSION_PATT)) { - info.extension = match[1].toLowerCase(); - } - return info; - }; - - /** - * Formats an object into a query string for either a POST or GET request. - * @method formatQueryString - * @param {Object} data The data to convert to a query string. - * @param {Array} [query] Existing name/value pairs to append on to this query. - * @static - */ - s.formatQueryString = function (data, query) { - if (data == null) { - throw new Error('You must specify data.'); - } - var params = []; - for (var n in data) { - params.push(n + '=' + escape(data[n])); - } - if (query) { - params = params.concat(query); - } - return params.join('&'); - }; - - /** - * A utility method that builds a file path using a source and a data object, and formats it into a new path. - * @method buildPath - * @param {String} src The source path to add values to. - * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the - * path will be preserved. - * @returns {string} A formatted string that contains the path and the supplied parameters. - * @static - */ - s.buildPath = function (src, data) { - if (data == null) { - return src; - } - - var query = []; - var idx = src.indexOf('?'); - - if (idx != -1) { - var q = src.slice(idx + 1); - query = query.concat(q.split('&')); - } - - if (idx != -1) { - return src.slice(0, idx) + '?' + this.formatQueryString(data, query); - } else { - return src + '?' + this.formatQueryString(data, query); - } - }; - - /** - * @method isCrossDomain - * @param {LoadItem|Object} item A load item with a `src` property. - * @return {Boolean} If the load item is loading from a different domain than the current location. - * @static - */ - s.isCrossDomain = function (item) { - var target = document.createElement("a"); - target.href = item.src; - - var host = document.createElement("a"); - host.href = location.href; - - var crossdomain = (target.hostname != "") && - (target.port != host.port || - target.protocol != host.protocol || - target.hostname != host.hostname); - return crossdomain; - }; - - /** - * @method isLocal - * @param {LoadItem|Object} item A load item with a `src` property - * @return {Boolean} If the load item is loading from the "file:" protocol. Assume that the host must be local as - * well. - * @static - */ - s.isLocal = function (item) { - var target = document.createElement("a"); - target.href = item.src; - return target.hostname == "" && target.protocol == "file:"; - }; - - /** - * Determine if a specific type should be loaded as a binary file. Currently, only images and items marked - * specifically as "binary" are loaded as binary. Note that audio is not a binary type, as we can not play - * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get - * a binary result to work with. Binary files are loaded using XHR2. Types are defined as static constants on - * {{#crossLink "AbstractLoader"}}{{/crossLink}}. - * @method isBinary - * @param {String} type The item type. - * @return {Boolean} If the specified type is binary. - * @static - */ - s.isBinary = function (type) { - switch (type) { - case createjs.AbstractLoader.IMAGE: - case createjs.AbstractLoader.BINARY: - return true; - default: - return false; - } - }; - - /** - * Check if item is a valid HTMLImageElement - * @method isImageTag - * @param {Object} item - * @returns {Boolean} - * @static - */ - s.isImageTag = function(item) { - return item instanceof HTMLImageElement; - }; - - /** - * Check if item is a valid HTMLAudioElement - * @method isAudioTag - * @param {Object} item - * @returns {Boolean} - * @static - */ - s.isAudioTag = function(item) { - if (window.HTMLAudioElement) { - return item instanceof HTMLAudioElement; - } else { - return false; - } - }; - - /** - * Check if item is a valid HTMLVideoElement - * @method isVideoTag - * @param {Object} item - * @returns {Boolean} - * @static - */ - s.isVideoTag = function(item) { - if (window.HTMLVideoElement) { - return item instanceof HTMLVideoElement; - } else { - return false; - } - }; - - /** - * Determine if a specific type is a text-based asset, and should be loaded as UTF-8. - * @method isText - * @param {String} type The item type. - * @return {Boolean} If the specified type is text. - * @static - */ - s.isText = function (type) { - switch (type) { - case createjs.AbstractLoader.TEXT: - case createjs.AbstractLoader.JSON: - case createjs.AbstractLoader.MANIFEST: - case createjs.AbstractLoader.XML: - case createjs.AbstractLoader.CSS: - case createjs.AbstractLoader.SVG: - case createjs.AbstractLoader.JAVASCRIPT: - case createjs.AbstractLoader.SPRITESHEET: - return true; - default: - return false; - } - }; - - /** - * Determine the type of the object using common extensions. Note that the type can be passed in with the load item - * if it is an unusual extension. - * @method getTypeByExtension - * @param {String} extension The file extension to use to determine the load type. - * @return {String} The determined load type (for example, AbstractLoader.IMAGE). Will return `null` if - * the type can not be determined by the extension. - * @static - */ - s.getTypeByExtension = function (extension) { - if (extension == null) { - return createjs.AbstractLoader.TEXT; - } - - switch (extension.toLowerCase()) { - case "jpeg": - case "jpg": - case "gif": - case "png": - case "webp": - case "bmp": - return createjs.AbstractLoader.IMAGE; - case "ogg": - case "mp3": - case "webm": - return createjs.AbstractLoader.SOUND; - case "mp4": - case "webm": - case "ts": - return createjs.AbstractLoader.VIDEO; - case "json": - return createjs.AbstractLoader.JSON; - case "xml": - return createjs.AbstractLoader.XML; - case "css": - return createjs.AbstractLoader.CSS; - case "js": - return createjs.AbstractLoader.JAVASCRIPT; - case 'svg': - return createjs.AbstractLoader.SVG; - default: - return createjs.AbstractLoader.TEXT; - } - }; - - createjs.RequestUtils = s; - -}()); - -//############################################################################## -// 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; - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - - /** - * Defines a POST request, use for a method value when loading data. - * @property POST - * @type {string} - * @default post - * @static - */ - s.POST = "POST"; - - /** - * Defines a GET request, use for a method value when loading data. - * @property GET - * @type {string} - * @default get - * @static - */ - s.GET = "GET"; - - /** - * The preload type for generic binary types. Note that images are loaded as binary files when using XHR. - * @property BINARY - * @type {String} - * @default binary - * @static - * @since 0.6.0 - */ - s.BINARY = "binary"; - - /** - * The preload type for css files. CSS files are loaded using a <link> when loaded with XHR, or a - * <style> tag when loaded with tags. - * @property CSS - * @type {String} - * @default css - * @static - * @since 0.6.0 - */ - s.CSS = "css"; - - /** - * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag. - * @property IMAGE - * @type {String} - * @default image - * @static - * @since 0.6.0 - */ - s.IMAGE = "image"; - - /** - * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a - * <script> tag. - * - * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into - * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier, - * only tag-loaded scripts are injected. - * @property JAVASCRIPT - * @type {String} - * @default javascript - * @static - * @since 0.6.0 - */ - s.JAVASCRIPT = "javascript"; - - /** - * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a - * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP, - * no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to, and the JSON - * must contain a matching wrapper function. - * @property JSON - * @type {String} - * @default json - * @static - * @since 0.6.0 - */ - s.JSON = "json"; - - /** - * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a - * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON. - * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} - * property is set to. - * @property JSONP - * @type {String} - * @default jsonp - * @static - * @since 0.6.0 - */ - s.JSONP = "jsonp"; - - /** - * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded - * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an - * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead, - * regardless of what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to. - * @property MANIFEST - * @type {String} - * @default manifest - * @static - * @since 0.6.0 - */ - s.MANIFEST = "manifest"; - - /** - * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an - * <audio> tag. - * @property SOUND - * @type {String} - * @default sound - * @static - * @since 0.6.0 - */ - s.SOUND = "sound"; - - /** - * The preload type for video files, usually mp4, ts, or ogg. When loading via tags, video is loaded into an - * <video> tag. - * @property VIDEO - * @type {String} - * @default video - * @static - * @since 0.6.0 - */ - s.VIDEO = "video"; - - /** - * The preload type for SpriteSheet files. SpriteSheet files are JSON files that contain string image paths. - * @property SPRITESHEET - * @type {String} - * @default spritesheet - * @static - * @since 0.6.0 - */ - s.SPRITESHEET = "spritesheet"; - - /** - * The preload type for SVG files. - * @property SVG - * @type {String} - * @default svg - * @static - * @since 0.6.0 - */ - s.SVG = "svg"; - - /** - * The preload type for text files, which is also the default file type if the type can not be determined. Text is - * loaded as raw text. - * @property TEXT - * @type {String} - * @default text - * @static - * @since 0.6.0 - */ - s.TEXT = "text"; - - /** - * The preload type for xml files. XML is loaded into an XML document. - * @property XML - * @type {String} - * @default xml - * @static - * @since 0.6.0 - */ - s.XML = "xml"; - -// Events - /** - * The {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when the overall progress changes. Prior to - * version 0.6.0, this was just a regular {{#crossLink "Event"}}{{/crossLink}}. - * @event progress - * @since 0.3.0 - */ - - /** - * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a load starts. - * @event loadstart - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.3.1 - */ - - /** - * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the entire queue has been loaded. - * @event complete - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.3.0 - */ - - /** - * The {{#crossLink "ErrorEvent"}}{{/crossLink}} that is fired when the loader encounters an error. If the error was - * encountered by a file, the event will contain the item that caused the error. Prior to version 0.6.0, this was - * just a regular {{#crossLink "Event"}}{{/crossLink}}. - * @event error - * @since 0.3.0 - */ - - /** - * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the loader encounters an internal file load error. - * This enables loaders to maintain internal queues, and surface file load errors. - * @event fileerror - * @param {Object} target The object that dispatched the event. - * @param {String} type The even type ("fileerror") - * @param {LoadItem|object} The item that encountered the error - * @since 0.6.0 - */ - - /** - * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a loader internally loads a file. This enables - * loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} to maintain internal {{#crossLink "LoadQueue"}}{{/crossLink}}s - * and notify when they have loaded a file. The {{#crossLink "LoadQueue"}}{{/crossLink}} class dispatches a - * slightly different {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event. - * @event fileload - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type ("fileload") - * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the - * object will contain that value as a `src` property. - * @param {Object} result The HTML tag or parsed result of the loaded item. - * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted - * to a usable object. - * @since 0.6.0 - */ - - /** - * The {{#crossLink "Event"}}{{/crossLink}} that is fired after the internal request is created, but before a load. - * This allows updates to the loader for specific loading needs, such as binary or XHR image loading. - * @event initialize - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type ("initialize") - * @param {AbstractLoader} loader The loader that has been initialized. - */ - - - /** - * Get a reference to the manifest item that is loaded by this loader. In some cases this will be the value that was - * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or - * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will - * be a {{#crossLink "LoadItem"}}{{/crossLink}}. - * @method getItem - * @return {Object} The manifest item that this loader is responsible for loading. - * @since 0.6.0 - */ - p.getItem = function () { - return this._item; - }; - - /** - * Get a reference to the content that was loaded by the loader (only available after the {{#crossLink "complete:event"}}{{/crossLink}} - * event is dispatched. - * @method getResult - * @param {Boolean} [raw=false] Determines if the returned result will be the formatted content, or the raw loaded - * data (if it exists). - * @return {Object} - * @since 0.6.0 - */ - p.getResult = function (raw) { - return raw ? this._rawResult : this._result; - }; - - /** - * Return the `tag` this object creates or uses for loading. - * @method getTag - * @return {Object} The tag instance - * @since 0.6.0 - */ - p.getTag = function () { - return this._tag; - }; - - /** - * Set the `tag` this item uses for loading. - * @method setTag - * @param {Object} tag The tag instance - * @since 0.6.0 - */ - p.setTag = function(tag) { - this._tag = tag; - }; - - /** - * Begin loading the item. This method is required when using a loader by itself. - * - *

    Example

    - * - * var queue = new createjs.LoadQueue(); - * queue.on("complete", handleComplete); - * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet - * queue.load(); - * - * @method load - */ - p.load = function () { - this._createRequest(); - - this._request.on("complete", this, this); - this._request.on("progress", this, this); - this._request.on("loadStart", this, this); - this._request.on("abort", this, this); - this._request.on("timeout", this, this); - this._request.on("error", this, this); - - var evt = new createjs.Event("initialize"); - evt.loader = this._request; - this.dispatchEvent(evt); - - this._request.load(); - }; - - /** - * Close the the item. This will stop any open requests (although downloads using HTML tags may still continue in - * the background), but events will not longer be dispatched. - * @method cancel - */ - p.cancel = function () { - this.canceled = true; - this.destroy(); - }; - - /** - * Clean up the loader. - * @method destroy - */ - p.destroy = function() { - if (this._request) { - this._request.removeAllEventListeners(); - this._request.destroy(); - } - - this._request = null; - - this._item = null; - this._rawResult = null; - this._result = null; - - this._loadItems = null; - - this.removeAllEventListeners(); - }; - - /** - * Get any items loaded internally by the loader. The enables loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} - * to expose items it loads internally. - * @method getLoadedItems - * @return {Array} A list of the items loaded by the loader. - * @since 0.6.0 - */ - p.getLoadedItems = function () { - return this._loadedItems; - }; - - - // Private methods - /** - * Create an internal request used for loading. By default, an {{#crossLink "XHRRequest"}}{{/crossLink}} or - * {{#crossLink "TagRequest"}}{{/crossLink}} is created, depending on the value of {{#crossLink "preferXHR:property"}}{{/crossLink}}. - * Other loaders may override this to use different request types, such as {{#crossLink "ManifestLoader"}}{{/crossLink}}, - * which uses {{#crossLink "JSONLoader"}}{{/crossLink}} or {{#crossLink "JSONPLoader"}}{{/crossLink}} under the hood. - * @method _createRequest - * @protected - */ - p._createRequest = function() { - if (!this._preferXHR) { - this._request = new createjs.TagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute); - } else { - this._request = new createjs.XHRRequest(this._item); - } - }; - - /** - * Create the HTML tag used for loading. This method does nothing by default, and needs to be implemented - * by loaders that require tag loading. - * @method _createTag - * @param {String} src The tag source - * @return {HTMLElement} The tag that was created - * @protected - */ - p._createTag = function(src) { return null; }; - - /** - * Dispatch a loadstart {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}} - * event for details on the event payload. - * @method _sendLoadStart - * @protected - */ - p._sendLoadStart = function () { - if (this._isCanceled()) { return; } - this.dispatchEvent("loadstart"); - }; - - /** - * Dispatch a {{#crossLink "ProgressEvent"}}{{/crossLink}}. - * @method _sendProgress - * @param {Number | Object} value The progress of the loaded item, or an object containing loaded - * and total properties. - * @protected - */ - p._sendProgress = function (value) { - if (this._isCanceled()) { return; } - var event = null; - if (typeof(value) == "number") { - this.progress = value; - event = new createjs.ProgressEvent(this.progress); - } else { - event = value; - this.progress = value.loaded / value.total; - event.progress = this.progress; - if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } - } - this.hasEventListener("progress") && this.dispatchEvent(event); - }; - - /** - * Dispatch a complete {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event - * @method _sendComplete - * @protected - */ - p._sendComplete = function () { - if (this._isCanceled()) { return; } - - this.loaded = true; - - var event = new createjs.Event("complete"); - event.rawResult = this._rawResult; - - if (this._result != null) { - event.result = this._result; - } - - this.dispatchEvent(event); - }; - - /** - * Dispatch an error {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} - * event for details on the event payload. - * @method _sendError - * @param {ErrorEvent} event The event object containing specific error properties. - * @protected - */ - p._sendError = function (event) { - if (this._isCanceled() || !this.hasEventListener("error")) { return; } - if (event == null) { - event = new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY"); // TODO: Populate error - } - this.dispatchEvent(event); - }; - - /** - * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events - * do not cause issues after the queue has been cleaned up. - * @method _isCanceled - * @return {Boolean} If the loader has been canceled. - * @protected - */ - p._isCanceled = function () { - if (window.createjs == null || this.canceled) { - return true; - } - return false; - }; - - /** - * A custom result formatter function, which is called just before a request dispatches its complete event. Most - * loader types already have an internal formatter, but this can be user-overridden for custom formatting. The - * formatted result will be available on Loaders using {{#crossLink "getResult"}}{{/crossLink}}, and passing `true`. - * @property resultFormatter - * @type Function - * @return {Object} The formatted result - * @since 0.6.0 - */ - p.resultFormatter = null; - - /** - * Handle events from internal requests. By default, loaders will handle, and redispatch the necessary events, but - * this method can be overridden for custom behaviours. - * @method handleEvent - * @param {Event} event The event that the internal request dispatches. - * @protected - * @since 0.6.0 - */ - p.handleEvent = function (event) { - switch (event.type) { - case "complete": - this._rawResult = event.target._response; - var result = this.resultFormatter && this.resultFormatter(this); - if (result instanceof Function) { - result.call(this, - createjs.proxy(this._resultFormatSuccess, this), - createjs.proxy(this._resultFormatFailed, this) - ); - } else { - this._result = result || this._rawResult; - this._sendComplete(); - } - break; - case "progress": - this._sendProgress(event); - break; - case "error": - this._sendError(event); - break; - case "loadstart": - this._sendLoadStart(); - break; - case "abort": - case "timeout": - if (!this._isCanceled()) { - this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_" + event.type.toUpperCase() + "_ERROR")); - } - break; - } - }; - - /** - * The "success" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous - * functions. - * @method _resultFormatSuccess - * @param {Object} result The formatted result - * @private - */ - p._resultFormatSuccess = function (result) { - this._result = result; - this._sendComplete(); - }; - - /** - * The "error" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous - * functions. - * @method _resultFormatSuccess - * @param {Object} error The error event - * @private - */ - p._resultFormatFailed = function (event) { - this._sendError(event); - }; - - /** - * @method buildPath - * @protected - * @deprecated Use the {{#crossLink "RequestUtils"}}{{/crossLink}} method {{#crossLink "RequestUtils/buildPath"}}{{/crossLink}} - * instead. - */ - p.buildPath = function (src, data) { - return createjs.RequestUtils.buildPath(src, data); - }; - - /** - * @method toString - * @return {String} a string representation of the instance. - */ - p.toString = function () { - return "[PreloadJS AbstractLoader]"; - }; - - createjs.AbstractLoader = createjs.promote(AbstractLoader, "EventDispatcher"); - -}()); - -//############################################################################## -// 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; - - /** - * Determines what the tags initial style.visibility was, so we can set it correctly after a load. - * - * @type {null} - * @private - */ - this._startTagVisibility = null; - }; - - var p = createjs.extend(TagRequest, createjs.AbstractRequest); - - // public methods - p.load = function () { - this._tag.onload = createjs.proxy(this._handleTagComplete, this); - this._tag.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this); - this._tag.onerror = createjs.proxy(this._handleError, this); - - var evt = new createjs.Event("initialize"); - evt.loader = this._tag; - - this.dispatchEvent(evt); - - this._hideTag(); - - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); - - this._tag[this._tagSrcAttribute] = this._item.src; - - // wdg:: Append the tag AFTER setting the src, or SVG loading on iOS will fail. - if (this._tag.parentNode == null) { - window.document.body.appendChild(this._tag); - this._addedToDOM = true; - } - }; - - p.destroy = function() { - this._clean(); - this._tag = null; - - this.AbstractRequest_destroy(); - }; - - // private methods - /** - * Handle the readyStateChange event from a tag. We need this in place of the `onload` callback (mainly SCRIPT - * and LINK tags), but other cases may exist. - * @method _handleReadyStateChange - * @private - */ - p._handleReadyStateChange = function () { - clearTimeout(this._loadTimeout); - // This is strictly for tags in browsers that do not support onload. - var tag = this._tag; - - // Complete is for old IE support. - if (tag.readyState == "loaded" || tag.readyState == "complete") { - this._handleTagComplete(); - } - }; - - /** - * Handle any error events from the tag. - * @method _handleError - * @protected - */ - p._handleError = function() { - this._clean(); - this.dispatchEvent("error"); - }; - - /** - * Handle the tag's onload callback. - * @method _handleTagComplete - * @private - */ - p._handleTagComplete = function () { - this._rawResult = this._tag; - this._result = this.resultFormatter && this.resultFormatter(this) || this._rawResult; - - this._clean(); - this._showTag(); - - this.dispatchEvent("complete"); - }; - - /** - * The tag request has not loaded within the time specified in loadTimeout. - * @method _handleError - * @param {Object} event The XHR error event. - * @private - */ - p._handleTimeout = function () { - this._clean(); - this.dispatchEvent(new createjs.Event("timeout")); - }; - - /** - * Remove event listeners, but don't destroy the request object - * @method _clean - * @private - */ - p._clean = function() { - this._tag.onload = null; - this._tag.onreadystatechange = null; - this._tag.onerror = null; - if (this._addedToDOM && this._tag.parentNode != null) { - this._tag.parentNode.removeChild(this._tag); - } - clearTimeout(this._loadTimeout); - }; - - p._hideTag = function() { - this._startTagVisibility = this._tag.style.visibility; - this._tag.style.visibility = "hidden"; - }; - - p._showTag = function() { - this._tag.style.visibility = this._startTagVisibility; - }; - - /** - * Handle a stalled audio event. The main place this happens is with HTMLAudio in Chrome when playing back audio - * that is already in a load, but not complete. - * @method _handleStalled - * @private - */ - p._handleStalled = function () { - //Ignore, let the timeout take care of it. Sometimes its not really stopped. - }; - - createjs.TagRequest = createjs.promote(TagRequest, "AbstractRequest"); - -}()); - -//############################################################################## -// MediaTagRequest.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - // constructor - /** - * An {{#crossLink "TagRequest"}}{{/crossLink}} that loads HTML tags for video and audio. - * @class MediaTagRequest - * @param {LoadItem} loadItem - * @param {HTMLAudioElement|HTMLVideoElement} tag - * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc. - * @constructor - */ - function MediaTagRequest(loadItem, tag, srcAttribute) { - this.AbstractRequest_constructor(loadItem); - - // protected properties - this._tag = tag; - this._tagSrcAttribute = srcAttribute; - this._loadedHandler = createjs.proxy(this._handleTagComplete, this); - }; - - var p = createjs.extend(MediaTagRequest, createjs.TagRequest); - var s = MediaTagRequest; - - // public methods - p.load = function () { - var sc = createjs.proxy(this._handleStalled, this); - this._stalledCallback = sc; - - var pc = createjs.proxy(this._handleProgress, this); - this._handleProgress = pc; - - this._tag.addEventListener("stalled", sc); - this._tag.addEventListener("progress", pc); - - // This will tell us when audio is buffered enough to play through, but not when its loaded. - // The tag doesn't keep loading in Chrome once enough has buffered, and we have decided that behaviour is sufficient. - this._tag.addEventListener && this._tag.addEventListener("canplaythrough", this._loadedHandler, false); // canplaythrough callback doesn't work in Chrome, so we use an event. - - this.TagRequest_load(); - }; - - // private methods - p._handleReadyStateChange = function () { - clearTimeout(this._loadTimeout); - // This is strictly for tags in browsers that do not support onload. - var tag = this._tag; - - // Complete is for old IE support. - if (tag.readyState == "loaded" || tag.readyState == "complete") { - this._handleTagComplete(); - } - }; - - p._handleStalled = function () { - //Ignore, let the timeout take care of it. Sometimes its not really stopped. - }; - - /** - * An XHR request has reported progress. - * @method _handleProgress - * @param {Object} event The XHR progress event. - * @private - */ - p._handleProgress = function (event) { - if (!event || event.loaded > 0 && event.total == 0) { - return; // Sometimes we get no "total", so just ignore the progress event. - } - - var newEvent = new createjs.ProgressEvent(event.loaded, event.total); - this.dispatchEvent(newEvent); - }; - - // protected methods - p._clean = function () { - this._tag.removeEventListener && this._tag.removeEventListener("canplaythrough", this._loadedHandler); - this._tag.removeEventListener("stalled", this._stalledCallback); - this._tag.removeEventListener("progress", this._progressCallback); - - this.TagRequest__clean(); - }; - - createjs.MediaTagRequest = createjs.promote(MediaTagRequest, "TagRequest"); - -}()); - -//############################################################################## -// XHRRequest.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - -// constructor - /** - * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used - * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary. - * XHR requests load the content as text or binary data, provide progress and consistent completion events, and - * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for - * cross-domain loading. - * @class XHRRequest - * @constructor - * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * for an overview of supported file properties. - * @extends AbstractLoader - */ - function XHRRequest (item) { - this.AbstractRequest_constructor(item); - - // protected properties - /** - * A reference to the XHR request used to load the content. - * @property _request - * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP} - * @private - */ - this._request = null; - - /** - * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1, - * typically IE9). - * @property _loadTimeout - * @type {Number} - * @private - */ - this._loadTimeout = null; - - /** - * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect - * the version, so we use capabilities to make a best guess. - * @property _xhrLevel - * @type {Number} - * @default 1 - * @private - */ - this._xhrLevel = 1; - - /** - * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be - * null until the file is loaded. - * @property _response - * @type {mixed} - * @private - */ - this._response = null; - - /** - * The response of the loaded file before it is modified. In most cases, content is converted from raw text to - * an HTML tag or a formatted object which is set to the result property, but the developer may still - * want to access the raw content as it was loaded. - * @property _rawResponse - * @type {String|Object} - * @private - */ - this._rawResponse = null; - - this._canceled = false; - - // Setup our event handlers now. - this._handleLoadStartProxy = createjs.proxy(this._handleLoadStart, this); - this._handleProgressProxy = createjs.proxy(this._handleProgress, this); - this._handleAbortProxy = createjs.proxy(this._handleAbort, this); - this._handleErrorProxy = createjs.proxy(this._handleError, this); - this._handleTimeoutProxy = createjs.proxy(this._handleTimeout, this); - this._handleLoadProxy = createjs.proxy(this._handleLoad, this); - this._handleReadyStateChangeProxy = createjs.proxy(this._handleReadyStateChange, this); - - if (!this._createXHR(item)) { - //TODO: Throw error? - } - }; - - var p = createjs.extend(XHRRequest, createjs.AbstractRequest); - -// static properties - /** - * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE. - * @property ACTIVEX_VERSIONS - * @type {Array} - * @since 0.4.2 - * @private - */ - XHRRequest.ACTIVEX_VERSIONS = [ - "Msxml2.XMLHTTP.6.0", - "Msxml2.XMLHTTP.5.0", - "Msxml2.XMLHTTP.4.0", - "MSXML2.XMLHTTP.3.0", - "MSXML2.XMLHTTP", - "Microsoft.XMLHTTP" - ]; - -// Public methods - /** - * Look up the loaded result. - * @method getResult - * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content - * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be - * returned instead. - * @return {Object} A result object containing the content that was loaded, such as: - *
      - *
    • An image tag (<image />) for images
    • - *
    • A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the - * HTML head.
    • - *
    • A style tag for CSS (<style />)
    • - *
    • Raw text for TEXT
    • - *
    • A formatted JavaScript object defined by JSON
    • - *
    • An XML document
    • - *
    • An binary arraybuffer loaded by XHR
    • - *
    - * Note that if a raw result is requested, but not found, the result will be returned instead. - */ - p.getResult = function (raw) { - if (raw && this._rawResponse) { - return this._rawResponse; - } - return this._response; - }; - - // Overrides abstract method in AbstractRequest - p.cancel = function () { - this.canceled = true; - this._clean(); - this._request.abort(); - }; - - // Overrides abstract method in AbstractLoader - p.load = function () { - if (this._request == null) { - this._handleError(); - return; - } - - //Events - if (this._request.addEventListener != null) { - this._request.addEventListener("loadstart", this._handleLoadStartProxy, false); - this._request.addEventListener("progress", this._handleProgressProxy, false); - this._request.addEventListener("abort", this._handleAbortProxy, false); - this._request.addEventListener("error", this._handleErrorProxy, false); - this._request.addEventListener("timeout", this._handleTimeoutProxy, false); - - // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. - this._request.addEventListener("load", this._handleLoadProxy, false); - this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false); - } else { - // IE9 support - this._request.onloadstart = this._handleLoadStartProxy; - this._request.onprogress = this._handleProgressProxy; - this._request.onabort = this._handleAbortProxy; - this._request.onerror = this._handleErrorProxy; - this._request.ontimeout = this._handleTimeoutProxy; - - // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. - this._request.onload = this._handleLoadProxy; - this._request.onreadystatechange = this._handleReadyStateChangeProxy; - } - - // Set up a timeout if we don't have XHR2 - if (this._xhrLevel == 1) { - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); - } - - // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome - try { - if (!this._item.values || this._item.method == createjs.AbstractLoader.GET) { - this._request.send(); - } else if (this._item.method == createjs.AbstractLoader.POST) { - this._request.send(createjs.RequestUtils.formatQueryString(this._item.values)); - } - } catch (error) { - this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND", null, error)); - } - }; - - p.setResponseType = function (type) { - // Some old browsers doesn't support blob, so we convert arraybuffer to blob after response is downloaded - if (type === 'blob') { - type = window.URL ? 'blob' : 'arraybuffer'; - this._responseType = type; - } - this._request.responseType = type; - }; - - /** - * Get all the response headers from the XmlHttpRequest. - * - * From the docs: Return all the HTTP headers, excluding headers that are a case-insensitive match - * for Set-Cookie or Set-Cookie2, as a single string, with each header line separated by a U+000D CR U+000A LF pair, - * excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE - * pair. - * @method getAllResponseHeaders - * @return {String} - * @since 0.4.1 - */ - p.getAllResponseHeaders = function () { - if (this._request.getAllResponseHeaders instanceof Function) { - return this._request.getAllResponseHeaders(); - } else { - return null; - } - }; - - /** - * Get a specific response header from the XmlHttpRequest. - * - * From the docs: Returns the header field value from the response of which the field name matches - * header, unless the field name is Set-Cookie or Set-Cookie2. - * @method getResponseHeader - * @param {String} header The header name to retrieve. - * @return {String} - * @since 0.4.1 - */ - p.getResponseHeader = function (header) { - if (this._request.getResponseHeader instanceof Function) { - return this._request.getResponseHeader(header); - } else { - return null; - } - }; - -// protected methods - /** - * The XHR request has reported progress. - * @method _handleProgress - * @param {Object} event The XHR progress event. - * @private - */ - p._handleProgress = function (event) { - if (!event || event.loaded > 0 && event.total == 0) { - return; // Sometimes we get no "total", so just ignore the progress event. - } - - var newEvent = new createjs.ProgressEvent(event.loaded, event.total); - this.dispatchEvent(newEvent); - }; - - /** - * The XHR request has reported a load start. - * @method _handleLoadStart - * @param {Object} event The XHR loadStart event. - * @private - */ - p._handleLoadStart = function (event) { - clearTimeout(this._loadTimeout); - this.dispatchEvent("loadstart"); - }; - - /** - * The XHR request has reported an abort event. - * @method handleAbort - * @param {Object} event The XHR abort event. - * @private - */ - p._handleAbort = function (event) { - this._clean(); - this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED", null, event)); - }; - - /** - * The XHR request has reported an error event. - * @method _handleError - * @param {Object} event The XHR error event. - * @private - */ - p._handleError = function (event) { - this._clean(); - this.dispatchEvent(new createjs.ErrorEvent(event.message)); - }; - - /** - * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload - * event, so we must monitor the readyStateChange to determine if the file is loaded. - * @method _handleReadyStateChange - * @param {Object} event The XHR readyStateChange event. - * @private - */ - p._handleReadyStateChange = function (event) { - if (this._request.readyState == 4) { - this._handleLoad(); - } - }; - - /** - * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has - * request.readyState == 4. Only the first call to this method will be processed. - * @method _handleLoad - * @param {Object} event The XHR load event. - * @private - */ - p._handleLoad = function (event) { - if (this.loaded) { - return; - } - this.loaded = true; - - var error = this._checkError(); - if (error) { - this._handleError(error); - return; - } - - this._response = this._getResponse(); - // Convert arraybuffer back to blob - if (this._responseType === 'arraybuffer') { - try { - this._response = new Blob([this._response]); - } catch (e) { - // Fallback to use BlobBuilder if Blob constructor is not supported - // Tested on Android 2.3 ~ 4.2 and iOS5 safari - window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; - if (e.name === 'TypeError' && window.BlobBuilder) { - var builder = new BlobBuilder(); - builder.append(this._response); - this._response = builder.getBlob(); - } - } - } - this._clean(); - - this.dispatchEvent(new createjs.Event("complete")); - }; - - /** - * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout - * callback. - * @method _handleTimeout - * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout. - * @private - */ - p._handleTimeout = function (event) { - this._clean(); - - this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT", null, event)); - }; - -// Protected - /** - * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note - * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code. - * @method _checkError - * @return {int} If the request status returns an error code. - * @private - */ - p._checkError = function () { - //LM: Probably need additional handlers here, maybe 501 - var status = parseInt(this._request.status); - - switch (status) { - case 404: // Not Found - case 0: // Not Loaded - return new Error(status); - } - return null; - }; - - /** - * Validate the response. Different browsers have different approaches, some of which throw errors when accessed - * in other browsers. If there is no response, the _response property will remain null. - * @method _getResponse - * @private - */ - p._getResponse = function () { - if (this._response != null) { - return this._response; - } - - if (this._request.response != null) { - return this._request.response; - } - - // Android 2.2 uses .responseText - try { - if (this._request.responseText != null) { - return this._request.responseText; - } - } catch (e) { - } - - // When loading XML, IE9 does not return .response, instead it returns responseXML.xml - try { - if (this._request.responseXML != null) { - return this._request.responseXML; - } - } catch (e) { - } - - return null; - }; - - /** - * Create an XHR request. Depending on a number of factors, we get totally different results. - *
    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.RequestUtils.isCrossDomain(item); - var headers = {}; - - // Create the request. Fallback to whatever support we have. - var req = null; - if (window.XMLHttpRequest) { - req = new XMLHttpRequest(); - // This is 8 or 9, so use XDomainRequest instead. - if (crossdomain && req.withCredentials === undefined && window.XDomainRequest) { - req = new XDomainRequest(); - } - } else { // Old IE versions use a different approach - for (var i = 0, l = s.ACTIVEX_VERSIONS.length; i < l; i++) { - var axVersion = s.ACTIVEX_VERSIONS[i]; - try { - req = new ActiveXObject(axVersion); - break; - } catch (e) { - } - } - if (req == null) { - return false; - } - } - - // Default to utf-8 for Text requests. - if (item.mimeType == null && createjs.RequestUtils.isText(item.type)) { - item.mimeType = "text/plain; charset=utf-8"; - } - - // IE9 doesn't support overrideMimeType(), so we need to check for it. - if (item.mimeType && req.overrideMimeType) { - req.overrideMimeType(item.mimeType); - } - - // Determine the XHR level - this._xhrLevel = (typeof req.responseType === "string") ? 2 : 1; - - var src = null; - if (item.method == createjs.AbstractLoader.GET) { - src = createjs.RequestUtils.buildPath(item.src, item.values); - } else { - src = item.src; - } - - // Open the request. Set cross-domain flags if it is supported (XHR level 1 only) - req.open(item.method || createjs.AbstractLoader.GET, src, true); - - if (crossdomain && req instanceof XMLHttpRequest && this._xhrLevel == 1) { - headers["Origin"] = location.origin; - } - - // To send data we need to set the Content-type header) - if (item.values && item.method == createjs.AbstractLoader.POST) { - headers["Content-Type"] = "application/x-www-form-urlencoded"; - } - - if (!crossdomain && !headers["X-Requested-With"]) { - headers["X-Requested-With"] = "XMLHttpRequest"; - } - - if (item.headers) { - for (var n in item.headers) { - headers[n] = item.headers[n]; - } - } - - for (n in headers) { - req.setRequestHeader(n, headers[n]) - } - - if (req instanceof XMLHttpRequest && item.withCredentials !== undefined) { - req.withCredentials = item.withCredentials; - } - - this._request = req; - - return true; - }; - - /** - * A request has completed (or failed or canceled), and needs to be disposed. - * @method _clean - * @private - */ - p._clean = function () { - clearTimeout(this._loadTimeout); - - if (this._request.removeEventListener != null) { - this._request.removeEventListener("loadstart", this._handleLoadStartProxy); - this._request.removeEventListener("progress", this._handleProgressProxy); - this._request.removeEventListener("abort", this._handleAbortProxy); - this._request.removeEventListener("error", this._handleErrorProxy); - this._request.removeEventListener("timeout", this._handleTimeoutProxy); - this._request.removeEventListener("load", this._handleLoadProxy); - this._request.removeEventListener("readystatechange", this._handleReadyStateChangeProxy); - } else { - this._request.onloadstart = null; - this._request.onprogress = null; - this._request.onabort = null; - this._request.onerror = null; - this._request.ontimeout = null; - this._request.onload = null; - this._request.onreadystatechange = null; - } - }; - - p.toString = function () { - return "[PreloadJS XHRRequest]"; - }; - - createjs.XHRRequest = createjs.promote(XHRRequest, "AbstractRequest"); - -}()); - -//############################################################################## -// LoadQueue.js -//############################################################################## - -this.createjs = this.createjs || {}; - -/* - TODO: WINDOWS ISSUES - * No error for HTML audio in IE 678 - * SVG no failure error in IE 67 (maybe 8) TAGS AND XHR - * No script complete handler in IE 67 TAGS (XHR is fine) - * No XML/JSON in IE6 TAGS - * Need to hide loading SVG in Opera TAGS - * No CSS onload/readystatechange in Safari or Android TAGS (requires rule checking) - * SVG no load or failure in Opera XHR - * Reported issues with IE7/8 - */ - -(function () { - "use strict"; - -// constructor - /** - * The LoadQueue class is the main API for preloading content. LoadQueue is a load manager, which can preload either - * a single file, or queue of files. - * - * Creating a Queue
    - * To use LoadQueue, create a LoadQueue instance. If you want to force tag loading where possible, set the preferXHR - * argument to false. - * - * var queue = new createjs.LoadQueue(true); - * - * Listening for Events
    - * Add any listeners you want to the queue. Since PreloadJS 0.3.0, the {{#crossLink "EventDispatcher"}}{{/crossLink}} - * lets you add as many listeners as you want for events. You can subscribe to the following events:
      - *
    • {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}: fired when a queue completes loading all - * files
    • - *
    • {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}}: fired when the queue encounters an error with - * any file.
    • - *
    • {{#crossLink "AbstractLoader/progress:event"}}{{/crossLink}}: Progress for the entire queue has - * changed.
    • - *
    • {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}}: A single file has completed loading.
    • - *
    • {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}}: Progress for a single file has changes. Note - * that only files loaded with XHR (or possibly by plugins) will fire progress events other than 0 or 100%.
    • - *
    - * - * queue.on("fileload", handleFileLoad, this); - * queue.on("complete", handleComplete, this); - * - * Adding files and manifests
    - * Add files you want to load using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or add multiple files at a - * time using a list or a manifest definition using {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. Files are - * appended to the end of the active queue, so you can use these methods as many times as you like, whenever you - * like. - * - * queue.loadFile("filePath/file.jpg"); - * queue.loadFile({id:"image", src:"filePath/file.jpg"}); - * queue.loadManifest(["filePath/file.jpg", {id:"image", src:"filePath/file.jpg"}]); - * - * // Use an external manifest - * queue.loadManifest("path/to/manifest.json"); - * queue.loadManifest({src:"manifest.json", type:"manifest"}); - * - * If you pass `false` as the `loadNow` parameter, the queue will not kick of the load of the files, but it will not - * stop if it has already been started. Call the {{#crossLink "AbstractLoader/load"}}{{/crossLink}} method to begin - * a paused queue. Note that a paused queue will automatically resume when new files are added to it with a - * `loadNow` argument of `true`. - * - * queue.load(); - * - * File Types
    - * The file type of a manifest item is auto-determined by the file extension. The pattern matching in PreloadJS - * should handle the majority of standard file and url formats, and works with common file extensions. If you have - * either a non-standard file extension, or are serving the file using a proxy script, then you can pass in a - * type property with any manifest item. - * - * queue.loadFile({src:"path/to/myFile.mp3x", type:createjs.AbstractLoader.SOUND}); - * - * // Note that PreloadJS will not read a file extension from the query string - * queue.loadFile({src:"http://server.com/proxy?file=image.jpg", type:createjs.AbstractLoader.IMAGE}); - * - * Supported types are defined on the {{#crossLink "AbstractLoader"}}{{/crossLink}} class, and include: - *
      - *
    • {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}}: Raw binary data via XHR
    • - *
    • {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}: CSS files
    • - *
    • {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}: Common image formats
    • - *
    • {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}}: JavaScript files
    • - *
    • {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}: JSON data
    • - *
    • {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}: JSON files cross-domain
    • - *
    • {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}: A list of files to load in JSON format, see - * {{#crossLink "AbstractLoader/loadManifest"}}{{/crossLink}}
    • - *
    • {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}: Audio file formats
    • - *
    • {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}: JSON SpriteSheet definitions. This - * will also load sub-images, and provide a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance.
    • - *
    • {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}}: SVG files
    • - *
    • {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}}: Text files - XHR only
    • - *
    • {{#crossLink "AbstractLoader/VIDEO:property"}}{{/crossLink}}: Video objects
    • - *
    • {{#crossLink "AbstractLoader/XML:property"}}{{/crossLink}}: XML data
    • - *
    - * - * Note: Loader types used to be defined on LoadQueue, but have been moved to AbstractLoader for better - * portability of loader classes, which can be used individually now. The properties on LoadQueue still exist, but - * are deprecated. - * - * Handling Results
    - * When a file is finished downloading, a {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event is - * dispatched. In an example above, there is an event listener snippet for fileload. Loaded files are usually a - * formatted object that can be used immediately, including: - *
      - *
    • Binary: The binary loaded result
    • - *
    • CSS: A <link /> tag
    • - *
    • Image: An <img /> tag
    • - *
    • JavaScript: A <script /> tag
    • - *
    • JSON/JSONP: A formatted JavaScript Object
    • - *
    • Manifest: A JavaScript object. - *
    • Sound: An <audio /> tag - *
    • SpriteSheet: A {{#crossLink "SpriteSheet"}}{{/crossLink}} instance, containing loaded images. - *
    • SVG: An <object /> tag
    • - *
    • Text: Raw text
    • - *
    • Video: A Video DOM node
    • - *
    • XML: An XML DOM node
    • - *
    - * - * function handleFileLoad(event) { - * var item = event.item; // A reference to the item that was passed in to the LoadQueue - * var type = item.type; - * - * // Add any images to the page body. - * if (type == createjs.LoadQueue.IMAGE) { - * document.body.appendChild(event.result); - * } - * } - * - * At any time after the file has been loaded (usually after the queue has completed), any result can be looked up - * via its "id" using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. If no id was provided, then the - * "src" or file path can be used instead, including the `path` defined by a manifest, but not including - * a base path defined on the LoadQueue. It is recommended to always pass an id if you want to look up content. - * - * var image = queue.getResult("image"); - * document.body.appendChild(image); - * - * Raw loaded content can be accessed using the rawResult property of the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} - * event, or can be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}, passing `true` as the 2nd - * argument. This is only applicable for content that has been parsed for the browser, specifically: JavaScript, - * CSS, XML, SVG, and JSON objects, or anything loaded with XHR. - * - * var image = queue.getResult("image", true); // load the binary image data loaded with XHR. - * - * Plugins
    - * LoadQueue has a simple plugin architecture to help process and preload content. For example, to preload audio, - * make sure to install the SoundJS Sound class, which will help load HTML audio, - * Flash audio, and WebAudio files. This should be installed before loading any audio files. - * - * queue.installPlugin(createjs.Sound); - * - *

    Known Browser Issues

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

    Example

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

    Example

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

    Example

    - * - * var queue = new createjs.LoadQueue(); - * queue.setMaxConnections(10); // Allow 10 concurrent loads - * - * @method setMaxConnections - * @param {Number} value The number of concurrent loads to allow. By default, only a single connection per LoadQueue - * is open at any time. - */ - p.setMaxConnections = function (value) { - this._maxConnections = value; - if (!this._paused && this._loadQueue.length > 0) { - this._loadNext(); - } - }; - - /** - * Load a single file. To add multiple files at once, use the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * method. - * - * Files are always appended to the current queue, so this method can be used multiple times to add files. - * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method. - * @method loadFile - * @param {LoadItem|Object|String} file The file object or path to load. A file can be either - *
      - *
    • A {{#crossLink "LoadItem"}}{{/crossLink}} instance
    • - *
    • An object containing properties defined by {{#crossLink "LoadItem"}}{{/crossLink}}
    • - *
    • OR A string path to a resource. Note that this kind of load item will be converted to a {{#crossLink "LoadItem"}}{{/crossLink}} - * in the background.
    • - *
    - * @param {Boolean} [loadNow=true] Kick off an immediate load (true) or wait for a load call (false). The default - * value is true. If the queue is paused using {{#crossLink "LoadQueue/setPaused"}}{{/crossLink}}, and the value is - * `true`, the queue will resume automatically. - * @param {String} [basePath] A base path that will be prepended to each file. The basePath argument overrides the - * path specified in the constructor. Note that if you load a manifest using a file of type {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}, - * its files will NOT use the basePath parameter. The basePath parameter is deprecated. - * This parameter will be removed in a future version. Please either use the `basePath` parameter in the LoadQueue - * constructor, or a `path` property in a manifest definition. - */ - p.loadFile = function (file, loadNow, basePath) { - if (file == null) { - var event = new createjs.ErrorEvent("PRELOAD_NO_FILE"); - this._sendError(event); - return; - } - this._addItem(file, null, basePath); - - if (loadNow !== false) { - this.setPaused(false); - } else { - this.setPaused(true); - } - }; - - /** - * Load an array of files. To load a single file, use the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} method. - * The files in the manifest are requested in the same order, but may complete in a different order if the max - * connections are set above 1 using {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}}. Scripts will load - * in the right order as long as {{#crossLink "LoadQueue/maintainScriptOrder"}}{{/crossLink}} is true (which is - * default). - * - * Files are always appended to the current queue, so this method can be used multiple times to add files. - * To clear the queue first, use the {{#crossLink "AbstractLoader/close"}}{{/crossLink}} method. - * @method loadManifest - * @param {Array|String|Object} manifest An list of files to load. The loadManifest call supports four types of - * manifests: - *
      - *
    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.LoadQueue.JAVASCRIPT - //&& loader instanceof createjs.XHRLoader //NOTE: Have to track all JS files this way - ) - || item.maintainOrder === true) { - this._scriptOrder.push(item); - this._loadedScripts.push(null); - } - } - }; - - /** - * Create a refined {{#crossLink "LoadItem"}}{{/crossLink}}, which contains all the required properties. The type of - * item is determined by browser support, requirements based on the file type, and developer settings. For example, - * XHR is only used for file types that support it in new browsers. - * - * Before the item is returned, any plugins registered to handle the type or extension will be fired, which may - * alter the load item. - * @method _createLoadItem - * @param {String | Object | HTMLAudioElement | HTMLImageElement} value The item that needs to be preloaded. - * @param {String} [path] A path to prepend to the item's source. Sources beginning with http:// or similar will - * not receive a path. Since PreloadJS 0.4.1, the src will be modified to include the `path` and {{#crossLink "LoadQueue/_basePath:property"}}{{/crossLink}} - * when it is added. - * @param {String} [basePath] Deprectated A base path to prepend to the items source in addition to - * the path argument. - * @return {Object} The loader instance that will be used. - * @private - */ - p._createLoadItem = function (value, path, basePath) { - var item = createjs.LoadItem.create(value); - if (item == null) { - return null; - } - - var bp = ""; // Store the generated basePath - var useBasePath = basePath || this._basePath; - - if (item.src instanceof Object) { - if (!item.type) { - return null; - } // the the src is an object, type is required to pass off to plugin - if (path) { - bp = path; - var pathMatch = createjs.RequestUtils.parseURI(path); - // Also append basePath - if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) { - bp = useBasePath + bp; - } - } else if (useBasePath != null) { - bp = useBasePath; - } - } else { - // Determine Extension, etc. - var match = createjs.RequestUtils.parseURI(item.src); - if (match.extension) { - item.ext = match.extension; - } - if (item.type == null) { - item.type = createjs.RequestUtils.getTypeByExtension(item.ext); - } - - // Inject path & basePath - var autoId = item.src; - if (!match.absolute && !match.relative) { - if (path) { - bp = path; - var pathMatch = createjs.RequestUtils.parseURI(path); - autoId = path + autoId; - // Also append basePath - if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) { - bp = useBasePath + bp; - } - } else if (useBasePath != null) { - bp = useBasePath; - } - } - item.src = bp + item.src; - } - item.path = bp; - - // If there's no id, set one now. - if (item.id === undefined || item.id === null || item.id === "") { - item.id = autoId; - } - - // Give plugins a chance to modify the loadItem: - var customHandler = this._typeCallbacks[item.type] || this._extensionCallbacks[item.ext]; - if (customHandler) { - // Plugins are now passed both the full source, as well as a combined path+basePath (appropriately) - var result = customHandler.callback.call(customHandler.scope, item, this); - - // The plugin will handle the load, or has canceled it. Ignore it. - if (result === false) { - return null; - - // Load as normal: - } else if (result === true) { - // Do Nothing - - // Result is a loader class: - } else if (result != null) { - item._loader = result; - } - - // Update the extension in case the type changed: - match = createjs.RequestUtils.parseURI(item.src); - if (match.extension != null) { - item.ext = match.extension; - } - } - - // Store the item for lookup. This also helps clean-up later. - this._loadItemsById[item.id] = item; - this._loadItemsBySrc[item.src] = item; - - if (item.crossOrigin == null) { - item.crossOrigin = this._crossOrigin; - } - - return item; - }; - - /** - * Create a loader for a load item. - * @method _createLoader - * @param {Object} item A formatted load item that can be used to generate a loader. - * @return {AbstractLoader} A loader that can be used to load content. - * @private - */ - p._createLoader = function (item) { - if (item._loader != null) { // A plugin already specified a loader - return item._loader; - } - - // Initially, try and use the provided/supported XHR mode: - var preferXHR = this.preferXHR; - - for (var i = 0; i < this._availableLoaders.length; i++) { - var loader = this._availableLoaders[i]; - if (loader && loader.canLoadItem(item)) { - return new loader(item, preferXHR); - } - } - - // TODO: Log error (requires createjs.log) - return null; - }; - - /** - * Load the next item in the queue. If the queue is empty (all items have been loaded), then the complete event - * is processed. The queue will "fill up" any empty slots, up to the max connection specified using - * {{#crossLink "LoadQueue.setMaxConnections"}}{{/crossLink}} method. The only exception is scripts that are loaded - * using tags, which have to be loaded one at a time to maintain load order. - * @method _loadNext - * @private - */ - p._loadNext = function () { - if (this._paused) { - return; - } - - // Only dispatch loadstart event when the first file is loaded. - if (!this._loadStartWasDispatched) { - this._sendLoadStart(); - this._loadStartWasDispatched = true; - } - - // The queue has completed. - if (this._numItems == this._numItemsLoaded) { - this.loaded = true; - this._sendComplete(); - - // Load the next queue, if it has been defined. - if (this.next && this.next.load) { - this.next.load(); - } - } else { - this.loaded = false; - } - - // Must iterate forwards to load in the right order. - for (var i = 0; i < this._loadQueue.length; i++) { - if (this._currentLoads.length >= this._maxConnections) { - break; - } - var loader = this._loadQueue[i]; - - // Determine if we should be only loading one tag-script at a time: - // Note: maintainOrder items don't do anything here because we can hold onto their loaded value - if (!this._canStartLoad(loader)) { - continue; - } - this._loadQueue.splice(i, 1); - i--; - this._loadItem(loader); - } - }; - - /** - * Begin loading an item. Event listeners are not added to the loaders until the load starts. - * @method _loadItem - * @param {AbstractLoader} loader The loader instance to start. Currently, this will be an XHRLoader or TagLoader. - * @private - */ - p._loadItem = function (loader) { - loader.on("fileload", this._handleFileLoad, this); - loader.on("progress", this._handleProgress, this); - loader.on("complete", this._handleFileComplete, this); - loader.on("error", this._handleError, this); - loader.on("fileerror", this._handleFileError, this); - this._currentLoads.push(loader); - this._sendFileStart(loader.getItem()); - loader.load(); - }; - - /** - * The callback that is fired when a loader loads a file. This enables loaders like {{#crossLink "ManifestLoader"}}{{/crossLink}} - * to maintain internal queues, but for this queue to dispatch the {{#crossLink "fileload:event"}}{{/crossLink}} - * events. - * @param {Event} event The {{#crossLink "AbstractLoader/fileload:event"}}{{/crossLink}} event from the loader. - * @private - * @since 0.6.0 - */ - p._handleFileLoad = function (event) { - event.target = null; - this.dispatchEvent(event); - }; - - /** - * The callback that is fired when a loader encounters an error from an internal file load operation. This enables - * loaders like M - * @param event - * @private - */ - p._handleFileError = function (event) { - var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, event.item); - this._sendError(newEvent); - }; - - /** - * The callback that is fired when a loader encounters an error. The queue will continue loading unless {{#crossLink "LoadQueue/stopOnError:property"}}{{/crossLink}} - * is set to `true`. - * @method _handleError - * @param {ErrorEvent} event The error event, containing relevant error information. - * @private - */ - p._handleError = function (event) { - var loader = event.target; - this._numItemsLoaded++; - - this._finishOrderedItem(loader, true); - this._updateProgress(); - - var newEvent = new createjs.ErrorEvent("FILE_LOAD_ERROR", null, loader.getItem()); - // TODO: Propagate actual error message. - - this._sendError(newEvent); - - if (!this.stopOnError) { - this._removeLoadItem(loader); - this._cleanLoadItem(loader); - this._loadNext(); - } else { - this.setPaused(true); - } - }; - - /** - * An item has finished loading. We can assume that it is totally loaded, has been parsed for immediate use, and - * is available as the "result" property on the load item. The raw text result for a parsed item (such as JSON, XML, - * CSS, JavaScript, etc) is available as the "rawResult" property, and can also be looked up using {{#crossLink "LoadQueue/getResult"}}{{/crossLink}}. - * @method _handleFileComplete - * @param {Event} event The event object from the loader. - * @private - */ - p._handleFileComplete = function (event) { - var loader = event.target; - var item = loader.getItem(); - - var result = loader.getResult(); - this._loadedResults[item.id] = result; - var rawResult = loader.getResult(true); - if (rawResult != null && rawResult !== result) { - this._loadedRawResults[item.id] = rawResult; - } - - this._saveLoadedItems(loader); - - // Remove the load item - this._removeLoadItem(loader); - - if (!this._finishOrderedItem(loader)) { - // The item was NOT managed, so process it now - this._processFinishedLoad(item, loader); - } - - // Clean up the load item - this._cleanLoadItem(loader); - }; - - /** - * Some loaders might load additional content, other than the item they were passed (such as {{#crossLink "ManifestLoader"}}{{/crossLink}}). - * Any items exposed by the loader using {{#crossLink "AbstractLoader/getLoadItems"}}{{/crossLink}} are added to the - * LoadQueue's look-ups, including {{#crossLink "getItem"}}{{/crossLink}} and {{#crossLink "getResult"}}{{/crossLink}} - * methods. - * @method _saveLoadedItems - * @param {AbstractLoader} loader - * @protected - * @since 0.6.0 - */ - p._saveLoadedItems = function (loader) { - // TODO: Not sure how to handle this. Would be nice to expose the items. - // Loaders may load sub-items. This adds them to this queue - var list = loader.getLoadedItems(); - if (list === null) { - return; - } - - for (var i = 0; i < list.length; i++) { - var item = list[i].item; - - // Store item lookups - this._loadItemsBySrc[item.src] = item; - this._loadItemsById[item.id] = item; - - // Store loaded content - this._loadedResults[item.id] = list[i].result; - this._loadedRawResults[item.id] = list[i].rawResult; - } - }; - - /** - * Flag an item as finished. If the item's order is being managed, then ensure that it is allowed to finish, and if - * so, trigger prior items to trigger as well. - * @method _finishOrderedItem - * @param {AbstractLoader} loader - * @param {Boolean} loadFailed - * @return {Boolean} If the item's order is being managed. This allows the caller to take an alternate - * behaviour if it is. - * @private - */ - p._finishOrderedItem = function (loader, loadFailed) { - var item = loader.getItem(); - - if ((this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT) - || item.maintainOrder) { - - //TODO: Evaluate removal of the _currentlyLoadingScript - if (loader instanceof createjs.JavaScriptLoader) { - this._currentlyLoadingScript = false; - } - - var index = createjs.indexOf(this._scriptOrder, item); - if (index == -1) { - return false; - } // This loader no longer exists - this._loadedScripts[index] = (loadFailed === true) ? true : item; - - this._checkScriptLoadOrder(); - return true; - } - - return false; - }; - - /** - * Ensure the scripts load and dispatch in the correct order. When using XHR, scripts are stored in an array in the - * order they were added, but with a "null" value. When they are completed, the value is set to the load item, - * and then when they are processed and dispatched, the value is set to `true`. This method simply - * iterates the array, and ensures that any loaded items that are not preceded by a `null` value are - * dispatched. - * @method _checkScriptLoadOrder - * @private - */ - p._checkScriptLoadOrder = function () { - var l = this._loadedScripts.length; - - for (var i = 0; i < l; i++) { - var item = this._loadedScripts[i]; - if (item === null) { - break; - } // This is still loading. Do not process further. - if (item === true) { - continue; - } // This has completed, and been processed. Move on. - - var loadItem = this._loadedResults[item.id]; - if (item.type == createjs.LoadQueue.JAVASCRIPT) { - // Append script tags to the head automatically. - createjs.DomUtils.appendToHead(loadItem); - } - - var loader = item._loader; - this._processFinishedLoad(item, loader); - this._loadedScripts[i] = true; - } - }; - - /** - * A file has completed loading, and the LoadQueue can move on. This triggers the complete event, and kick-starts - * the next item. - * @method _processFinishedLoad - * @param {LoadItem|Object} item - * @param {AbstractLoader} loader - * @protected - */ - p._processFinishedLoad = function (item, loader) { - this._numItemsLoaded++; - - // Since LoadQueue needs maintain order, we can't append scripts in the loader. - // So we do it here instead. Or in _checkScriptLoadOrder(); - if (!this.maintainScriptOrder && item.type == createjs.LoadQueue.JAVASCRIPT) { - var tag = loader.getTag(); - createjs.DomUtils.appendToHead(tag); - } - - this._updateProgress(); - this._sendFileComplete(item, loader); - this._loadNext(); - }; - - /** - * Ensure items with `maintainOrder=true` that are before the specified item have loaded. This only applies to - * JavaScript items that are being loaded with a TagLoader, since they have to be loaded and completed before - * the script can even be started, since it exist in the DOM while loading. - * @method _canStartLoad - * @param {AbstractLoader} loader The loader for the item - * @return {Boolean} Whether the item can start a load or not. - * @private - */ - p._canStartLoad = function (loader) { - if (!this.maintainScriptOrder || loader.preferXHR) { - return true; - } - var item = loader.getItem(); - if (item.type != createjs.LoadQueue.JAVASCRIPT) { - return true; - } - if (this._currentlyLoadingScript) { - return false; - } - - var index = this._scriptOrder.indexOf(item); - var i = 0; - while (i < index) { - var checkItem = this._loadedScripts[i]; - if (checkItem == null) { - return false; - } - i++; - } - this._currentlyLoadingScript = true; - return true; - }; - - /** - * A load item is completed or was canceled, and needs to be removed from the LoadQueue. - * @method _removeLoadItem - * @param {AbstractLoader} loader A loader instance to remove. - * @private - */ - p._removeLoadItem = function (loader) { - var l = this._currentLoads.length; - for (var i = 0; i < l; i++) { - if (this._currentLoads[i] == loader) { - this._currentLoads.splice(i, 1); - break; - } - } - }; - - /** - * Remove unneeded references from a loader. - * - * @param loader - * @private - */ - p._cleanLoadItem = function(loader) { - var item = loader.getItem(); - if (item) { - delete item._loader; - } - } - - /** - * An item has dispatched progress. Propagate that progress, and update the LoadQueue's overall progress. - * @method _handleProgress - * @param {ProgressEvent} event The progress event from the item. - * @private - */ - p._handleProgress = function (event) { - var loader = event.target; - this._sendFileProgress(loader.getItem(), loader.progress); - this._updateProgress(); - }; - - /** - * Overall progress has changed, so determine the new progress amount and dispatch it. This changes any time an - * item dispatches progress or completes. Note that since we don't always know the actual filesize of items before - * they are loaded. In this case, we define a "slot" for each item (1 item in 10 would get 10%), and then append - * loaded progress on top of the already-loaded items. - * - * For example, if 5/10 items have loaded, and item 6 is 20% loaded, the total progress would be: - *
      - *
    • 5/10 of the items in the queue (50%)
    • - *
    • plus 20% of item 6's slot (2%)
    • - *
    • equals 52%
    • - *
    - * @method _updateProgress - * @private - */ - p._updateProgress = function () { - var loaded = this._numItemsLoaded / this._numItems; // Fully Loaded Progress - var remaining = this._numItems - this._numItemsLoaded; - if (remaining > 0) { - var chunk = 0; - for (var i = 0, l = this._currentLoads.length; i < l; i++) { - chunk += this._currentLoads[i].progress; - } - loaded += (chunk / remaining) * (remaining / this._numItems); - } - - if (this._lastProgress != loaded) { - this._sendProgress(loaded); - this._lastProgress = loaded; - } - }; - - /** - * Clean out item results, to free them from memory. Mainly, the loaded item and results are cleared from internal - * hashes. - * @method _disposeItem - * @param {LoadItem|Object} item The item that was passed in for preloading. - * @private - */ - p._disposeItem = function (item) { - delete this._loadedResults[item.id]; - delete this._loadedRawResults[item.id]; - delete this._loadItemsById[item.id]; - delete this._loadItemsBySrc[item.src]; - }; - - /** - * Dispatch a "fileprogress" {{#crossLink "Event"}}{{/crossLink}}. Please see the LoadQueue {{#crossLink "LoadQueue/fileprogress:event"}}{{/crossLink}} - * event for details on the event payload. - * @method _sendFileProgress - * @param {LoadItem|Object} item The item that is being loaded. - * @param {Number} progress The amount the item has been loaded (between 0 and 1). - * @protected - */ - p._sendFileProgress = function (item, progress) { - if (this._isCanceled() || this._paused) { - return; - } - if (!this.hasEventListener("fileprogress")) { - return; - } - - //LM: Rework ProgressEvent to support this? - var event = new createjs.Event("fileprogress"); - event.progress = progress; - event.loaded = progress; - event.total = 1; - event.item = item; - - this.dispatchEvent(event); - }; - - /** - * Dispatch a fileload {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event for - * details on the event payload. - * @method _sendFileComplete - * @param {LoadItemObject} item The item that is being loaded. - * @param {AbstractLoader} loader - * @protected - */ - p._sendFileComplete = function (item, loader) { - if (this._isCanceled() || this._paused) { - return; - } - - var event = new createjs.Event("fileload"); - event.loader = loader; - event.item = item; - event.result = this._loadedResults[item.id]; - event.rawResult = this._loadedRawResults[item.id]; - - // This calls a handler specified on the actual load item. Currently, the SoundJS plugin uses this. - if (item.completeHandler) { - item.completeHandler(event); - } - - this.hasEventListener("fileload") && this.dispatchEvent(event); - }; - - /** - * Dispatch a filestart {{#crossLink "Event"}}{{/crossLink}} immediately before a file starts to load. Please see - * the {{#crossLink "LoadQueue/filestart:event"}}{{/crossLink}} event for details on the event payload. - * @method _sendFileStart - * @param {LoadItem|Object} item The item that is being loaded. - * @protected - */ - p._sendFileStart = function (item) { - var event = new createjs.Event("filestart"); - event.item = item; - this.hasEventListener("filestart") && this.dispatchEvent(event); - }; - - p.toString = function () { - return "[PreloadJS LoadQueue]"; - }; - - createjs.LoadQueue = createjs.promote(LoadQueue, "AbstractLoader"); -}()); - -//############################################################################## -// TextLoader.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - // constructor - /** - * A loader for Text files. - * @class TextLoader - * @param {LoadItem|Object} loadItem - * @extends AbstractLoader - * @constructor - */ - function TextLoader(loadItem) { - this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.TEXT); - }; - - var p = createjs.extend(TextLoader, createjs.AbstractLoader); - var s = TextLoader; - - // static methods - /** - * Determines if the loader can load a specific item. This loader loads items that are of type {{#crossLink "AbstractLoader/TEXT:property"}}{{/crossLink}}, - * but is also the default loader if a file type can not be determined. - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.TEXT; - }; - - createjs.TextLoader = createjs.promote(TextLoader, "AbstractLoader"); - -}()); - -//############################################################################## -// BinaryLoader.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - // constructor - /** - * A loader for binary files. This is useful for loading web audio, or content that requires an ArrayBuffer. - * @class BinaryLoader - * @param {LoadItem|Object} loadItem - * @extends AbstractLoader - * @constructor - */ - function BinaryLoader(loadItem) { - this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.BINARY); - this.on("initialize", this._updateXHR, this); - }; - - var p = createjs.extend(BinaryLoader, createjs.AbstractLoader); - var s = BinaryLoader; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/BINARY:property"}}{{/crossLink}} - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.BINARY; - }; - - // private methods - /** - * Before the item loads, set the response type to "arraybuffer" - * @property _updateXHR - * @param {Event} event - * @private - */ - p._updateXHR = function (event) { - event.loader.setResponseType("arraybuffer"); - }; - - createjs.BinaryLoader = createjs.promote(BinaryLoader, "AbstractLoader"); - -}()); - -//############################################################################## -// CSSLoader.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - // constructor - /** - * A loader for CSS files. - * @class CSSLoader - * @param {LoadItem|Object} loadItem - * @param {Boolean} preferXHR - * @extends AbstractLoader - * @constructor - */ - function CSSLoader(loadItem, preferXHR) { - this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.CSS); - - // public properties - this.resultFormatter = this._formatResult; - - // protected properties - this._tagSrcAttribute = "href"; - - if (preferXHR) { - this._tag = document.createElement("style"); - } else { - this._tag = document.createElement("link"); - } - - this._tag.rel = "stylesheet"; - this._tag.type = "text/css"; - }; - - var p = createjs.extend(CSSLoader, createjs.AbstractLoader); - var s = CSSLoader; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/CSS:property"}}{{/crossLink}}. - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.CSS; - }; - - // protected methods - /** - * The result formatter for CSS files. - * @method _formatResult - * @param {AbstractLoader} loader - * @returns {HTMLLinkElement|HTMLStyleElement} - * @private - */ - p._formatResult = function (loader) { - if (this._preferXHR) { - var tag = loader.getTag(); - - if (tag.styleSheet) { // IE - tag.styleSheet.cssText = loader.getResult(true); - } else { - var textNode = document.createTextNode(loader.getResult(true)); - tag.appendChild(textNode); - } - } else { - tag = this._tag; - } - - createjs.DomUtils.appendToHead(tag); - - return tag; - }; - - createjs.CSSLoader = createjs.promote(CSSLoader, "AbstractLoader"); - -}()); - -//############################################################################## -// ImageLoader.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - // constructor - /** - * A loader for image files. - * @class ImageLoader - * @param {LoadItem|Object} loadItem - * @param {Boolean} preferXHR - * @extends AbstractLoader - * @constructor - */ - function ImageLoader (loadItem, preferXHR) { - this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.IMAGE); - - // public properties - this.resultFormatter = this._formatResult; - - // protected properties - this._tagSrcAttribute = "src"; - - // Check if the preload item is already a tag. - if (createjs.RequestUtils.isImageTag(loadItem)) { - this._tag = loadItem; - } else if (createjs.RequestUtils.isImageTag(loadItem.src)) { - this._tag = loadItem.src; - } else if (createjs.RequestUtils.isImageTag(loadItem.tag)) { - this._tag = loadItem.tag; - } - - if (this._tag != null) { - this._preferXHR = false; - } else { - this._tag = document.createElement("img"); - } - - this.on("initialize", this._updateXHR, this); - }; - - var p = createjs.extend(ImageLoader, createjs.AbstractLoader); - var s = ImageLoader; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/IMAGE:property"}}{{/crossLink}}. - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.IMAGE; - }; - - // public methods - p.load = function () { - if (this._tag.src != "" && this._tag.complete) { - this._sendComplete(); - return; - } - - var crossOrigin = this._item.crossOrigin; - if (crossOrigin == true) { crossOrigin = "Anonymous"; } - if (crossOrigin != null && !createjs.RequestUtils.isLocal(this._item.src)) { - this._tag.crossOrigin = crossOrigin; - } - - this.AbstractLoader_load(); - }; - - // protected methods - /** - * Before the item loads, set its mimeType and responseType. - * @property _updateXHR - * @param {Event} event - * @private - */ - p._updateXHR = function (event) { - event.loader.mimeType = 'text/plain; charset=x-user-defined-binary'; - - // Only exists for XHR - if (event.loader.setResponseType) { - event.loader.setResponseType("blob"); - } - }; - - /** - * The result formatter for Image files. - * @method _formatResult - * @param {AbstractLoader} loader - * @returns {HTMLImageElement} - * @private - */ - p._formatResult = function (loader) { - return this._formatImage; - }; - - /** - * The asynchronous image formatter function. This is required because images have - * a short delay before they are ready. - * @method _formatImage - * @param {Function} successCallback The method to call when the result has finished formatting - * @param {Function} errorCallback The method to call if an error occurs during formatting - * @private - */ - p._formatImage = function (successCallback, errorCallback) { - var tag = this._tag; - var URL = window.URL || window.webkitURL; - - if (!this._preferXHR) { - //document.body.removeChild(tag); - } else if (URL) { - var objURL = URL.createObjectURL(this.getResult(true)); - tag.src = objURL; - - tag.addEventListener("load", this._cleanUpURL, false); - tag.addEventListener("error", this._cleanUpURL, false); - } else { - tag.src = this._item.src; - } - - if (tag.complete) { - successCallback(tag); - } else { - tag.onload = createjs.proxy(function() { - successCallback(this._tag); - }, this); - - tag.onerror = createjs.proxy(function() { - errorCallback(_this._tag); - }, this); - } - }; - - /** - * Clean up the ObjectURL, the tag is done with it. Note that this function is run - * as an event listener without a proxy/closure, as it doesn't require it - so do not - * include any functionality that requires scope without changing it. - * @method _cleanUpURL - * @param event - * @private - */ - p._cleanUpURL = function (event) { - var URL = window.URL || window.webkitURL; - URL.revokeObjectURL(event.target.src); - }; - - createjs.ImageLoader = createjs.promote(ImageLoader, "AbstractLoader"); - -}()); - -//############################################################################## -// JavaScriptLoader.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - // constructor - /** - * A loader for JavaScript files. - * @class JavaScriptLoader - * @param {LoadItem|Object} loadItem - * @param {Boolean} preferXHR - * @extends AbstractLoader - * @constructor - */ - function JavaScriptLoader(loadItem, preferXHR) { - this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.JAVASCRIPT); - - // public properties - this.resultFormatter = this._formatResult; - - // protected properties - this._tagSrcAttribute = "src"; - this.setTag(document.createElement("script")); - }; - - var p = createjs.extend(JavaScriptLoader, createjs.AbstractLoader); - var s = JavaScriptLoader; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/JAVASCRIPT:property"}}{{/crossLink}} - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.JAVASCRIPT; - }; - - // protected methods - /** - * The result formatter for JavaScript files. - * @method _formatResult - * @param {AbstractLoader} loader - * @returns {HTMLLinkElement|HTMLStyleElement} - * @private - */ - p._formatResult = function (loader) { - var tag = loader.getTag(); - if (this._preferXHR) { - tag.text = loader.getResult(true); - } - return tag; - }; - - createjs.JavaScriptLoader = createjs.promote(JavaScriptLoader, "AbstractLoader"); - -}()); - -//############################################################################## -// JSONLoader.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - // constructor - /** - * A loader for JSON files. To load JSON cross-domain, use JSONP and the {{#crossLink "JSONPLoader"}}{{/crossLink}} - * instead. To load JSON-formatted manifests, use {{#crossLink "ManifestLoader"}}{{/crossLink}}, and to - * load EaselJS SpriteSheets, use {{#crossLink "SpriteSheetLoader"}}{{/crossLink}}. - * @class JSONLoader - * @param {LoadItem|Object} loadItem - * @extends AbstractLoader - * @constructor - */ - function JSONLoader(loadItem) { - this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.JSON); - - // public properties - this.resultFormatter = this._formatResult; - }; - - var p = createjs.extend(JSONLoader, createjs.AbstractLoader); - var s = JSONLoader; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/JSON:property"}}{{/crossLink}}. - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.JSON; - }; - - // protected methods - /** - * The result formatter for JSON files. - * @method _formatResult - * @param {AbstractLoader} loader - * @returns {HTMLLinkElement|HTMLStyleElement} - * @private - */ - p._formatResult = function (loader) { - var json = null; - try { - json = createjs.DataUtils.parseJSON(loader.getResult(true)); - } catch (e) { - var event = new createjs.ErrorEvent("JSON_FORMAT", null, e); - this._sendError(event); - return e; - } - - return json; - }; - - createjs.JSONLoader = createjs.promote(JSONLoader, "AbstractLoader"); - -}()); - -//############################################################################## -// JSONPLoader.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - // constructor - /** - * A loader for JSONP files, which are JSON-formatted text files, wrapped in a callback. To load regular JSON - * without a callback use the {{#crossLink "JSONLoader"}}{{/crossLink}} instead. To load JSON-formatted manifests, - * use {{#crossLink "ManifestLoader"}}{{/crossLink}}, and to load EaselJS SpriteSheets, use - * {{#crossLink "SpriteSheetLoader"}}{{/crossLink}}. - * - * JSONP is a format that provides a solution for loading JSON files cross-domain without requiring CORS. - * JSONP files are loaded as JavaScript, and the "callback" is executed once they are loaded. The callback in the - * JSONP must match the callback passed to the loadItem. - * - *

    Example JSONP

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

    Example

    - * - * var loadItem = {id:"json", type:"jsonp", src:"http://server.com/text.json", callback:"callbackName"} - * var queue = new createjs.LoadQueue(); - * queue.on("complete", handleComplete); - * queue.loadItem(loadItem); - * - * function handleComplete(event) } - * var json = queue.getResult("json"); - * console.log(json.obj.bool); // true - * } - * - * Note that JSONP files loaded concurrently require a unique callback. To ensure JSONP files are loaded - * in order, either use the {{#crossLink "LoadQueue/setMaxConnections"}}{{/crossLink}} method (set to 1), - * or set {{#crossLink "LoadItem/maintainOrder:property"}}{{/crossLink}} on items with the same callback. - * - * @class JSONPLoader - * @param {LoadItem|Object} loadItem - * @extends AbstractLoader - * @constructor - */ - function JSONPLoader(loadItem) { - this.AbstractLoader_constructor(loadItem, false, createjs.AbstractLoader.JSONP); - this.setTag(document.createElement("script")); - this.getTag().type = "text/javascript"; - }; - - var p = createjs.extend(JSONPLoader, createjs.AbstractLoader); - var s = JSONPLoader; - - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/JSONP:property"}}{{/crossLink}}. - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.JSONP; - }; - - // public methods - p.cancel = function () { - this.AbstractLoader_cancel(); - this._dispose(); - }; - - /** - * Loads the JSONp file. Because of the unique loading needs of JSONp - * we don't use the AbstractLoader.load() method. - * - * @method load - * - */ - p.load = function () { - if (this._item.callback == null) { - throw new Error('callback is required for loading JSONP requests.'); - } - - // TODO: Look into creating our own iFrame to handle the load - // In the first attempt, FF did not get the result - // result instanceof Object did not work either - // so we would need to clone the result. - if (window[this._item.callback] != null) { - throw new Error( - "JSONP callback '" + - this._item.callback + - "' already exists on window. You need to specify a different callback or re-name the current one."); - } - - window[this._item.callback] = createjs.proxy(this._handleLoad, this); - window.document.body.appendChild(this._tag); - - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); - - // Load the tag - this._tag.src = this._item.src; - }; - - // private methods - /** - * Handle the JSONP callback, which is a public method defined on `window`. - * @method _handleLoad - * @param {Object} data The formatted JSON data. - * @private - */ - p._handleLoad = function (data) { - this._result = this._rawResult = data; - this._sendComplete(); - - this._dispose(); - }; - - /** - * The tag request has not loaded within the time specfied in loadTimeout. - * @method _handleError - * @param {Object} event The XHR error event. - * @private - */ - p._handleTimeout = function () { - this._dispose(); - this.dispatchEvent(new createjs.ErrorEvent("timeout")); - }; - - /** - * Clean up the JSONP load. This clears out the callback and script tag that this loader creates. - * @method _dispose - * @private - */ - p._dispose = function () { - window.document.body.removeChild(this._tag); - delete window[this._item.callback]; - - clearTimeout(this._loadTimeout); - }; - - createjs.JSONPLoader = createjs.promote(JSONPLoader, "AbstractLoader"); - -}()); - -//############################################################################## -// 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 "AbstractLoader/MANIFEST:property"}}{{/crossLink}}. - * @class ManifestLoader - * @param {LoadItem|Object} loadItem - * @extends AbstractLoader - * @constructor - */ - function ManifestLoader(loadItem) { - this.AbstractLoader_constructor(loadItem, null, createjs.AbstractLoader.MANIFEST); - - // Public Properties - /** - * An array of the plugins registered using {{#crossLink "LoadQueue/installPlugin"}}{{/crossLink}}, - * used to pass plugins to new LoadQueues that may be created. - * @property _plugins - * @type {Array} - * @private - * @since 0.6.1 - */ - this.plugins = null; - - - // Protected Properties - /** - * An internal {{#crossLink "LoadQueue"}}{{/crossLink}} that loads the contents of the manifest. - * @property _manifestQueue - * @type {LoadQueue} - * @private - */ - this._manifestQueue = null; - }; - - var p = createjs.extend(ManifestLoader, createjs.AbstractLoader); - var s = ManifestLoader; - - // static properties - /** - * The amount of progress that the manifest itself takes up. - * @property MANIFEST_PROGRESS - * @type {number} - * @default 0.25 (25%) - * @private - * @static - */ - s.MANIFEST_PROGRESS = 0.25; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}} - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.MANIFEST; - }; - - // public methods - p.load = function () { - this.AbstractLoader_load(); - }; - - // protected methods - p._createRequest = function() { - var callback = this._item.callback; - if (callback != null) { - this._request = new createjs.JSONPLoader(this._item); - } else { - this._request = new createjs.JSONLoader(this._item); - } - }; - - p.handleEvent = function (event) { - switch (event.type) { - case "complete": - this._rawResult = event.target.getResult(true); - this._result = event.target.getResult(); - this._sendProgress(s.MANIFEST_PROGRESS); - this._loadManifest(this._result); - return; - case "progress": - event.loaded *= s.MANIFEST_PROGRESS; - this.progress = event.loaded / event.total; - if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } - this._sendProgress(event); - return; - } - this.AbstractLoader_handleEvent(event); - }; - - p.destroy = function() { - this.AbstractLoader_destroy(); - this._manifestQueue.close(); - }; - - /** - * Create and load the manifest items once the actual manifest has been loaded. - * @method _loadManifest - * @param {Object} json - * @private - */ - p._loadManifest = function (json) { - if (json && json.manifest) { - var queue = this._manifestQueue = new createjs.LoadQueue(); - queue.on("fileload", this._handleManifestFileLoad, this); - queue.on("progress", this._handleManifestProgress, this); - queue.on("complete", this._handleManifestComplete, this, true); - queue.on("error", this._handleManifestError, this, true); - for(var i = 0, l = this.plugins.length; i < l; i++) { // conserve order of plugins - queue.installPlugin(this.plugins[i]); - } - queue.loadManifest(json); - } else { - this._sendComplete(); - } - }; - - /** - * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed. - * @method _handleManifestFileLoad - * @param {Event} event - * @private - */ - p._handleManifestFileLoad = function (event) { - event.target = null; - this.dispatchEvent(event); - }; - - /** - * The manifest has completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} - * {{#crossLink "Event"}}{{/crossLink}} from the ManifestLoader. - * @method _handleManifestComplete - * @param {Event} event - * @private - */ - p._handleManifestComplete = function (event) { - this._loadedItems = this._manifestQueue.getItems(true); - this._sendComplete(); - }; - - /** - * The manifest has reported progress. - * @method _handleManifestProgress - * @param {ProgressEvent} event - * @private - */ - p._handleManifestProgress = function (event) { - this.progress = event.progress * (1 - s.MANIFEST_PROGRESS) + s.MANIFEST_PROGRESS; - this._sendProgress(this.progress); - }; - - /** - * The manifest has reported an error with one of the files. - * @method _handleManifestError - * @param {ErrorEvent} event - * @private - */ - p._handleManifestError = function (event) { - var newEvent = new createjs.Event("fileerror"); - newEvent.item = event.data; - this.dispatchEvent(newEvent); - }; - - createjs.ManifestLoader = createjs.promote(ManifestLoader, "AbstractLoader"); - -}()); - -//############################################################################## -// 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.AbstractLoader.SOUND); - - // protected properties - if (createjs.RequestUtils.isAudioTag(loadItem)) { - this._tag = loadItem; - } else if (createjs.RequestUtils.isAudioTag(loadItem.src)) { - this._tag = loadItem; - } else if (createjs.RequestUtils.isAudioTag(loadItem.tag)) { - this._tag = createjs.RequestUtils.isAudioTag(loadItem) ? loadItem : loadItem.src; - } - - if (this._tag != null) { - this._preferXHR = false; - } - }; - - var p = createjs.extend(SoundLoader, createjs.AbstractMediaLoader); - var s = SoundLoader; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}. - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.SOUND; - }; - - // protected methods - p._createTag = function (src) { - var tag = document.createElement("audio"); - tag.autoplay = false; - tag.preload = "none"; - - //LM: Firefox fails when this the preload="none" for other tags, but it needs to be "none" to ensure PreloadJS works. - tag.src = src; - return tag; - }; - - createjs.SoundLoader = createjs.promote(SoundLoader, "AbstractMediaLoader"); - -}()); - -//############################################################################## -// 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.AbstractLoader.VIDEO); - - if (createjs.RequestUtils.isVideoTag(loadItem) || createjs.RequestUtils.isVideoTag(loadItem.src)) { - this.setTag(createjs.RequestUtils.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 document.createElement("video"); - }; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/VIDEO:property"}}{{/crossLink}}. - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.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 "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}}. - * - * The {{#crossLink "LoadItem"}}{{/crossLink}} {{#crossLink "LoadItem/crossOrigin:property"}}{{/crossLink}} as well - * as the {{#crossLink "LoadQueue's"}}{{/crossLink}} `basePath` argument and {{#crossLink "LoadQueue/_preferXHR"}}{{/crossLink}} - * property supplied to the {{#crossLink "LoadQueue"}}{{/crossLink}} are passed on to the sub-manifest that loads - * the SpriteSheet images. - * - * Note that the SpriteSheet JSON does not respect the {{#crossLink "LoadQueue/_preferXHR:property"}}{{/crossLink}} - * property, which should instead be determined by the presence of a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} - * property on the SpriteSheet load item. This is because the JSON loaded will have a different format depending on - * if it is loaded as JSON, so just changing `preferXHR` is not enough to change how it is loaded. - * @class SpriteSheetLoader - * @param {LoadItem|Object} loadItem - * @extends AbstractLoader - * @constructor - */ - function SpriteSheetLoader(loadItem, preferXHR) { - this.AbstractLoader_constructor(loadItem, preferXHR, createjs.AbstractLoader.SPRITESHEET); - - // protected properties - /** - * An internal queue which loads the SpriteSheet's images. - * @method _manifestQueue - * @type {LoadQueue} - * @private - */ - this._manifestQueue = null; - } - - var p = createjs.extend(SpriteSheetLoader, createjs.AbstractLoader); - var s = SpriteSheetLoader; - - // static properties - /** - * The amount of progress that the manifest itself takes up. - * @property SPRITESHEET_PROGRESS - * @type {number} - * @default 0.25 (25%) - * @private - * @static - */ - s.SPRITESHEET_PROGRESS = 0.25; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/SPRITESHEET:property"}}{{/crossLink}} - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.SPRITESHEET; - }; - - // public methods - p.destroy = function() { - this.AbstractLoader_destroy; - this._manifestQueue.close(); - }; - - // protected methods - p._createRequest = function() { - var callback = this._item.callback; - if (callback != null) { - this._request = new createjs.JSONPLoader(this._item); - } else { - this._request = new createjs.JSONLoader(this._item); - } - }; - - p.handleEvent = function (event) { - switch (event.type) { - case "complete": - this._rawResult = event.target.getResult(true); - this._result = event.target.getResult(); - this._sendProgress(s.SPRITESHEET_PROGRESS); - this._loadManifest(this._result); - return; - case "progress": - event.loaded *= s.SPRITESHEET_PROGRESS; - this.progress = event.loaded / event.total; - if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } - this._sendProgress(event); - return; - } - this.AbstractLoader_handleEvent(event); - }; - - /** - * Create and load the images once the SpriteSheet JSON has been loaded. - * @method _loadManifest - * @param {Object} json - * @private - */ - p._loadManifest = function (json) { - if (json && json.images) { - var queue = this._manifestQueue = new createjs.LoadQueue(this._preferXHR, this._item.path, this._item.crossOrigin); - queue.on("complete", this._handleManifestComplete, this, true); - queue.on("fileload", this._handleManifestFileLoad, this); - queue.on("progress", this._handleManifestProgress, this); - queue.on("error", this._handleManifestError, this, true); - queue.loadManifest(json.images); - } - }; - - /** - * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed. - * @method _handleManifestFileLoad - * @param {Event} event - * @private - */ - p._handleManifestFileLoad = function (event) { - var image = event.result; - if (image != null) { - var images = this.getResult().images; - var pos = images.indexOf(event.item.src); - images[pos] = image; - } - }; - - /** - * The images have completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} - * {{#crossLink "Event"}}{{/crossLink}} from the SpriteSheetLoader. - * @method _handleManifestComplete - * @param {Event} event - * @private - */ - p._handleManifestComplete = function (event) { - this._result = new createjs.SpriteSheet(this._result); - this._loadedItems = this._manifestQueue.getItems(true); - this._sendComplete(); - }; - - /** - * The images {{#crossLink "LoadQueue"}}{{/crossLink}} has reported progress. - * @method _handleManifestProgress - * @param {ProgressEvent} event - * @private - */ - p._handleManifestProgress = function (event) { - this.progress = event.progress * (1 - s.SPRITESHEET_PROGRESS) + s.SPRITESHEET_PROGRESS; - this._sendProgress(this.progress); - }; - - /** - * An image has reported an error. - * @method _handleManifestError - * @param {ErrorEvent} event - * @private - */ - p._handleManifestError = function (event) { - var newEvent = new createjs.Event("fileerror"); - newEvent.item = event.data; - this.dispatchEvent(newEvent); - }; - - createjs.SpriteSheetLoader = createjs.promote(SpriteSheetLoader, "AbstractLoader"); - -}()); - -//############################################################################## -// 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.AbstractLoader.SVG); - - // public properties - this.resultFormatter = this._formatResult; - - // protected properties - this._tagSrcAttribute = "data"; - - if (preferXHR) { - this.setTag(document.createElement("svg")); - } else { - this.setTag(document.createElement("object")); - this.getTag().type = "image/svg+xml"; - } - }; - - var p = createjs.extend(SVGLoader, createjs.AbstractLoader); - var s = SVGLoader; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/SVG:property"}}{{/crossLink}} - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.SVG; - }; - - // protected methods - /** - * The result formatter for SVG files. - * @method _formatResult - * @param {AbstractLoader} loader - * @returns {Object} - * @private - */ - p._formatResult = function (loader) { - // mime should be image/svg+xml, but Opera requires text/xml - var xml = createjs.DataUtils.parseXML(loader.getResult(true), "text/xml"); - var tag = loader.getTag(); - - if (!this._preferXHR && document.body.contains(tag)) { - document.body.removeChild(tag); - } - - if (xml.documentElement != null) { - tag.appendChild(xml.documentElement); - tag.style.visibility = "visible"; - return tag; - } else { // For browsers that don't support SVG, just give them the XML. (IE 9-8) - return xml; - } - }; - - createjs.SVGLoader = createjs.promote(SVGLoader, "AbstractLoader"); - -}()); - -//############################################################################## -// 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.AbstractLoader.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 "AbstractLoader/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.AbstractLoader.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), "text/xml"); - }; - - createjs.XMLLoader = createjs.promote(XMLLoader, "AbstractLoader"); - -}()); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/js/lib/soundjs-NEXT.combined.js b/bomberman/frontend/src/main/webapp/js/lib/soundjs-NEXT.combined.js deleted file mode 100644 index 6f898e826e..0000000000 --- a/bomberman/frontend/src/main/webapp/js/lib/soundjs-NEXT.combined.js +++ /dev/null @@ -1,7949 +0,0 @@ -/*! -* SoundJS -* Visit http://createjs.com/ for documentation, updates and examples. -* -* Copyright (c) 2010 gskinner.com, inc. -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, -* copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following -* conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -*/ - - -//############################################################################## -// version.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - - /** - * Static class holding library specific information such as the version and buildDate of the library. - * The SoundJS class has been renamed {{#crossLink "Sound"}}{{/crossLink}}. Please see {{#crossLink "Sound"}}{{/crossLink}} - * for information on using sound. - * @class SoundJS - **/ - var s = createjs.SoundJS = createjs.SoundJS || {}; - - /** - * The version string for this release. - * @property version - * @type String - * @static - **/ - s.version = /*=version*/"NEXT"; // injected by build process - - /** - * The build date for this release in UTC format. - * @property buildDate - * @type String - * @static - **/ - s.buildDate = /*=date*/"Fri, 04 Dec 2015 17:24:04 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; -}; - -//############################################################################## -// 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; -}; - -//############################################################################## -// 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)); - }; - } - -}()); - -//############################################################################## -// BrowserDetect.js -//############################################################################## - -this.createjs = this.createjs||{}; - -/** - * @class Utility Methods - */ -(function() { - "use strict"; - - /** - * An object that determines the current browser, version, operating system, and other environment - * variables via user agent string. - * - * Used for audio because feature detection is unable to detect the many limitations of mobile devices. - * - *

    Example

    - * - * if (createjs.BrowserDetect.isIOS) { // do stuff } - * - * @property BrowserDetect - * @type {Object} - * @param {Boolean} isFirefox True if our browser is Firefox. - * @param {Boolean} isOpera True if our browser is opera. - * @param {Boolean} isChrome True if our browser is Chrome. Note that Chrome for Android returns true, but is a - * completely different browser with different abilities. - * @param {Boolean} isIOS True if our browser is safari for iOS devices (iPad, iPhone, and iPod). - * @param {Boolean} isAndroid True if our browser is Android. - * @param {Boolean} isBlackberry True if our browser is Blackberry. - * @constructor - * @static - */ - function BrowserDetect() { - throw "BrowserDetect cannot be instantiated"; - }; - - var agent = BrowserDetect.agent = window.navigator.userAgent; - BrowserDetect.isWindowPhone = (agent.indexOf("IEMobile") > -1) || (agent.indexOf("Windows Phone") > -1); - BrowserDetect.isFirefox = (agent.indexOf("Firefox") > -1); - BrowserDetect.isOpera = (window.opera != null); - BrowserDetect.isChrome = (agent.indexOf("Chrome") > -1); // NOTE that Chrome on Android returns true but is a completely different browser with different abilities - BrowserDetect.isIOS = (agent.indexOf("iPod") > -1 || agent.indexOf("iPhone") > -1 || agent.indexOf("iPad") > -1) && !BrowserDetect.isWindowPhone; - BrowserDetect.isAndroid = (agent.indexOf("Android") > -1) && !BrowserDetect.isWindowPhone; - BrowserDetect.isBlackberry = (agent.indexOf("Blackberry") > -1); - - createjs.BrowserDetect = BrowserDetect; - -}()); - -//############################################################################## -// EventDispatcher.js -//############################################################################## - -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; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// static public methods: - /** - * Static initializer to mix EventDispatcher methods into a target object or prototype. - * - * EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class - * EventDispatcher.initialize(myObject); // add to a specific instance - * - * @method initialize - * @static - * @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a - * prototype. - **/ - EventDispatcher.initialize = function(target) { - target.addEventListener = p.addEventListener; - target.on = p.on; - target.removeEventListener = target.off = p.removeEventListener; - target.removeAllEventListeners = p.removeAllEventListeners; - target.hasEventListener = p.hasEventListener; - target.dispatchEvent = p.dispatchEvent; - target._dispatchEvent = p._dispatchEvent; - target.willTrigger = p.willTrigger; - }; - - -// public methods: - /** - * Adds the specified event listener. Note that adding multiple listeners to the same function will result in - * multiple callbacks getting fired. - * - *

    Example

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

    Example

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

    Example

    - * - * displayObject.removeEventListener("click", handleClick); - * - * @method removeEventListener - * @param {String} type The string type of the event. - * @param {Function | Object} listener The listener function or object. - * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. - **/ - p.removeEventListener = function(type, listener, useCapture) { - var listeners = useCapture ? this._captureListeners : this._listeners; - if (!listeners) { return; } - var arr = listeners[type]; - if (!arr) { return; } - for (var i=0,l=arr.length; iIMPORTANT: To remove a listener added with `on`, you must pass in the returned wrapper function as the listener. See - * {{#crossLink "EventDispatcher/on"}}{{/crossLink}} for an example. - * - * @method off - * @param {String} type The string type of the event. - * @param {Function | Object} listener The listener function or object. - * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. - **/ - p.off = p.removeEventListener; - - /** - * Removes all listeners for the specified type, or all listeners of all types. - * - *

    Example

    - * - * // Remove all listeners - * displayObject.removeAllEventListeners(); - * - * // Remove all click listeners - * displayObject.removeAllEventListeners("click"); - * - * @method removeAllEventListeners - * @param {String} [type] The string type of the event. If omitted, all listeners for all types will be removed. - **/ - p.removeAllEventListeners = function(type) { - if (!type) { this._listeners = this._captureListeners = null; } - else { - if (this._listeners) { delete(this._listeners[type]); } - if (this._captureListeners) { delete(this._captureListeners[type]); } - } - }; - - /** - * Dispatches the specified event to all listeners. - * - *

    Example

    - * - * // Use a string event - * this.dispatchEvent("complete"); - * - * // Use an Event instance - * var event = new createjs.Event("progress"); - * this.dispatchEvent(event); - * - * @method dispatchEvent - * @param {Object | String | Event} eventObj An object with a "type" property, or a string type. - * While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used, - * dispatchEvent will construct an Event instance if necessary with the specified type. This latter approach can - * be used to avoid event object instantiation for non-bubbling events that may not have any listeners. - * @param {Boolean} [bubbles] Specifies the `bubbles` value when a string was passed to eventObj. - * @param {Boolean} [cancelable] Specifies the `cancelable` value when a string was passed to eventObj. - * @return {Boolean} Returns false if `preventDefault()` was called on a cancelable event, true otherwise. - **/ - p.dispatchEvent = function(eventObj, bubbles, cancelable) { - if (typeof eventObj == "string") { - // skip everything if there's no listeners and it doesn't bubble: - var listeners = this._listeners; - if (!bubbles && (!listeners || !listeners[eventObj])) { return true; } - eventObj = new createjs.Event(eventObj, bubbles, cancelable); - } else if (eventObj.target && eventObj.clone) { - // redispatching an active event object, so clone it: - eventObj = eventObj.clone(); - } - - // TODO: it would be nice to eliminate this. Maybe in favour of evtObj instanceof Event? Or !!evtObj.createEvent - try { eventObj.target = this; } catch (e) {} // try/catch allows redispatching of native events - - if (!eventObj.bubbles || !this.parent) { - this._dispatchEvent(eventObj, 2); - } else { - var top=this, list=[top]; - while (top.parent) { list.push(top = top.parent); } - var i, l=list.length; - - // capture & atTarget - for (i=l-1; i>=0 && !eventObj.propagationStopped; i--) { - list[i]._dispatchEvent(eventObj, 1+(i==0)); - } - // bubbling - for (i=1; i - *
  • capture phase: starting from the top parent to the target
  • - *
  • at target phase: currently being dispatched from the target
  • - *
  • bubbling phase: from the target to the top parent
  • - * - * @property eventPhase - * @type Number - * @default 0 - * @readonly - */ - this.eventPhase = 0; - - /** - * Indicates whether the event will bubble through the display list. - * @property bubbles - * @type Boolean - * @default false - * @readonly - */ - this.bubbles = !!bubbles; - - /** - * Indicates whether the default behaviour of this event can be cancelled via - * {{#crossLink "Event/preventDefault"}}{{/crossLink}}. This is set via the Event constructor. - * @property cancelable - * @type Boolean - * @default false - * @readonly - */ - this.cancelable = !!cancelable; - - /** - * The epoch time at which this event was created. - * @property timeStamp - * @type Number - * @default 0 - * @readonly - */ - this.timeStamp = (new Date()).getTime(); - - /** - * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called - * on this event. - * @property defaultPrevented - * @type Boolean - * @default false - * @readonly - */ - this.defaultPrevented = false; - - /** - * Indicates if {{#crossLink "Event/stopPropagation"}}{{/crossLink}} or - * {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called on this event. - * @property propagationStopped - * @type Boolean - * @default false - * @readonly - */ - this.propagationStopped = false; - - /** - * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called - * on this event. - * @property immediatePropagationStopped - * @type Boolean - * @default false - * @readonly - */ - this.immediatePropagationStopped = false; - - /** - * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event. - * @property removed - * @type Boolean - * @default false - * @readonly - */ - this.removed = false; - } - var p = Event.prototype; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - -// public methods: - /** - * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true 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"); - -}()); - -//############################################################################## -// ProgressEvent.js -//############################################################################## - -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)); - -//############################################################################## -// 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 "AbstractLoader/GET:property"}}{{/crossLink}} or - * {{#crossLink "AbstractLoader/POST:property"}}{{/crossLink}} request types are supported, and are defined as - * constants on {{#crossLink "AbstractLoader"}}{{/crossLink}}. - * @property method - * @type {String} - * @default get - */ - this.method = createjs.LoadItem.GET; - - /** - * An object hash of name/value pairs to send to the server. - * @property values - * @type {Object} - * @default null - */ - this.values = null; - - /** - * An object hash of headers to attach to an XHR request. PreloadJS will automatically attach some default - * headers when required, including "Origin", "Content-Type", and "X-Requested-With". You may override the - * default headers by including them in your headers object. - * @property headers - * @type {Object} - * @default null - */ - this.headers = null; - - /** - * Enable credentials for XHR requests. - * @property withCredentials - * @type {Boolean} - * @default false - */ - this.withCredentials = false; - - /** - * Set the mime type of XHR-based requests. This is automatically set to "text/plain; charset=utf-8" for text - * based files (json, xml, text, css, js). - * @property mimeType - * @type {String} - * @default null - */ - this.mimeType = null; - - /** - * Sets the crossOrigin attribute for CORS-enabled images loading cross-domain. - * @property crossOrigin - * @type {boolean} - * @default Anonymous - */ - this.crossOrigin = null; - - /** - * The duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR - * (level one) loading, as XHR (level 2) provides its own timeout event. - * @property loadTimeout - * @type {Number} - * @default 8000 (8 seconds) - */ - this.loadTimeout = s.LOAD_TIMEOUT_DEFAULT; - }; - - var p = LoadItem.prototype = {}; - var s = LoadItem; - - /** - * Default duration in milliseconds to wait before a request times out. This only applies to tag-based and and XHR - * (level one) loading, as XHR (level 2) provides its own timeout event. - * @property LOAD_TIMEOUT_DEFAULT - * @type {number} - * @static - */ - s.LOAD_TIMEOUT_DEFAULT = 8000; - - /** - * Create a LoadItem. - *
      - *
    • String-based items are converted to a LoadItem with a populated {{#crossLink "src:property"}}{{/crossLink}}.
    • - *
    • LoadItem instances are returned as-is
    • - *
    • Objects are returned with any needed properties added
    • - *
    - * @method create - * @param {LoadItem|String|Object} value The load item value - * @returns {LoadItem|Object} - * @static - */ - s.create = function (value) { - if (typeof value == "string") { - var item = new LoadItem(); - item.src = value; - return item; - } else if (value instanceof s) { - return value; - } else if (value instanceof Object && value.src) { - if (value.loadTimeout == null) { - value.loadTimeout = s.LOAD_TIMEOUT_DEFAULT; - } - return value; - } else { - throw new Error("Type not recognized."); - } - }; - - /** - * Provides a chainable shortcut method for setting a number of properties on the instance. - * - *

    Example

    - * - * var loadItem = new createjs.LoadItem().set({src:"image.png", maintainOrder:true}); - * - * @method set - * @param {Object} props A generic object containing properties to copy to the LoadItem instance. - * @return {LoadItem} Returns the instance the method is called on (useful for chaining calls.) - */ - p.set = function(props) { - for (var n in props) { this[n] = props[n]; } - return this; - }; - - createjs.LoadItem = s; - -}()); - -//############################################################################## -// RequestUtils.js -//############################################################################## - -(function () { - - /** - * Utilities that assist with parsing load items, and determining file types, etc. - * @class RequestUtils - */ - var s = {}; - - /** - * The Regular Expression used to test file URLS for an absolute path. - * @property ABSOLUTE_PATH - * @type {RegExp} - * @static - */ - s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i; - - /** - * The Regular Expression used to test file URLS for a relative path. - * @property RELATIVE_PATH - * @type {RegExp} - * @static - */ - s.RELATIVE_PATT = (/^[./]*?\//i); - - /** - * The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string - * removed. - * @property EXTENSION_PATT - * @type {RegExp} - * @static - */ - s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i; - - /** - * Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know: - *
      - *
    • If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or - * `//networkPath`)
    • - *
    • If the path is relative. Relative paths start with `../` or `/path` (or similar)
    • - *
    • The file extension. This is determined by the filename with an extension. Query strings are dropped, and - * the file path is expected to follow the format `name.ext`.
    • - *
    - * @method parseURI - * @param {String} path - * @returns {Object} An Object with an `absolute` and `relative` Boolean values, as well as an optional 'extension` - * property, which is the lowercase extension. - * @static - */ - s.parseURI = function (path) { - var info = {absolute: false, relative: false}; - if (path == null) { return info; } - - // Drop the query string - var queryIndex = path.indexOf("?"); - if (queryIndex > -1) { - path = path.substr(0, queryIndex); - } - - // Absolute - var match; - if (s.ABSOLUTE_PATT.test(path)) { - info.absolute = true; - - // Relative - } else if (s.RELATIVE_PATT.test(path)) { - info.relative = true; - } - - // Extension - if (match = path.match(s.EXTENSION_PATT)) { - info.extension = match[1].toLowerCase(); - } - return info; - }; - - /** - * Formats an object into a query string for either a POST or GET request. - * @method formatQueryString - * @param {Object} data The data to convert to a query string. - * @param {Array} [query] Existing name/value pairs to append on to this query. - * @static - */ - s.formatQueryString = function (data, query) { - if (data == null) { - throw new Error('You must specify data.'); - } - var params = []; - for (var n in data) { - params.push(n + '=' + escape(data[n])); - } - if (query) { - params = params.concat(query); - } - return params.join('&'); - }; - - /** - * A utility method that builds a file path using a source and a data object, and formats it into a new path. - * @method buildPath - * @param {String} src The source path to add values to. - * @param {Object} [data] Object used to append values to this request as a query string. Existing parameters on the - * path will be preserved. - * @returns {string} A formatted string that contains the path and the supplied parameters. - * @static - */ - s.buildPath = function (src, data) { - if (data == null) { - return src; - } - - var query = []; - var idx = src.indexOf('?'); - - if (idx != -1) { - var q = src.slice(idx + 1); - query = query.concat(q.split('&')); - } - - if (idx != -1) { - return src.slice(0, idx) + '?' + this.formatQueryString(data, query); - } else { - return src + '?' + this.formatQueryString(data, query); - } - }; - - /** - * @method isCrossDomain - * @param {LoadItem|Object} item A load item with a `src` property. - * @return {Boolean} If the load item is loading from a different domain than the current location. - * @static - */ - s.isCrossDomain = function (item) { - var target = document.createElement("a"); - target.href = item.src; - - var host = document.createElement("a"); - host.href = location.href; - - var crossdomain = (target.hostname != "") && - (target.port != host.port || - target.protocol != host.protocol || - target.hostname != host.hostname); - return crossdomain; - }; - - /** - * @method isLocal - * @param {LoadItem|Object} item A load item with a `src` property - * @return {Boolean} If the load item is loading from the "file:" protocol. Assume that the host must be local as - * well. - * @static - */ - s.isLocal = function (item) { - var target = document.createElement("a"); - target.href = item.src; - return target.hostname == "" && target.protocol == "file:"; - }; - - /** - * Determine if a specific type should be loaded as a binary file. Currently, only images and items marked - * specifically as "binary" are loaded as binary. Note that audio is not a binary type, as we can not play - * back using an audio tag if it is loaded as binary. Plugins can change the item type to binary to ensure they get - * a binary result to work with. Binary files are loaded using XHR2. Types are defined as static constants on - * {{#crossLink "AbstractLoader"}}{{/crossLink}}. - * @method isBinary - * @param {String} type The item type. - * @return {Boolean} If the specified type is binary. - * @static - */ - s.isBinary = function (type) { - switch (type) { - case createjs.AbstractLoader.IMAGE: - case createjs.AbstractLoader.BINARY: - return true; - default: - return false; - } - }; - - /** - * Check if item is a valid HTMLImageElement - * @method isImageTag - * @param {Object} item - * @returns {Boolean} - * @static - */ - s.isImageTag = function(item) { - return item instanceof HTMLImageElement; - }; - - /** - * Check if item is a valid HTMLAudioElement - * @method isAudioTag - * @param {Object} item - * @returns {Boolean} - * @static - */ - s.isAudioTag = function(item) { - if (window.HTMLAudioElement) { - return item instanceof HTMLAudioElement; - } else { - return false; - } - }; - - /** - * Check if item is a valid HTMLVideoElement - * @method isVideoTag - * @param {Object} item - * @returns {Boolean} - * @static - */ - s.isVideoTag = function(item) { - if (window.HTMLVideoElement) { - return item instanceof HTMLVideoElement; - } else { - return false; - } - }; - - /** - * Determine if a specific type is a text-based asset, and should be loaded as UTF-8. - * @method isText - * @param {String} type The item type. - * @return {Boolean} If the specified type is text. - * @static - */ - s.isText = function (type) { - switch (type) { - case createjs.AbstractLoader.TEXT: - case createjs.AbstractLoader.JSON: - case createjs.AbstractLoader.MANIFEST: - case createjs.AbstractLoader.XML: - case createjs.AbstractLoader.CSS: - case createjs.AbstractLoader.SVG: - case createjs.AbstractLoader.JAVASCRIPT: - case createjs.AbstractLoader.SPRITESHEET: - return true; - default: - return false; - } - }; - - /** - * Determine the type of the object using common extensions. Note that the type can be passed in with the load item - * if it is an unusual extension. - * @method getTypeByExtension - * @param {String} extension The file extension to use to determine the load type. - * @return {String} The determined load type (for example, AbstractLoader.IMAGE). Will return `null` if - * the type can not be determined by the extension. - * @static - */ - s.getTypeByExtension = function (extension) { - if (extension == null) { - return createjs.AbstractLoader.TEXT; - } - - switch (extension.toLowerCase()) { - case "jpeg": - case "jpg": - case "gif": - case "png": - case "webp": - case "bmp": - return createjs.AbstractLoader.IMAGE; - case "ogg": - case "mp3": - case "webm": - return createjs.AbstractLoader.SOUND; - case "mp4": - case "webm": - case "ts": - return createjs.AbstractLoader.VIDEO; - case "json": - return createjs.AbstractLoader.JSON; - case "xml": - return createjs.AbstractLoader.XML; - case "css": - return createjs.AbstractLoader.CSS; - case "js": - return createjs.AbstractLoader.JAVASCRIPT; - case 'svg': - return createjs.AbstractLoader.SVG; - default: - return createjs.AbstractLoader.TEXT; - } - }; - - createjs.RequestUtils = s; - -}()); - -//############################################################################## -// 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; - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - - /** - * Defines a POST request, use for a method value when loading data. - * @property POST - * @type {string} - * @default post - * @static - */ - s.POST = "POST"; - - /** - * Defines a GET request, use for a method value when loading data. - * @property GET - * @type {string} - * @default get - * @static - */ - s.GET = "GET"; - - /** - * The preload type for generic binary types. Note that images are loaded as binary files when using XHR. - * @property BINARY - * @type {String} - * @default binary - * @static - * @since 0.6.0 - */ - s.BINARY = "binary"; - - /** - * The preload type for css files. CSS files are loaded using a <link> when loaded with XHR, or a - * <style> tag when loaded with tags. - * @property CSS - * @type {String} - * @default css - * @static - * @since 0.6.0 - */ - s.CSS = "css"; - - /** - * The preload type for image files, usually png, gif, or jpg/jpeg. Images are loaded into an <image> tag. - * @property IMAGE - * @type {String} - * @default image - * @static - * @since 0.6.0 - */ - s.IMAGE = "image"; - - /** - * The preload type for javascript files, usually with the "js" file extension. JavaScript files are loaded into a - * <script> tag. - * - * Since version 0.4.1+, due to how tag-loaded scripts work, all JavaScript files are automatically injected into - * the body of the document to maintain parity between XHR and tag-loaded scripts. In version 0.4.0 and earlier, - * only tag-loaded scripts are injected. - * @property JAVASCRIPT - * @type {String} - * @default javascript - * @static - * @since 0.6.0 - */ - s.JAVASCRIPT = "javascript"; - - /** - * The preload type for json files, usually with the "json" file extension. JSON data is loaded and parsed into a - * JavaScript object. Note that if a `callback` is present on the load item, the file will be loaded with JSONP, - * no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to, and the JSON - * must contain a matching wrapper function. - * @property JSON - * @type {String} - * @default json - * @static - * @since 0.6.0 - */ - s.JSON = "json"; - - /** - * The preload type for jsonp files, usually with the "json" file extension. JSON data is loaded and parsed into a - * JavaScript object. You are required to pass a callback parameter that matches the function wrapper in the JSON. - * Note that JSONP will always be used if there is a callback present, no matter what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} - * property is set to. - * @property JSONP - * @type {String} - * @default jsonp - * @static - * @since 0.6.0 - */ - s.JSONP = "jsonp"; - - /** - * The preload type for json-based manifest files, usually with the "json" file extension. The JSON data is loaded - * and parsed into a JavaScript object. PreloadJS will then look for a "manifest" property in the JSON, which is an - * Array of files to load, following the same format as the {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} - * method. If a "callback" is specified on the manifest object, then it will be loaded using JSONP instead, - * regardless of what the {{#crossLink "LoadQueue/preferXHR:property"}}{{/crossLink}} property is set to. - * @property MANIFEST - * @type {String} - * @default manifest - * @static - * @since 0.6.0 - */ - s.MANIFEST = "manifest"; - - /** - * The preload type for sound files, usually mp3, ogg, or wav. When loading via tags, audio is loaded into an - * <audio> tag. - * @property SOUND - * @type {String} - * @default sound - * @static - * @since 0.6.0 - */ - s.SOUND = "sound"; - - /** - * The preload type for video files, usually mp4, ts, or ogg. When loading via tags, video is loaded into an - * <video> tag. - * @property VIDEO - * @type {String} - * @default video - * @static - * @since 0.6.0 - */ - s.VIDEO = "video"; - - /** - * The preload type for SpriteSheet files. SpriteSheet files are JSON files that contain string image paths. - * @property SPRITESHEET - * @type {String} - * @default spritesheet - * @static - * @since 0.6.0 - */ - s.SPRITESHEET = "spritesheet"; - - /** - * The preload type for SVG files. - * @property SVG - * @type {String} - * @default svg - * @static - * @since 0.6.0 - */ - s.SVG = "svg"; - - /** - * The preload type for text files, which is also the default file type if the type can not be determined. Text is - * loaded as raw text. - * @property TEXT - * @type {String} - * @default text - * @static - * @since 0.6.0 - */ - s.TEXT = "text"; - - /** - * The preload type for xml files. XML is loaded into an XML document. - * @property XML - * @type {String} - * @default xml - * @static - * @since 0.6.0 - */ - s.XML = "xml"; - -// Events - /** - * The {{#crossLink "ProgressEvent"}}{{/crossLink}} that is fired when the overall progress changes. Prior to - * version 0.6.0, this was just a regular {{#crossLink "Event"}}{{/crossLink}}. - * @event progress - * @since 0.3.0 - */ - - /** - * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a load starts. - * @event loadstart - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.3.1 - */ - - /** - * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the entire queue has been loaded. - * @event complete - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.3.0 - */ - - /** - * The {{#crossLink "ErrorEvent"}}{{/crossLink}} that is fired when the loader encounters an error. If the error was - * encountered by a file, the event will contain the item that caused the error. Prior to version 0.6.0, this was - * just a regular {{#crossLink "Event"}}{{/crossLink}}. - * @event error - * @since 0.3.0 - */ - - /** - * The {{#crossLink "Event"}}{{/crossLink}} that is fired when the loader encounters an internal file load error. - * This enables loaders to maintain internal queues, and surface file load errors. - * @event fileerror - * @param {Object} target The object that dispatched the event. - * @param {String} type The even type ("fileerror") - * @param {LoadItem|object} The item that encountered the error - * @since 0.6.0 - */ - - /** - * The {{#crossLink "Event"}}{{/crossLink}} that is fired when a loader internally loads a file. This enables - * loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} to maintain internal {{#crossLink "LoadQueue"}}{{/crossLink}}s - * and notify when they have loaded a file. The {{#crossLink "LoadQueue"}}{{/crossLink}} class dispatches a - * slightly different {{#crossLink "LoadQueue/fileload:event"}}{{/crossLink}} event. - * @event fileload - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type ("fileload") - * @param {Object} item The file item which was specified in the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * or {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}} call. If only a string path or tag was specified, the - * object will contain that value as a `src` property. - * @param {Object} result The HTML tag or parsed result of the loaded item. - * @param {Object} rawResult The unprocessed result, usually the raw text or binary data before it is converted - * to a usable object. - * @since 0.6.0 - */ - - /** - * The {{#crossLink "Event"}}{{/crossLink}} that is fired after the internal request is created, but before a load. - * This allows updates to the loader for specific loading needs, such as binary or XHR image loading. - * @event initialize - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type ("initialize") - * @param {AbstractLoader} loader The loader that has been initialized. - */ - - - /** - * Get a reference to the manifest item that is loaded by this loader. In some cases this will be the value that was - * passed into {{#crossLink "LoadQueue"}}{{/crossLink}} using {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} or - * {{#crossLink "LoadQueue/loadManifest"}}{{/crossLink}}. However if only a String path was passed in, then it will - * be a {{#crossLink "LoadItem"}}{{/crossLink}}. - * @method getItem - * @return {Object} The manifest item that this loader is responsible for loading. - * @since 0.6.0 - */ - p.getItem = function () { - return this._item; - }; - - /** - * Get a reference to the content that was loaded by the loader (only available after the {{#crossLink "complete:event"}}{{/crossLink}} - * event is dispatched. - * @method getResult - * @param {Boolean} [raw=false] Determines if the returned result will be the formatted content, or the raw loaded - * data (if it exists). - * @return {Object} - * @since 0.6.0 - */ - p.getResult = function (raw) { - return raw ? this._rawResult : this._result; - }; - - /** - * Return the `tag` this object creates or uses for loading. - * @method getTag - * @return {Object} The tag instance - * @since 0.6.0 - */ - p.getTag = function () { - return this._tag; - }; - - /** - * Set the `tag` this item uses for loading. - * @method setTag - * @param {Object} tag The tag instance - * @since 0.6.0 - */ - p.setTag = function(tag) { - this._tag = tag; - }; - - /** - * Begin loading the item. This method is required when using a loader by itself. - * - *

    Example

    - * - * var queue = new createjs.LoadQueue(); - * queue.on("complete", handleComplete); - * queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet - * queue.load(); - * - * @method load - */ - p.load = function () { - this._createRequest(); - - this._request.on("complete", this, this); - this._request.on("progress", this, this); - this._request.on("loadStart", this, this); - this._request.on("abort", this, this); - this._request.on("timeout", this, this); - this._request.on("error", this, this); - - var evt = new createjs.Event("initialize"); - evt.loader = this._request; - this.dispatchEvent(evt); - - this._request.load(); - }; - - /** - * Close the the item. This will stop any open requests (although downloads using HTML tags may still continue in - * the background), but events will not longer be dispatched. - * @method cancel - */ - p.cancel = function () { - this.canceled = true; - this.destroy(); - }; - - /** - * Clean up the loader. - * @method destroy - */ - p.destroy = function() { - if (this._request) { - this._request.removeAllEventListeners(); - this._request.destroy(); - } - - this._request = null; - - this._item = null; - this._rawResult = null; - this._result = null; - - this._loadItems = null; - - this.removeAllEventListeners(); - }; - - /** - * Get any items loaded internally by the loader. The enables loaders such as {{#crossLink "ManifestLoader"}}{{/crossLink}} - * to expose items it loads internally. - * @method getLoadedItems - * @return {Array} A list of the items loaded by the loader. - * @since 0.6.0 - */ - p.getLoadedItems = function () { - return this._loadedItems; - }; - - - // Private methods - /** - * Create an internal request used for loading. By default, an {{#crossLink "XHRRequest"}}{{/crossLink}} or - * {{#crossLink "TagRequest"}}{{/crossLink}} is created, depending on the value of {{#crossLink "preferXHR:property"}}{{/crossLink}}. - * Other loaders may override this to use different request types, such as {{#crossLink "ManifestLoader"}}{{/crossLink}}, - * which uses {{#crossLink "JSONLoader"}}{{/crossLink}} or {{#crossLink "JSONPLoader"}}{{/crossLink}} under the hood. - * @method _createRequest - * @protected - */ - p._createRequest = function() { - if (!this._preferXHR) { - this._request = new createjs.TagRequest(this._item, this._tag || this._createTag(), this._tagSrcAttribute); - } else { - this._request = new createjs.XHRRequest(this._item); - } - }; - - /** - * Create the HTML tag used for loading. This method does nothing by default, and needs to be implemented - * by loaders that require tag loading. - * @method _createTag - * @param {String} src The tag source - * @return {HTMLElement} The tag that was created - * @protected - */ - p._createTag = function(src) { return null; }; - - /** - * Dispatch a loadstart {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/loadstart:event"}}{{/crossLink}} - * event for details on the event payload. - * @method _sendLoadStart - * @protected - */ - p._sendLoadStart = function () { - if (this._isCanceled()) { return; } - this.dispatchEvent("loadstart"); - }; - - /** - * Dispatch a {{#crossLink "ProgressEvent"}}{{/crossLink}}. - * @method _sendProgress - * @param {Number | Object} value The progress of the loaded item, or an object containing loaded - * and total properties. - * @protected - */ - p._sendProgress = function (value) { - if (this._isCanceled()) { return; } - var event = null; - if (typeof(value) == "number") { - this.progress = value; - event = new createjs.ProgressEvent(this.progress); - } else { - event = value; - this.progress = value.loaded / value.total; - event.progress = this.progress; - if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; } - } - this.hasEventListener("progress") && this.dispatchEvent(event); - }; - - /** - * Dispatch a complete {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}} event - * @method _sendComplete - * @protected - */ - p._sendComplete = function () { - if (this._isCanceled()) { return; } - - this.loaded = true; - - var event = new createjs.Event("complete"); - event.rawResult = this._rawResult; - - if (this._result != null) { - event.result = this._result; - } - - this.dispatchEvent(event); - }; - - /** - * Dispatch an error {{#crossLink "Event"}}{{/crossLink}}. Please see the {{#crossLink "AbstractLoader/error:event"}}{{/crossLink}} - * event for details on the event payload. - * @method _sendError - * @param {ErrorEvent} event The event object containing specific error properties. - * @protected - */ - p._sendError = function (event) { - if (this._isCanceled() || !this.hasEventListener("error")) { return; } - if (event == null) { - event = new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY"); // TODO: Populate error - } - this.dispatchEvent(event); - }; - - /** - * Determine if the load has been canceled. This is important to ensure that method calls or asynchronous events - * do not cause issues after the queue has been cleaned up. - * @method _isCanceled - * @return {Boolean} If the loader has been canceled. - * @protected - */ - p._isCanceled = function () { - if (window.createjs == null || this.canceled) { - return true; - } - return false; - }; - - /** - * A custom result formatter function, which is called just before a request dispatches its complete event. Most - * loader types already have an internal formatter, but this can be user-overridden for custom formatting. The - * formatted result will be available on Loaders using {{#crossLink "getResult"}}{{/crossLink}}, and passing `true`. - * @property resultFormatter - * @type Function - * @return {Object} The formatted result - * @since 0.6.0 - */ - p.resultFormatter = null; - - /** - * Handle events from internal requests. By default, loaders will handle, and redispatch the necessary events, but - * this method can be overridden for custom behaviours. - * @method handleEvent - * @param {Event} event The event that the internal request dispatches. - * @protected - * @since 0.6.0 - */ - p.handleEvent = function (event) { - switch (event.type) { - case "complete": - this._rawResult = event.target._response; - var result = this.resultFormatter && this.resultFormatter(this); - if (result instanceof Function) { - result.call(this, - createjs.proxy(this._resultFormatSuccess, this), - createjs.proxy(this._resultFormatFailed, this) - ); - } else { - this._result = result || this._rawResult; - this._sendComplete(); - } - break; - case "progress": - this._sendProgress(event); - break; - case "error": - this._sendError(event); - break; - case "loadstart": - this._sendLoadStart(); - break; - case "abort": - case "timeout": - if (!this._isCanceled()) { - this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_" + event.type.toUpperCase() + "_ERROR")); - } - break; - } - }; - - /** - * The "success" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous - * functions. - * @method _resultFormatSuccess - * @param {Object} result The formatted result - * @private - */ - p._resultFormatSuccess = function (result) { - this._result = result; - this._sendComplete(); - }; - - /** - * The "error" callback passed to {{#crossLink "AbstractLoader/resultFormatter"}}{{/crossLink}} asynchronous - * functions. - * @method _resultFormatSuccess - * @param {Object} error The error event - * @private - */ - p._resultFormatFailed = function (event) { - this._sendError(event); - }; - - /** - * @method buildPath - * @protected - * @deprecated Use the {{#crossLink "RequestUtils"}}{{/crossLink}} method {{#crossLink "RequestUtils/buildPath"}}{{/crossLink}} - * instead. - */ - p.buildPath = function (src, data) { - return createjs.RequestUtils.buildPath(src, data); - }; - - /** - * @method toString - * @return {String} a string representation of the instance. - */ - p.toString = function () { - return "[PreloadJS AbstractLoader]"; - }; - - createjs.AbstractLoader = createjs.promote(AbstractLoader, "EventDispatcher"); - -}()); - -//############################################################################## -// 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; - - /** - * Determines what the tags initial style.visibility was, so we can set it correctly after a load. - * - * @type {null} - * @private - */ - this._startTagVisibility = null; - }; - - var p = createjs.extend(TagRequest, createjs.AbstractRequest); - - // public methods - p.load = function () { - this._tag.onload = createjs.proxy(this._handleTagComplete, this); - this._tag.onreadystatechange = createjs.proxy(this._handleReadyStateChange, this); - this._tag.onerror = createjs.proxy(this._handleError, this); - - var evt = new createjs.Event("initialize"); - evt.loader = this._tag; - - this.dispatchEvent(evt); - - this._hideTag(); - - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); - - this._tag[this._tagSrcAttribute] = this._item.src; - - // wdg:: Append the tag AFTER setting the src, or SVG loading on iOS will fail. - if (this._tag.parentNode == null) { - window.document.body.appendChild(this._tag); - this._addedToDOM = true; - } - }; - - p.destroy = function() { - this._clean(); - this._tag = null; - - this.AbstractRequest_destroy(); - }; - - // private methods - /** - * Handle the readyStateChange event from a tag. We need this in place of the `onload` callback (mainly SCRIPT - * and LINK tags), but other cases may exist. - * @method _handleReadyStateChange - * @private - */ - p._handleReadyStateChange = function () { - clearTimeout(this._loadTimeout); - // This is strictly for tags in browsers that do not support onload. - var tag = this._tag; - - // Complete is for old IE support. - if (tag.readyState == "loaded" || tag.readyState == "complete") { - this._handleTagComplete(); - } - }; - - /** - * Handle any error events from the tag. - * @method _handleError - * @protected - */ - p._handleError = function() { - this._clean(); - this.dispatchEvent("error"); - }; - - /** - * Handle the tag's onload callback. - * @method _handleTagComplete - * @private - */ - p._handleTagComplete = function () { - this._rawResult = this._tag; - this._result = this.resultFormatter && this.resultFormatter(this) || this._rawResult; - - this._clean(); - this._showTag(); - - this.dispatchEvent("complete"); - }; - - /** - * The tag request has not loaded within the time specified in loadTimeout. - * @method _handleError - * @param {Object} event The XHR error event. - * @private - */ - p._handleTimeout = function () { - this._clean(); - this.dispatchEvent(new createjs.Event("timeout")); - }; - - /** - * Remove event listeners, but don't destroy the request object - * @method _clean - * @private - */ - p._clean = function() { - this._tag.onload = null; - this._tag.onreadystatechange = null; - this._tag.onerror = null; - if (this._addedToDOM && this._tag.parentNode != null) { - this._tag.parentNode.removeChild(this._tag); - } - clearTimeout(this._loadTimeout); - }; - - p._hideTag = function() { - this._startTagVisibility = this._tag.style.visibility; - this._tag.style.visibility = "hidden"; - }; - - p._showTag = function() { - this._tag.style.visibility = this._startTagVisibility; - }; - - /** - * Handle a stalled audio event. The main place this happens is with HTMLAudio in Chrome when playing back audio - * that is already in a load, but not complete. - * @method _handleStalled - * @private - */ - p._handleStalled = function () { - //Ignore, let the timeout take care of it. Sometimes its not really stopped. - }; - - createjs.TagRequest = createjs.promote(TagRequest, "AbstractRequest"); - -}()); - -//############################################################################## -// MediaTagRequest.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - // constructor - /** - * An {{#crossLink "TagRequest"}}{{/crossLink}} that loads HTML tags for video and audio. - * @class MediaTagRequest - * @param {LoadItem} loadItem - * @param {HTMLAudioElement|HTMLVideoElement} tag - * @param {String} srcAttribute The tag attribute that specifies the source, such as "src", "href", etc. - * @constructor - */ - function MediaTagRequest(loadItem, tag, srcAttribute) { - this.AbstractRequest_constructor(loadItem); - - // protected properties - this._tag = tag; - this._tagSrcAttribute = srcAttribute; - this._loadedHandler = createjs.proxy(this._handleTagComplete, this); - }; - - var p = createjs.extend(MediaTagRequest, createjs.TagRequest); - var s = MediaTagRequest; - - // public methods - p.load = function () { - var sc = createjs.proxy(this._handleStalled, this); - this._stalledCallback = sc; - - var pc = createjs.proxy(this._handleProgress, this); - this._handleProgress = pc; - - this._tag.addEventListener("stalled", sc); - this._tag.addEventListener("progress", pc); - - // This will tell us when audio is buffered enough to play through, but not when its loaded. - // The tag doesn't keep loading in Chrome once enough has buffered, and we have decided that behaviour is sufficient. - this._tag.addEventListener && this._tag.addEventListener("canplaythrough", this._loadedHandler, false); // canplaythrough callback doesn't work in Chrome, so we use an event. - - this.TagRequest_load(); - }; - - // private methods - p._handleReadyStateChange = function () { - clearTimeout(this._loadTimeout); - // This is strictly for tags in browsers that do not support onload. - var tag = this._tag; - - // Complete is for old IE support. - if (tag.readyState == "loaded" || tag.readyState == "complete") { - this._handleTagComplete(); - } - }; - - p._handleStalled = function () { - //Ignore, let the timeout take care of it. Sometimes its not really stopped. - }; - - /** - * An XHR request has reported progress. - * @method _handleProgress - * @param {Object} event The XHR progress event. - * @private - */ - p._handleProgress = function (event) { - if (!event || event.loaded > 0 && event.total == 0) { - return; // Sometimes we get no "total", so just ignore the progress event. - } - - var newEvent = new createjs.ProgressEvent(event.loaded, event.total); - this.dispatchEvent(newEvent); - }; - - // protected methods - p._clean = function () { - this._tag.removeEventListener && this._tag.removeEventListener("canplaythrough", this._loadedHandler); - this._tag.removeEventListener("stalled", this._stalledCallback); - this._tag.removeEventListener("progress", this._progressCallback); - - this.TagRequest__clean(); - }; - - createjs.MediaTagRequest = createjs.promote(MediaTagRequest, "TagRequest"); - -}()); - -//############################################################################## -// XHRRequest.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - -// constructor - /** - * A preloader that loads items using XHR requests, usually XMLHttpRequest. However XDomainRequests will be used - * for cross-domain requests if possible, and older versions of IE fall back on to ActiveX objects when necessary. - * XHR requests load the content as text or binary data, provide progress and consistent completion events, and - * can be canceled during load. Note that XHR is not supported in IE 6 or earlier, and is not recommended for - * cross-domain loading. - * @class XHRRequest - * @constructor - * @param {Object} item The object that defines the file to load. Please see the {{#crossLink "LoadQueue/loadFile"}}{{/crossLink}} - * for an overview of supported file properties. - * @extends AbstractLoader - */ - function XHRRequest (item) { - this.AbstractRequest_constructor(item); - - // protected properties - /** - * A reference to the XHR request used to load the content. - * @property _request - * @type {XMLHttpRequest | XDomainRequest | ActiveX.XMLHTTP} - * @private - */ - this._request = null; - - /** - * A manual load timeout that is used for browsers that do not support the onTimeout event on XHR (XHR level 1, - * typically IE9). - * @property _loadTimeout - * @type {Number} - * @private - */ - this._loadTimeout = null; - - /** - * The browser's XHR (XMLHTTPRequest) version. Supported versions are 1 and 2. There is no official way to detect - * the version, so we use capabilities to make a best guess. - * @property _xhrLevel - * @type {Number} - * @default 1 - * @private - */ - this._xhrLevel = 1; - - /** - * The response of a loaded file. This is set because it is expensive to look up constantly. This property will be - * null until the file is loaded. - * @property _response - * @type {mixed} - * @private - */ - this._response = null; - - /** - * The response of the loaded file before it is modified. In most cases, content is converted from raw text to - * an HTML tag or a formatted object which is set to the result property, but the developer may still - * want to access the raw content as it was loaded. - * @property _rawResponse - * @type {String|Object} - * @private - */ - this._rawResponse = null; - - this._canceled = false; - - // Setup our event handlers now. - this._handleLoadStartProxy = createjs.proxy(this._handleLoadStart, this); - this._handleProgressProxy = createjs.proxy(this._handleProgress, this); - this._handleAbortProxy = createjs.proxy(this._handleAbort, this); - this._handleErrorProxy = createjs.proxy(this._handleError, this); - this._handleTimeoutProxy = createjs.proxy(this._handleTimeout, this); - this._handleLoadProxy = createjs.proxy(this._handleLoad, this); - this._handleReadyStateChangeProxy = createjs.proxy(this._handleReadyStateChange, this); - - if (!this._createXHR(item)) { - //TODO: Throw error? - } - }; - - var p = createjs.extend(XHRRequest, createjs.AbstractRequest); - -// static properties - /** - * A list of XMLHTTP object IDs to try when building an ActiveX object for XHR requests in earlier versions of IE. - * @property ACTIVEX_VERSIONS - * @type {Array} - * @since 0.4.2 - * @private - */ - XHRRequest.ACTIVEX_VERSIONS = [ - "Msxml2.XMLHTTP.6.0", - "Msxml2.XMLHTTP.5.0", - "Msxml2.XMLHTTP.4.0", - "MSXML2.XMLHTTP.3.0", - "MSXML2.XMLHTTP", - "Microsoft.XMLHTTP" - ]; - -// Public methods - /** - * Look up the loaded result. - * @method getResult - * @param {Boolean} [raw=false] Return a raw result instead of a formatted result. This applies to content - * loaded via XHR such as scripts, XML, CSS, and Images. If there is no raw result, the formatted result will be - * returned instead. - * @return {Object} A result object containing the content that was loaded, such as: - *
      - *
    • An image tag (<image />) for images
    • - *
    • A script tag for JavaScript (<script />). Note that scripts loaded with tags may be added to the - * HTML head.
    • - *
    • A style tag for CSS (<style />)
    • - *
    • Raw text for TEXT
    • - *
    • A formatted JavaScript object defined by JSON
    • - *
    • An XML document
    • - *
    • An binary arraybuffer loaded by XHR
    • - *
    - * Note that if a raw result is requested, but not found, the result will be returned instead. - */ - p.getResult = function (raw) { - if (raw && this._rawResponse) { - return this._rawResponse; - } - return this._response; - }; - - // Overrides abstract method in AbstractRequest - p.cancel = function () { - this.canceled = true; - this._clean(); - this._request.abort(); - }; - - // Overrides abstract method in AbstractLoader - p.load = function () { - if (this._request == null) { - this._handleError(); - return; - } - - //Events - if (this._request.addEventListener != null) { - this._request.addEventListener("loadstart", this._handleLoadStartProxy, false); - this._request.addEventListener("progress", this._handleProgressProxy, false); - this._request.addEventListener("abort", this._handleAbortProxy, false); - this._request.addEventListener("error", this._handleErrorProxy, false); - this._request.addEventListener("timeout", this._handleTimeoutProxy, false); - - // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. - this._request.addEventListener("load", this._handleLoadProxy, false); - this._request.addEventListener("readystatechange", this._handleReadyStateChangeProxy, false); - } else { - // IE9 support - this._request.onloadstart = this._handleLoadStartProxy; - this._request.onprogress = this._handleProgressProxy; - this._request.onabort = this._handleAbortProxy; - this._request.onerror = this._handleErrorProxy; - this._request.ontimeout = this._handleTimeoutProxy; - - // Note: We don't get onload in all browsers (earlier FF and IE). onReadyStateChange handles these. - this._request.onload = this._handleLoadProxy; - this._request.onreadystatechange = this._handleReadyStateChangeProxy; - } - - // Set up a timeout if we don't have XHR2 - if (this._xhrLevel == 1) { - this._loadTimeout = setTimeout(createjs.proxy(this._handleTimeout, this), this._item.loadTimeout); - } - - // Sometimes we get back 404s immediately, particularly when there is a cross origin request. // note this does not catch in Chrome - try { - if (!this._item.values || this._item.method == createjs.AbstractLoader.GET) { - this._request.send(); - } else if (this._item.method == createjs.AbstractLoader.POST) { - this._request.send(createjs.RequestUtils.formatQueryString(this._item.values)); - } - } catch (error) { - this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND", null, error)); - } - }; - - p.setResponseType = function (type) { - // Some old browsers doesn't support blob, so we convert arraybuffer to blob after response is downloaded - if (type === 'blob') { - type = window.URL ? 'blob' : 'arraybuffer'; - this._responseType = type; - } - this._request.responseType = type; - }; - - /** - * Get all the response headers from the XmlHttpRequest. - * - * From the docs: Return all the HTTP headers, excluding headers that are a case-insensitive match - * for Set-Cookie or Set-Cookie2, as a single string, with each header line separated by a U+000D CR U+000A LF pair, - * excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE - * pair. - * @method getAllResponseHeaders - * @return {String} - * @since 0.4.1 - */ - p.getAllResponseHeaders = function () { - if (this._request.getAllResponseHeaders instanceof Function) { - return this._request.getAllResponseHeaders(); - } else { - return null; - } - }; - - /** - * Get a specific response header from the XmlHttpRequest. - * - * From the docs: Returns the header field value from the response of which the field name matches - * header, unless the field name is Set-Cookie or Set-Cookie2. - * @method getResponseHeader - * @param {String} header The header name to retrieve. - * @return {String} - * @since 0.4.1 - */ - p.getResponseHeader = function (header) { - if (this._request.getResponseHeader instanceof Function) { - return this._request.getResponseHeader(header); - } else { - return null; - } - }; - -// protected methods - /** - * The XHR request has reported progress. - * @method _handleProgress - * @param {Object} event The XHR progress event. - * @private - */ - p._handleProgress = function (event) { - if (!event || event.loaded > 0 && event.total == 0) { - return; // Sometimes we get no "total", so just ignore the progress event. - } - - var newEvent = new createjs.ProgressEvent(event.loaded, event.total); - this.dispatchEvent(newEvent); - }; - - /** - * The XHR request has reported a load start. - * @method _handleLoadStart - * @param {Object} event The XHR loadStart event. - * @private - */ - p._handleLoadStart = function (event) { - clearTimeout(this._loadTimeout); - this.dispatchEvent("loadstart"); - }; - - /** - * The XHR request has reported an abort event. - * @method handleAbort - * @param {Object} event The XHR abort event. - * @private - */ - p._handleAbort = function (event) { - this._clean(); - this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED", null, event)); - }; - - /** - * The XHR request has reported an error event. - * @method _handleError - * @param {Object} event The XHR error event. - * @private - */ - p._handleError = function (event) { - this._clean(); - this.dispatchEvent(new createjs.ErrorEvent(event.message)); - }; - - /** - * The XHR request has reported a readyState change. Note that older browsers (IE 7 & 8) do not provide an onload - * event, so we must monitor the readyStateChange to determine if the file is loaded. - * @method _handleReadyStateChange - * @param {Object} event The XHR readyStateChange event. - * @private - */ - p._handleReadyStateChange = function (event) { - if (this._request.readyState == 4) { - this._handleLoad(); - } - }; - - /** - * The XHR request has completed. This is called by the XHR request directly, or by a readyStateChange that has - * request.readyState == 4. Only the first call to this method will be processed. - * @method _handleLoad - * @param {Object} event The XHR load event. - * @private - */ - p._handleLoad = function (event) { - if (this.loaded) { - return; - } - this.loaded = true; - - var error = this._checkError(); - if (error) { - this._handleError(error); - return; - } - - this._response = this._getResponse(); - // Convert arraybuffer back to blob - if (this._responseType === 'arraybuffer') { - try { - this._response = new Blob([this._response]); - } catch (e) { - // Fallback to use BlobBuilder if Blob constructor is not supported - // Tested on Android 2.3 ~ 4.2 and iOS5 safari - window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; - if (e.name === 'TypeError' && window.BlobBuilder) { - var builder = new BlobBuilder(); - builder.append(this._response); - this._response = builder.getBlob(); - } - } - } - this._clean(); - - this.dispatchEvent(new createjs.Event("complete")); - }; - - /** - * The XHR request has timed out. This is called by the XHR request directly, or via a setTimeout - * callback. - * @method _handleTimeout - * @param {Object} [event] The XHR timeout event. This is occasionally null when called by the backup setTimeout. - * @private - */ - p._handleTimeout = function (event) { - this._clean(); - - this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT", null, event)); - }; - -// Protected - /** - * Determine if there is an error in the current load. This checks the status of the request for problem codes. Note - * that this does not check for an actual response. Currently, it only checks for 404 or 0 error code. - * @method _checkError - * @return {int} If the request status returns an error code. - * @private - */ - p._checkError = function () { - //LM: Probably need additional handlers here, maybe 501 - var status = parseInt(this._request.status); - - switch (status) { - case 404: // Not Found - case 0: // Not Loaded - return new Error(status); - } - return null; - }; - - /** - * Validate the response. Different browsers have different approaches, some of which throw errors when accessed - * in other browsers. If there is no response, the _response property will remain null. - * @method _getResponse - * @private - */ - p._getResponse = function () { - if (this._response != null) { - return this._response; - } - - if (this._request.response != null) { - return this._request.response; - } - - // Android 2.2 uses .responseText - try { - if (this._request.responseText != null) { - return this._request.responseText; - } - } catch (e) { - } - - // When loading XML, IE9 does not return .response, instead it returns responseXML.xml - try { - if (this._request.responseXML != null) { - return this._request.responseXML; - } - } catch (e) { - } - - return null; - }; - - /** - * Create an XHR request. Depending on a number of factors, we get totally different results. - *
    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.RequestUtils.isCrossDomain(item); - var headers = {}; - - // Create the request. Fallback to whatever support we have. - var req = null; - if (window.XMLHttpRequest) { - req = new XMLHttpRequest(); - // This is 8 or 9, so use XDomainRequest instead. - if (crossdomain && req.withCredentials === undefined && window.XDomainRequest) { - req = new XDomainRequest(); - } - } else { // Old IE versions use a different approach - for (var i = 0, l = s.ACTIVEX_VERSIONS.length; i < l; i++) { - var axVersion = s.ACTIVEX_VERSIONS[i]; - try { - req = new ActiveXObject(axVersion); - break; - } catch (e) { - } - } - if (req == null) { - return false; - } - } - - // Default to utf-8 for Text requests. - if (item.mimeType == null && createjs.RequestUtils.isText(item.type)) { - item.mimeType = "text/plain; charset=utf-8"; - } - - // IE9 doesn't support overrideMimeType(), so we need to check for it. - if (item.mimeType && req.overrideMimeType) { - req.overrideMimeType(item.mimeType); - } - - // Determine the XHR level - this._xhrLevel = (typeof req.responseType === "string") ? 2 : 1; - - var src = null; - if (item.method == createjs.AbstractLoader.GET) { - src = createjs.RequestUtils.buildPath(item.src, item.values); - } else { - src = item.src; - } - - // Open the request. Set cross-domain flags if it is supported (XHR level 1 only) - req.open(item.method || createjs.AbstractLoader.GET, src, true); - - if (crossdomain && req instanceof XMLHttpRequest && this._xhrLevel == 1) { - headers["Origin"] = location.origin; - } - - // To send data we need to set the Content-type header) - if (item.values && item.method == createjs.AbstractLoader.POST) { - headers["Content-Type"] = "application/x-www-form-urlencoded"; - } - - if (!crossdomain && !headers["X-Requested-With"]) { - headers["X-Requested-With"] = "XMLHttpRequest"; - } - - if (item.headers) { - for (var n in item.headers) { - headers[n] = item.headers[n]; - } - } - - for (n in headers) { - req.setRequestHeader(n, headers[n]) - } - - if (req instanceof XMLHttpRequest && item.withCredentials !== undefined) { - req.withCredentials = item.withCredentials; - } - - this._request = req; - - return true; - }; - - /** - * A request has completed (or failed or canceled), and needs to be disposed. - * @method _clean - * @private - */ - p._clean = function () { - clearTimeout(this._loadTimeout); - - if (this._request.removeEventListener != null) { - this._request.removeEventListener("loadstart", this._handleLoadStartProxy); - this._request.removeEventListener("progress", this._handleProgressProxy); - this._request.removeEventListener("abort", this._handleAbortProxy); - this._request.removeEventListener("error", this._handleErrorProxy); - this._request.removeEventListener("timeout", this._handleTimeoutProxy); - this._request.removeEventListener("load", this._handleLoadProxy); - this._request.removeEventListener("readystatechange", this._handleReadyStateChangeProxy); - } else { - this._request.onloadstart = null; - this._request.onprogress = null; - this._request.onabort = null; - this._request.onerror = null; - this._request.ontimeout = null; - this._request.onload = null; - this._request.onreadystatechange = null; - } - }; - - p.toString = function () { - return "[PreloadJS XHRRequest]"; - }; - - createjs.XHRRequest = createjs.promote(XHRRequest, "AbstractRequest"); - -}()); - -//############################################################################## -// 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.AbstractLoader.SOUND); - - // protected properties - if (createjs.RequestUtils.isAudioTag(loadItem)) { - this._tag = loadItem; - } else if (createjs.RequestUtils.isAudioTag(loadItem.src)) { - this._tag = loadItem; - } else if (createjs.RequestUtils.isAudioTag(loadItem.tag)) { - this._tag = createjs.RequestUtils.isAudioTag(loadItem) ? loadItem : loadItem.src; - } - - if (this._tag != null) { - this._preferXHR = false; - } - }; - - var p = createjs.extend(SoundLoader, createjs.AbstractMediaLoader); - var s = SoundLoader; - - // static methods - /** - * Determines if the loader can load a specific item. This loader can only load items that are of type - * {{#crossLink "AbstractLoader/SOUND:property"}}{{/crossLink}}. - * @method canLoadItem - * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load. - * @returns {Boolean} Whether the loader can load the item. - * @static - */ - s.canLoadItem = function (item) { - return item.type == createjs.AbstractLoader.SOUND; - }; - - // protected methods - p._createTag = function (src) { - var tag = document.createElement("audio"); - tag.autoplay = false; - tag.preload = "none"; - - //LM: Firefox fails when this the preload="none" for other tags, but it needs to be "none" to ensure PreloadJS works. - tag.src = src; - return tag; - }; - - createjs.SoundLoader = createjs.promote(SoundLoader, "AbstractMediaLoader"); - -}()); - -//############################################################################## -// AudioSprite.js -//############################################################################## - -// NOTE this is "Class" is purely to document audioSprite Setup and usage. - - -/** - * Note: AudioSprite is not a class, but its usage is easily lost in the documentation, so it has been called - * out here for quick reference. - * - * Audio sprites are much like CSS sprites or image sprite sheets: multiple audio assets grouped into a single file. - * Audio sprites work around limitations in certain browsers, where only a single sound can be loaded and played at a - * time. We recommend at least 300ms of silence between audio clips to deal with HTML audio tag inaccuracy, and to prevent - * accidentally playing bits of the neighbouring clips. - * - * Benefits of Audio Sprites: - *
      - *
    • More robust support for older browsers and devices that only allow a single audio instance, such as iOS 5.
    • - *
    • They provide a work around for the Internet Explorer 9 audio tag limit, which restricts how many different - * sounds that could be loaded at once.
    • - *
    • Faster loading by only requiring a single network request for several sounds, especially on mobile devices - * where the network round trip for each file can add significant latency.
    • - *
    - * - * Drawbacks of Audio Sprites - *
      - *
    • No guarantee of smooth looping when using HTML or Flash audio. If you have a track that needs to loop - * smoothly and you are supporting non-web audio browsers, do not use audio sprites for that sound if you can avoid - * it.
    • - *
    • No guarantee that HTML audio will play back immediately, especially the first time. In some browsers - * (Chrome!), HTML audio will only load enough to play through at the current download speed – so we rely on the - * `canplaythrough` event to determine if the audio is loaded. Since audio sprites must jump ahead to play specific - * sounds, the audio may not yet have downloaded fully.
    • - *
    • Audio sprites share the same core source, so if you have a sprite with 5 sounds and are limited to 2 - * concurrently playing instances, you can only play 2 of the sounds at the same time.
    • - *
    - * - *

    Example

    - * - * createjs.Sound.initializeDefaultPlugins(); - * var assetsPath = "./assets/"; - * var sounds = [{ - * src:"MyAudioSprite.ogg", data: { - * audioSprite: [ - * {id:"sound1", startTime:0, duration:500}, - * {id:"sound2", startTime:1000, duration:400}, - * {id:"sound3", startTime:1700, duration: 1000} - * ]} - * } - * ]; - * createjs.Sound.alternateExtensions = ["mp3"]; - * createjs.Sound.on("fileload", loadSound); - * createjs.Sound.registerSounds(sounds, assetsPath); - * // after load is complete - * createjs.Sound.play("sound2"); - * - * You can also create audio sprites on the fly by setting the startTime and duration when creating an new AbstractSoundInstance. - * - * createjs.Sound.play("MyAudioSprite", {startTime: 1000, duration: 400}); - * - * The excellent CreateJS community has created a tool to create audio sprites, available at - * https://github.com/tonistiigi/audiosprite, - * as well as a jsfiddle to convert the output - * to SoundJS format. - * - * @class AudioSprite - * @since 0.6.0 - */ - -//############################################################################## -// PlayPropsConfig.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - /** - * A class to store the optional play properties passed in {{#crossLink "Sound/play"}}{{/crossLink}} and - * {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}} calls. - * - * Optional Play Properties Include: - *
      - *
    • interrupt - How to interrupt any currently playing instances of audio with the same source, - * if the maximum number of instances of the sound are already playing. Values are defined as INTERRUPT_TYPE - * constants on the Sound class, with the default defined by {{#crossLink "Sound/defaultInterruptBehavior:property"}}{{/crossLink}}.
    • - *
    • delay - The amount of time to delay the start of audio playback, in milliseconds.
    • - *
    • offset - The offset from the start of the audio to begin playback, in milliseconds.
    • - *
    • loop - How many times the audio loops when it reaches the end of playback. The default is 0 (no - * loops), and -1 can be used for infinite playback.
    • - *
    • volume - The volume of the sound, between 0 and 1. Note that the master volume is applied - * against the individual volume.
    • - *
    • pan - The left-right pan of the sound (if supported), between -1 (left) and 1 (right).
    • - *
    • startTime - To create an audio sprite (with duration), the initial offset to start playback and loop from, in milliseconds.
    • - *
    • duration - To create an audio sprite (with startTime), the amount of time to play the clip for, in milliseconds.
    • - *
    - * - *

    Example

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

    Example

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

    Example

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

    Example

    - * - * var assetsPath = "./assets/"; - * var sounds = [{ - * src:"MyAudioSprite.ogg", data: { - * audioSprite: [ - * {id:"sound1", startTime:0, duration:500}, - * {id:"sound2", startTime:1000, duration:400}, - * {id:"sound3", startTime:1700, duration: 1000} - * ]} - * } - * ]; - * createjs.Sound.alternateExtensions = ["mp3"]; - * createjs.Sound.on("fileload", loadSound); - * createjs.Sound.registerSounds(sounds, assetsPath); - * // after load is complete - * createjs.Sound.play("sound2"); - * - * Mobile Playback
    - * Devices running iOS require the WebAudio context to be "unlocked" by playing at least one sound inside of a user- - * initiated event (such as touch/click). Earlier versions of SoundJS included a "MobileSafe" sample, but this is no - * longer necessary as of SoundJS 0.6.2. - *
      - *
    • - * In SoundJS 0.4.1 and above, you can either initialize plugins or use the {{#crossLink "WebAudioPlugin/playEmptySound"}}{{/crossLink}} - * method in the call stack of a user input event to manually unlock the audio context. - *
    • - *
    • - * In SoundJS 0.6.2 and above, SoundJS will automatically listen for the first document-level "mousedown" - * and "touchend" event, and unlock WebAudio. This will continue to check these events until the WebAudio - * context becomes "unlocked" (changes from "suspended" to "running") - *
    • - *
    • - * Both the "mousedown" and "touchend" events can be used to unlock audio in iOS9+, the "touchstart" event - * will work in iOS8 and below. The "touchend" event will only work in iOS9 when the gesture is interpreted - * as a "click", so if the user long-presses the button, it will no longer work. - *
    • - *
    • - * When using the EaselJS Touch class, - * the "mousedown" event will not fire when a canvas is clicked, since MouseEvents are prevented, to ensure - * only touch events fire. To get around this, you can either rely on "touchend", or: - *
        - *
      1. Set the `allowDefault` property on the Touch class constructor to `true` (defaults to `false`).
      2. - *
      3. Set the `preventSelection` property on the EaselJS `Stage` to `false`.
      4. - *
      - * These settings may change how your application behaves, and are not recommended. - *
    • - *
    - * - * Loading Alternate Paths and Extension-less Files
    - * SoundJS supports loading alternate paths and extension-less files by passing an object instead of a string for - * the `src` property, which is a hash using the format `{extension:"path", extension2:"path2"}`. These labels are - * how SoundJS determines if the browser will support the sound. This also enables multiple formats to live in - * different folders, or on CDNs, which often has completely different filenames for each file. - * - * Priority is determined by the property order (first property is tried first). This is supported by both internal loading - * and loading with PreloadJS. - * - * Note: an id is required for playback. - * - *

    Example

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

    Known Browser and OS issues

    - * IE 9 HTML Audio limitations
    - *
    • There is a delay in applying volume changes to tags that occurs once playback is started. So if you have - * muted all sounds, they will all play during this delay until the mute applies internally. This happens regardless of - * when or how you apply the volume change, as the tag seems to need to play to apply it.
    • - *
    • MP3 encoding will not always work for audio tags, particularly in Internet Explorer. We've found default - * encoding with 64kbps works.
    • - *
    • Occasionally very short samples will get cut off.
    • - *
    • There is a limit to how many audio tags you can load and play at once, which appears to be determined by - * hardware and browser settings. See {{#crossLink "HTMLAudioPlugin.MAX_INSTANCES"}}{{/crossLink}} for a safe - * estimate.
    - * - * Firefox 25 Web Audio limitations - *
    • mp3 audio files do not load properly on all windows machines, reported - * here.
      - * For this reason it is recommended to pass another FF supported type (ie ogg) first until this bug is resolved, if - * possible.
    - - * Safari limitations
    - *
    • Safari requires Quicktime to be installed for audio playback.
    - * - * iOS 6 Web Audio limitations
    - *
    • Sound is initially locked, and must be unlocked via a user-initiated event. Please see the section on - * Mobile Playback above.
    • - *
    • A bug exists that will distort un-cached web audio when a video element is present in the DOM that has audio - * at a different sampleRate.
    • - *
    - * - * Android HTML Audio limitations
    - *
    • We have no control over audio volume. Only the user can set volume on their device.
    • - *
    • We can only play audio inside a user event (touch/click). This currently means you cannot loop sound or use - * a delay.
    - * - * Web Audio and PreloadJS
    - *
    • Web Audio must be loaded through XHR, therefore when used with PreloadJS, tag loading is not possible. - * This means that tag loading can not be used to avoid cross domain issues.
      • - * - * @class Sound - * @static - * @uses EventDispatcher - */ - function Sound() { - throw "Sound cannot be instantiated"; - } - - var s = Sound; - - -// Static Properties - /** - * The interrupt value to interrupt any currently playing instance with the same source, if the maximum number of - * instances of the sound are already playing. - * @property INTERRUPT_ANY - * @type {String} - * @default any - * @static - */ - s.INTERRUPT_ANY = "any"; - - /** - * The interrupt value to interrupt the earliest currently playing instance with the same source that progressed the - * least distance in the audio track, if the maximum number of instances of the sound are already playing. - * @property INTERRUPT_EARLY - * @type {String} - * @default early - * @static - */ - s.INTERRUPT_EARLY = "early"; - - /** - * The interrupt value to interrupt the currently playing instance with the same source that progressed the most - * distance in the audio track, if the maximum number of instances of the sound are already playing. - * @property INTERRUPT_LATE - * @type {String} - * @default late - * @static - */ - s.INTERRUPT_LATE = "late"; - - /** - * The interrupt value to not interrupt any currently playing instances with the same source, if the maximum number of - * instances of the sound are already playing. - * @property INTERRUPT_NONE - * @type {String} - * @default none - * @static - */ - s.INTERRUPT_NONE = "none"; - - /** - * Defines the playState of an instance that is still initializing. - * @property PLAY_INITED - * @type {String} - * @default playInited - * @static - */ - s.PLAY_INITED = "playInited"; - - /** - * Defines the playState of an instance that is currently playing or paused. - * @property PLAY_SUCCEEDED - * @type {String} - * @default playSucceeded - * @static - */ - s.PLAY_SUCCEEDED = "playSucceeded"; - - /** - * Defines the playState of an instance that was interrupted by another instance. - * @property PLAY_INTERRUPTED - * @type {String} - * @default playInterrupted - * @static - */ - s.PLAY_INTERRUPTED = "playInterrupted"; - - /** - * Defines the playState of an instance that completed playback. - * @property PLAY_FINISHED - * @type {String} - * @default playFinished - * @static - */ - s.PLAY_FINISHED = "playFinished"; - - /** - * Defines the playState of an instance that failed to play. This is usually caused by a lack of available channels - * when the interrupt mode was "INTERRUPT_NONE", the playback stalled, or the sound could not be found. - * @property PLAY_FAILED - * @type {String} - * @default playFailed - * @static - */ - s.PLAY_FAILED = "playFailed"; - - /** - * A list of the default supported extensions that Sound will try to play. Plugins will check if the browser - * can play these types, so modifying this list before a plugin is initialized will allow the plugins to try to - * support additional media types. - * - * NOTE this does not currently work for {{#crossLink "FlashAudioPlugin"}}{{/crossLink}}. - * - * More details on file formats can be found at http://en.wikipedia.org/wiki/Audio_file_format.
        - * A very detailed list of file formats can be found at http://www.fileinfo.com/filetypes/audio. - * @property SUPPORTED_EXTENSIONS - * @type {Array[String]} - * @default ["mp3", "ogg", "opus", "mpeg", "wav", "m4a", "mp4", "aiff", "wma", "mid"] - * @since 0.4.0 - * @static - */ - s.SUPPORTED_EXTENSIONS = ["mp3", "ogg", "opus", "mpeg", "wav", "m4a", "mp4", "aiff", "wma", "mid"]; - - /** - * Some extensions use another type of extension support to play (one of them is a codex). This allows you to map - * that support so plugins can accurately determine if an extension is supported. Adding to this list can help - * plugins determine more accurately if an extension is supported. - * - * A useful list of extensions for each format can be found at http://html5doctor.com/html5-audio-the-state-of-play/. - * @property EXTENSION_MAP - * @type {Object} - * @since 0.4.0 - * @default {m4a:"mp4"} - * @static - */ - s.EXTENSION_MAP = { - m4a:"mp4" - }; - - /** - * The RegExp pattern used 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 path:$3 file:$4 extension:$5 query:$6. - * @property FILE_PATTERN - * @type {RegExp} - * @static - * @protected - */ - s.FILE_PATTERN = /^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/; - - -// Class Public properties - /** - * Determines the default behavior for interrupting other currently playing instances with the same source, if the - * maximum number of instances of the sound are already playing. Currently the default is {{#crossLink "Sound/INTERRUPT_NONE:property"}}{{/crossLink}} - * but this can be set and will change playback behavior accordingly. This is only used when {{#crossLink "Sound/play"}}{{/crossLink}} - * is called without passing a value for interrupt. - * @property defaultInterruptBehavior - * @type {String} - * @default Sound.INTERRUPT_NONE, or "none" - * @static - * @since 0.4.0 - */ - s.defaultInterruptBehavior = s.INTERRUPT_NONE; // OJR does s.INTERRUPT_ANY make more sense as default? Needs game dev testing to see which case makes more sense. - - /** - * An array of extensions to attempt to use when loading sound, if the default is unsupported by the active plugin. - * These are applied in order, so if you try to Load Thunder.ogg in a browser that does not support ogg, and your - * extensions array is ["mp3", "m4a", "wav"] it will check mp3 support, then m4a, then wav. The audio files need - * to exist in the same location, as only the extension is altered. - * - * Note that regardless of which file is loaded, you can call {{#crossLink "Sound/createInstance"}}{{/crossLink}} - * and {{#crossLink "Sound/play"}}{{/crossLink}} using the same id or full source path passed for loading. - * - *

        Example

        - * - * var sounds = [ - * {src:"myPath/mySound.ogg", id:"example"}, - * ]; - * createjs.Sound.alternateExtensions = ["mp3"]; // now if ogg is not supported, SoundJS will try asset0.mp3 - * createjs.Sound.on("fileload", handleLoad); // call handleLoad when each sound loads - * createjs.Sound.registerSounds(sounds, assetPath); - * // ... - * createjs.Sound.play("myPath/mySound.ogg"); // works regardless of what extension is supported. Note calling with ID is a better approach - * - * @property alternateExtensions - * @type {Array} - * @since 0.5.2 - * @static - */ - s.alternateExtensions = []; - - /** - * The currently active plugin. If this is null, then no plugin could be initialized. If no plugin was specified, - * Sound attempts to apply the default plugins: {{#crossLink "WebAudioPlugin"}}{{/crossLink}}, followed by - * {{#crossLink "HTMLAudioPlugin"}}{{/crossLink}}. - * @property activePlugin - * @type {Object} - * @static - */ - s.activePlugin = null; - - -// class getter / setter properties - /** - * Set the master volume of Sound. The master volume is multiplied against each sound's individual volume. For - * example, if master volume is 0.5 and a sound's volume is 0.5, the resulting volume is 0.25. To set individual - * sound volume, use AbstractSoundInstance {{#crossLink "AbstractSoundInstance/volume:property"}}{{/crossLink}} instead. - * - *

        Example

        - * - * createjs.Sound.volume = 0.5; - * - * - * @property volume - * @type {Number} - * @default 1 - * @since 0.6.1 - */ - s._masterVolume = 1; - Object.defineProperty(s, "volume", { - get: function () {return this._masterVolume;}, - set: function (value) { - if (Number(value) == null) {return false;} - value = Math.max(0, Math.min(1, value)); - s._masterVolume = value; - if (!this.activePlugin || !this.activePlugin.setVolume || !this.activePlugin.setVolume(value)) { - var instances = this._instances; - for (var i = 0, l = instances.length; i < l; i++) { - instances[i].setMasterVolume(value); - } - } - } - }); - - /** - * Mute/Unmute all audio. Note that muted audio still plays at 0 volume. This global mute value is maintained - * separately and when set will override, but not change the mute property of individual instances. To mute an individual - * instance, use AbstractSoundInstance {{#crossLink "AbstractSoundInstance/muted:property"}}{{/crossLink}} instead. - * - *

        Example

        - * - * createjs.Sound.muted = true; - * - * - * @property muted - * @type {Boolean} - * @default false - * @since 0.6.1 - */ - s._masterMute = false; - // OJR references to the methods were not working, so the code had to be duplicated here - Object.defineProperty(s, "muted", { - get: function () {return this._masterMute;}, - set: function (value) { - if (value == null) {return false;} - - this._masterMute = value; - if (!this.activePlugin || !this.activePlugin.setMute || !this.activePlugin.setMute(value)) { - var instances = this._instances; - for (var i = 0, l = instances.length; i < l; i++) { - instances[i].setMasterMute(value); - } - } - return true; - } - }); - - /** - * Get the active plugins capabilities, which help determine if a plugin can be used in the current environment, - * or if the plugin supports a specific feature. Capabilities include: - *
          - *
        • panning: If the plugin can pan audio from left to right
        • - *
        • volume; If the plugin can control audio volume.
        • - *
        • tracks: The maximum number of audio tracks that can be played back at a time. This will be -1 - * if there is no known limit.
        • - *
          An entry for each file type in {{#crossLink "Sound/SUPPORTED_EXTENSIONS:property"}}{{/crossLink}}: - *
        • mp3: If MP3 audio is supported.
        • - *
        • ogg: If OGG audio is supported.
        • - *
        • wav: If WAV audio is supported.
        • - *
        • mpeg: If MPEG audio is supported.
        • - *
        • m4a: If M4A audio is supported.
        • - *
        • mp4: If MP4 audio is supported.
        • - *
        • aiff: If aiff audio is supported.
        • - *
        • wma: If wma audio is supported.
        • - *
        • mid: If mid audio is supported.
        • - *
        - * - * You can get a specific capability of the active plugin using standard object notation - * - *

        Example

        - * - * var mp3 = createjs.Sound.capabilities.mp3; - * - * Note this property is read only. - * - * @property capabilities - * @type {Object} - * @static - * @readOnly - * @since 0.6.1 - */ - Object.defineProperty(s, "capabilities", { - get: function () { - if (s.activePlugin == null) {return null;} - return s.activePlugin._capabilities; - }, - set: function (value) { return false;} - }); - - -// Class Private properties - /** - * Determines if the plugins have been registered. If false, the first call to play() will instantiate the default - * plugins ({{#crossLink "WebAudioPlugin"}}{{/crossLink}}, followed by {{#crossLink "HTMLAudioPlugin"}}{{/crossLink}}). - * If plugins have been registered, but none are applicable, then sound playback will fail. - * @property _pluginsRegistered - * @type {Boolean} - * @default false - * @static - * @protected - */ - s._pluginsRegistered = false; - - /** - * Used internally to assign unique IDs to each AbstractSoundInstance. - * @property _lastID - * @type {Number} - * @static - * @protected - */ - s._lastID = 0; - - /** - * An array containing all currently playing instances. This allows Sound to control the volume, mute, and playback of - * all instances when using static APIs like {{#crossLink "Sound/stop"}}{{/crossLink}} and {{#crossLink "Sound/setVolume"}}{{/crossLink}}. - * When an instance has finished playback, it gets removed via the {{#crossLink "Sound/finishedPlaying"}}{{/crossLink}} - * method. If the user replays an instance, it gets added back in via the {{#crossLink "Sound/_beginPlaying"}}{{/crossLink}} - * method. - * @property _instances - * @type {Array} - * @protected - * @static - */ - s._instances = []; - - /** - * An object hash storing objects with sound sources, startTime, and duration via there corresponding ID. - * @property _idHash - * @type {Object} - * @protected - * @static - */ - s._idHash = {}; - - /** - * An object hash that stores preloading sound sources via the parsed source that is passed to the plugin. Contains the - * source, id, and data that was passed in by the user. Parsed sources can contain multiple instances of source, id, - * and data. - * @property _preloadHash - * @type {Object} - * @protected - * @static - */ - s._preloadHash = {}; - - /** - * An object hash storing {{#crossLink "PlayPropsConfig"}}{{/crossLink}} via the parsed source that is passed as defaultPlayProps in - * {{#crossLink "Sound/registerSound"}}{{/crossLink}} and {{#crossLink "Sound/registerSounds"}}{{/crossLink}}. - * @property _defaultPlayPropsHash - * @type {Object} - * @protected - * @static - * @since 0.6.1 - */ - s._defaultPlayPropsHash = {}; - - -// EventDispatcher methods: - s.addEventListener = null; - s.removeEventListener = null; - s.removeAllEventListeners = null; - s.dispatchEvent = null; - s.hasEventListener = null; - s._listeners = null; - - createjs.EventDispatcher.initialize(s); // inject EventDispatcher methods. - - -// Events - /** - * This event is fired when a file finishes loading internally. This event is fired for each loaded sound, - * so any handler methods should look up the event.src to handle a particular sound. - * @event fileload - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {String} src The source of the sound that was loaded. - * @param {String} [id] The id passed in when the sound was registered. If one was not provided, it will be null. - * @param {Number|Object} [data] Any additional data associated with the item. If not provided, it will be undefined. - * @since 0.4.1 - */ - - /** - * This event is fired when a file fails loading internally. This event is fired for each loaded sound, - * so any handler methods should look up the event.src to handle a particular sound. - * @event fileerror - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @param {String} src The source of the sound that was loaded. - * @param {String} [id] The id passed in when the sound was registered. If one was not provided, it will be null. - * @param {Number|Object} [data] Any additional data associated with the item. If not provided, it will be undefined. - * @since 0.6.0 - */ - - -// Class Public Methods - /** - * Get the preload rules to allow Sound to be used as a plugin by PreloadJS. - * Any load calls that have the matching type or extension will fire the callback method, and use the resulting - * object, which is potentially modified by Sound. This helps when determining the correct path, as well as - * registering the audio instance(s) with Sound. This method should not be called, except by PreloadJS. - * @method getPreloadHandlers - * @return {Object} An object containing: - *
        • callback: A preload callback that is fired when a file is added to PreloadJS, which provides - * Sound a mechanism to modify the load parameters, select the correct file format, register the sound, etc.
        • - *
        • types: A list of file types that are supported by Sound (currently supports "sound").
        • - *
        • extensions: A list of file extensions that are supported by Sound (see {{#crossLink "Sound/SUPPORTED_EXTENSIONS:property"}}{{/crossLink}}).
        - * @static - * @protected - */ - s.getPreloadHandlers = function () { - return { - callback:createjs.proxy(s.initLoad, s), - types:["sound"], - extensions:s.SUPPORTED_EXTENSIONS - }; - }; - - /** - * Used to dispatch fileload events from internal loading. - * @method _handleLoadComplete - * @param event A loader event. - * @protected - * @static - * @since 0.6.0 - */ - s._handleLoadComplete = function(event) { - var src = event.target.getItem().src; - if (!s._preloadHash[src]) {return;} - - for (var i = 0, l = s._preloadHash[src].length; i < l; i++) { - var item = s._preloadHash[src][i]; - s._preloadHash[src][i] = true; - - if (!s.hasEventListener("fileload")) { continue; } - - var event = new createjs.Event("fileload"); - event.src = item.src; - event.id = item.id; - event.data = item.data; - event.sprite = item.sprite; - - s.dispatchEvent(event); - } - }; - - /** - * Used to dispatch error events from internal preloading. - * @param event - * @protected - * @since 0.6.0 - * @static - */ - s._handleLoadError = function(event) { - var src = event.target.getItem().src; - if (!s._preloadHash[src]) {return;} - - for (var i = 0, l = s._preloadHash[src].length; i < l; i++) { - var item = s._preloadHash[src][i]; - s._preloadHash[src][i] = false; - - if (!s.hasEventListener("fileerror")) { continue; } - - var event = new createjs.Event("fileerror"); - event.src = item.src; - event.id = item.id; - event.data = item.data; - event.sprite = item.sprite; - - s.dispatchEvent(event); - } - }; - - /** - * Used by {{#crossLink "Sound/registerPlugins"}}{{/crossLink}} to register a Sound plugin. - * - * @method _registerPlugin - * @param {Object} plugin The plugin class to install. - * @return {Boolean} Whether the plugin was successfully initialized. - * @static - * @private - */ - s._registerPlugin = function (plugin) { - // Note: Each plugin is passed in as a class reference, but we store the activePlugin as an instance - if (plugin.isSupported()) { - s.activePlugin = new plugin(); - return true; - } - return false; - }; - - /** - * Register a list of Sound plugins, in order of precedence. To register a single plugin, pass a single element in the array. - * - *

        Example

        - * - * createjs.FlashAudioPlugin.swfPath = "../src/soundjs/flashaudio/"; - * createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.HTMLAudioPlugin, createjs.FlashAudioPlugin]); - * - * @method registerPlugins - * @param {Array} plugins An array of plugins classes to install. - * @return {Boolean} Whether a plugin was successfully initialized. - * @static - */ - s.registerPlugins = function (plugins) { - s._pluginsRegistered = true; - for (var i = 0, l = plugins.length; i < l; i++) { - if (s._registerPlugin(plugins[i])) { - return true; - } - } - return false; - }; - - /** - * Initialize the default plugins. This method is automatically called when any audio is played or registered before - * the user has manually registered plugins, and enables Sound to work without manual plugin setup. Currently, the - * default plugins are {{#crossLink "WebAudioPlugin"}}{{/crossLink}} followed by {{#crossLink "HTMLAudioPlugin"}}{{/crossLink}}. - * - *

        Example

        - * - * if (!createjs.initializeDefaultPlugins()) { return; } - * - * @method initializeDefaultPlugins - * @returns {Boolean} True if a plugin was initialized, false otherwise. - * @since 0.4.0 - * @static - */ - s.initializeDefaultPlugins = function () { - if (s.activePlugin != null) {return true;} - if (s._pluginsRegistered) {return false;} - if (s.registerPlugins([createjs.WebAudioPlugin, createjs.HTMLAudioPlugin])) {return true;} - return false; - }; - - /** - * Determines if Sound has been initialized, and a plugin has been activated. - * - *

        Example

        - * This example sets up a Flash fallback, but only if there is no plugin specified yet. - * - * if (!createjs.Sound.isReady()) { - * createjs.FlashAudioPlugin.swfPath = "../src/soundjs/flashaudio/"; - * createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.HTMLAudioPlugin, createjs.FlashAudioPlugin]); - * } - * - * @method isReady - * @return {Boolean} If Sound has initialized a plugin. - * @static - */ - s.isReady = function () { - return (s.activePlugin != null); - }; - - /** - * Deprecated, please use {{#crossLink "Sound/capabilities:property"}}{{/crossLink}} instead. - * - * @method getCapabilities - * @return {Object} An object containing the capabilities of the active plugin. - * @static - * @deprecated - */ - s.getCapabilities = function () { - if (s.activePlugin == null) {return null;} - return s.activePlugin._capabilities; - }; - - /** - * Deprecated, please use {{#crossLink "Sound/capabilities:property"}}{{/crossLink}} instead. - * - * @method getCapability - * @param {String} key The capability to retrieve - * @return {Number|Boolean} The value of the capability. - * @static - * @see getCapabilities - * @deprecated - */ - s.getCapability = function (key) { - if (s.activePlugin == null) {return null;} - return s.activePlugin._capabilities[key]; - }; - - /** - * Process manifest items from PreloadJS. This method is intended - * for usage by a plugin, and not for direct interaction. - * @method initLoad - * @param {Object} src The object to load. - * @return {Object|AbstractLoader} An instance of AbstractLoader. - * @protected - * @static - */ - s.initLoad = function (loadItem) { - return s._registerSound(loadItem); - }; - - /** - * Internal method for loading sounds. This should not be called directly. - * - * @method _registerSound - * @param {Object} src The object to load, containing src property and optionally containing id and data. - * @return {Object} An object with the modified values that were passed in, which defines the sound. - * Returns false if the source cannot be parsed or no plugins can be initialized. - * Returns true if the source is already loaded. - * @static - * @private - * @since 0.6.0 - */ - - s._registerSound = function (loadItem) { - if (!s.initializeDefaultPlugins()) {return false;} - - var details; - if (loadItem.src instanceof Object) { - details = s._parseSrc(loadItem.src); - details.src = loadItem.path + details.src; - } else { - details = s._parsePath(loadItem.src); - } - if (details == null) {return false;} - loadItem.src = details.src; - loadItem.type = "sound"; - - var data = loadItem.data; - var numChannels = null; - if (data != null) { - if (!isNaN(data.channels)) { - numChannels = parseInt(data.channels); - } else if (!isNaN(data)) { - numChannels = parseInt(data); - } - - if(data.audioSprite) { - var sp; - for(var i = data.audioSprite.length; i--; ) { - sp = data.audioSprite[i]; - s._idHash[sp.id] = {src: loadItem.src, startTime: parseInt(sp.startTime), duration: parseInt(sp.duration)}; - - if (sp.defaultPlayProps) { - s._defaultPlayPropsHash[sp.id] = createjs.PlayPropsConfig.create(sp.defaultPlayProps); - } - } - } - } - if (loadItem.id != null) {s._idHash[loadItem.id] = {src: loadItem.src}}; - var loader = s.activePlugin.register(loadItem); - - SoundChannel.create(loadItem.src, numChannels); - - // return the number of instances to the user. This will also be returned in the load event. - if (data == null || !isNaN(data)) { - loadItem.data = numChannels || SoundChannel.maxPerChannel(); - } else { - loadItem.data.channels = numChannels || SoundChannel.maxPerChannel(); - } - - if (loader.type) {loadItem.type = loader.type;} - - if (loadItem.defaultPlayProps) { - s._defaultPlayPropsHash[loadItem.src] = createjs.PlayPropsConfig.create(loadItem.defaultPlayProps); - } - return loader; - }; - - /** - * Register an audio file for loading and future playback in Sound. This is automatically called when using - * PreloadJS. It is recommended to register all sounds that - * need to be played back in order to properly prepare and preload them. Sound does internal preloading when required. - * - *

        Example

        - * - * createjs.Sound.alternateExtensions = ["mp3"]; - * createjs.Sound.on("fileload", handleLoad); // add an event listener for when load is completed - * createjs.Sound.registerSound("myAudioPath/mySound.ogg", "myID", 3); - * createjs.Sound.registerSound({ogg:"path1/mySound.ogg", mp3:"path2/mySoundNoExtension"}, "myID", 3); - * - * - * @method registerSound - * @param {String | Object} src The source or an Object with a "src" property or an Object with multiple extension labeled src properties. - * @param {String} [id] An id specified by the user to play the sound later. Note id is required for when src is multiple extension labeled src properties. - * @param {Number | Object} [data] Data associated with the item. Sound uses the data parameter as the number of - * channels for an audio instance, however a "channels" property can be appended to the data object if it is used - * for other information. The audio channels will set a default based on plugin if no value is found. - * Sound also uses the data property to hold an {{#crossLink "AudioSprite"}}{{/crossLink}} array of objects in the following format {id, startTime, duration}.
        - * id used to play the sound later, in the same manner as a sound src with an id.
        - * startTime is the initial offset to start playback and loop from, in milliseconds.
        - * duration is the amount of time to play the clip for, in milliseconds.
        - * This allows Sound to support audio sprites that are played back by id. - * @param {string} basePath Set a path that will be prepended to src for loading. - * @param {Object | PlayPropsConfig} defaultPlayProps Optional Playback properties that will be set as the defaults on any new AbstractSoundInstance. - * See {{#crossLink "PlayPropsConfig"}}{{/crossLink}} for options. - * @return {Object} An object with the modified values that were passed in, which defines the sound. - * Returns false if the source cannot be parsed or no plugins can be initialized. - * Returns true if the source is already loaded. - * @static - * @since 0.4.0 - */ - s.registerSound = function (src, id, data, basePath, defaultPlayProps) { - var loadItem = {src: src, id: id, data:data, defaultPlayProps:defaultPlayProps}; - if (src instanceof Object && src.src) { - basePath = id; - loadItem = src; - } - loadItem = createjs.LoadItem.create(loadItem); - loadItem.path = basePath; - - if (basePath != null && !(loadItem.src instanceof Object)) {loadItem.src = basePath + src;} - - var loader = s._registerSound(loadItem); - if(!loader) {return false;} - - if (!s._preloadHash[loadItem.src]) { s._preloadHash[loadItem.src] = [];} - s._preloadHash[loadItem.src].push(loadItem); - if (s._preloadHash[loadItem.src].length == 1) { - // OJR note this will disallow reloading a sound if loading fails or the source changes - loader.on("complete", createjs.proxy(this._handleLoadComplete, this)); - loader.on("error", createjs.proxy(this._handleLoadError, this)); - s.activePlugin.preload(loader); - } else { - if (s._preloadHash[loadItem.src][0] == true) {return true;} - } - - return loadItem; - }; - - /** - * Register an array of audio files for loading and future playback in Sound. It is recommended to register all - * sounds that need to be played back in order to properly prepare and preload them. Sound does internal preloading - * when required. - * - *

        Example

        - * - * var assetPath = "./myAudioPath/"; - * var sounds = [ - * {src:"asset0.ogg", id:"example"}, - * {src:"asset1.ogg", id:"1", data:6}, - * {src:"asset2.mp3", id:"works"} - * {src:{mp3:"path1/asset3.mp3", ogg:"path2/asset3NoExtension"}, id:"better"} - * ]; - * createjs.Sound.alternateExtensions = ["mp3"]; // if the passed extension is not supported, try this extension - * createjs.Sound.on("fileload", handleLoad); // call handleLoad when each sound loads - * createjs.Sound.registerSounds(sounds, assetPath); - * - * @method registerSounds - * @param {Array} sounds An array of objects to load. Objects are expected to be in the format needed for - * {{#crossLink "Sound/registerSound"}}{{/crossLink}}: {src:srcURI, id:ID, data:Data} - * with "id" and "data" being optional. - * You can also pass an object with path and manifest properties, where path is a basePath and manifest is an array of objects to load. - * Note id is required if src is an object with extension labeled src properties. - * @param {string} basePath Set a path that will be prepended to each src when loading. When creating, playing, or removing - * audio that was loaded with a basePath by src, the basePath must be included. - * @return {Object} An array of objects with the modified values that were passed in, which defines each sound. - * Like registerSound, it will return false for any values when the source cannot be parsed or if no plugins can be initialized. - * Also, it will return true for any values when the source is already loaded. - * @static - * @since 0.6.0 - */ - s.registerSounds = function (sounds, basePath) { - var returnValues = []; - if (sounds.path) { - if (!basePath) { - basePath = sounds.path; - } else { - basePath = basePath + sounds.path; - } - sounds = sounds.manifest; - // TODO document this feature - } - for (var i = 0, l = sounds.length; i < l; i++) { - returnValues[i] = createjs.Sound.registerSound(sounds[i].src, sounds[i].id, sounds[i].data, basePath, sounds[i].defaultPlayProps); - } - return returnValues; - }; - - /** - * Remove a sound that has been registered with {{#crossLink "Sound/registerSound"}}{{/crossLink}} or - * {{#crossLink "Sound/registerSounds"}}{{/crossLink}}. - *
        Note this will stop playback on active instances playing this sound before deleting them. - *
        Note if you passed in a basePath, you need to pass it or prepend it to the src here. - * - *

        Example

        - * - * createjs.Sound.removeSound("myID"); - * createjs.Sound.removeSound("myAudioBasePath/mySound.ogg"); - * createjs.Sound.removeSound("myPath/myOtherSound.mp3", "myBasePath/"); - * createjs.Sound.removeSound({mp3:"musicNoExtension", ogg:"music.ogg"}, "myBasePath/"); - * - * @method removeSound - * @param {String | Object} src The src or ID of the audio, or an Object with a "src" property, or an Object with multiple extension labeled src properties. - * @param {string} basePath Set a path that will be prepended to each src when removing. - * @return {Boolean} True if sound is successfully removed. - * @static - * @since 0.4.1 - */ - s.removeSound = function(src, basePath) { - if (s.activePlugin == null) {return false;} - - if (src instanceof Object && src.src) {src = src.src;} - - var details; - if (src instanceof Object) { - details = s._parseSrc(src); - } else { - src = s._getSrcById(src).src; - details = s._parsePath(src); - } - if (details == null) {return false;} - src = details.src; - if (basePath != null) {src = basePath + src;} - - for(var prop in s._idHash){ - if(s._idHash[prop].src == src) { - delete(s._idHash[prop]); - } - } - - // clear from SoundChannel, which also stops and deletes all instances - SoundChannel.removeSrc(src); - - delete(s._preloadHash[src]); - - s.activePlugin.removeSound(src); - - return true; - }; - - /** - * Remove an array of audio files that have been registered with {{#crossLink "Sound/registerSound"}}{{/crossLink}} or - * {{#crossLink "Sound/registerSounds"}}{{/crossLink}}. - *
        Note this will stop playback on active instances playing this audio before deleting them. - *
        Note if you passed in a basePath, you need to pass it or prepend it to the src here. - * - *

        Example

        - * - * assetPath = "./myPath/"; - * var sounds = [ - * {src:"asset0.ogg", id:"example"}, - * {src:"asset1.ogg", id:"1", data:6}, - * {src:"asset2.mp3", id:"works"} - * ]; - * createjs.Sound.removeSounds(sounds, assetPath); - * - * @method removeSounds - * @param {Array} sounds An array of objects to remove. Objects are expected to be in the format needed for - * {{#crossLink "Sound/removeSound"}}{{/crossLink}}: {srcOrID:srcURIorID}. - * You can also pass an object with path and manifest properties, where path is a basePath and manifest is an array of objects to remove. - * @param {string} basePath Set a path that will be prepended to each src when removing. - * @return {Object} An array of Boolean values representing if the sounds with the same array index were - * successfully removed. - * @static - * @since 0.4.1 - */ - s.removeSounds = function (sounds, basePath) { - var returnValues = []; - if (sounds.path) { - if (!basePath) { - basePath = sounds.path; - } else { - basePath = basePath + sounds.path; - } - sounds = sounds.manifest; - } - for (var i = 0, l = sounds.length; i < l; i++) { - returnValues[i] = createjs.Sound.removeSound(sounds[i].src, basePath); - } - return returnValues; - }; - - /** - * Remove all sounds that have been registered with {{#crossLink "Sound/registerSound"}}{{/crossLink}} or - * {{#crossLink "Sound/registerSounds"}}{{/crossLink}}. - *
        Note this will stop playback on all active sound instances before deleting them. - * - *

        Example

        - * - * createjs.Sound.removeAllSounds(); - * - * @method removeAllSounds - * @static - * @since 0.4.1 - */ - s.removeAllSounds = function() { - s._idHash = {}; - s._preloadHash = {}; - SoundChannel.removeAll(); - if (s.activePlugin) {s.activePlugin.removeAllSounds();} - }; - - /** - * Check if a source has been loaded by internal preloaders. This is necessary to ensure that sounds that are - * not completed preloading will not kick off a new internal preload if they are played. - * - *

        Example

        - * - * var mySound = "assetPath/asset0.ogg"; - * if(createjs.Sound.loadComplete(mySound) { - * createjs.Sound.play(mySound); - * } - * - * @method loadComplete - * @param {String} src The src or id that is being loaded. - * @return {Boolean} If the src is already loaded. - * @since 0.4.0 - * @static - */ - s.loadComplete = function (src) { - if (!s.isReady()) { return false; } - var details = s._parsePath(src); - if (details) { - src = s._getSrcById(details.src).src; - } else { - src = s._getSrcById(src).src; - } - if(s._preloadHash[src] == undefined) {return false;} - return (s._preloadHash[src][0] == true); // src only loads once, so if it's true for the first it's true for all - }; - - /** - * Parse the path of a sound. Alternate extensions will be attempted in order if the - * current extension is not supported - * @method _parsePath - * @param {String} value The path to an audio source. - * @return {Object} A formatted object that can be registered with the {{#crossLink "Sound/activePlugin:property"}}{{/crossLink}} - * and returned to a preloader like PreloadJS. - * @protected - * @static - */ - s._parsePath = function (value) { - if (typeof(value) != "string") {value = value.toString();} - - var match = value.match(s.FILE_PATTERN); - if (match == null) {return false;} - - var name = match[4]; - var ext = match[5]; - var c = s.capabilities; - var i = 0; - while (!c[ext]) { - ext = s.alternateExtensions[i++]; - if (i > s.alternateExtensions.length) { return null;} // no extensions are supported - } - value = value.replace("."+match[5], "."+ext); - - var ret = {name:name, src:value, extension:ext}; - return ret; - }; - - /** - * Parse the path of a sound based on properties of src matching with supported extensions. - * Returns false if none of the properties are supported - * @method _parseSrc - * @param {Object} value The paths to an audio source, indexed by extension type. - * @return {Object} A formatted object that can be registered with the {{#crossLink "Sound/activePlugin:property"}}{{/crossLink}} - * and returned to a preloader like PreloadJS. - * @protected - * @static - */ - s._parseSrc = function (value) { - var ret = {name:undefined, src:undefined, extension:undefined}; - var c = s.capabilities; - - for (var prop in value) { - if(value.hasOwnProperty(prop) && c[prop]) { - ret.src = value[prop]; - ret.extension = prop; - break; - } - } - if (!ret.src) {return false;} // no matches - - var i = ret.src.lastIndexOf("/"); - if (i != -1) { - ret.name = ret.src.slice(i+1); - } else { - ret.name = ret.src; - } - - return ret; - }; - - /* --------------- - Static API. - --------------- */ - /** - * Play a sound and get a {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} to control. If the sound fails to play, a - * AbstractSoundInstance will still be returned, and have a playState of {{#crossLink "Sound/PLAY_FAILED:property"}}{{/crossLink}}. - * Note that even on sounds with failed playback, you may still be able to call AbstractSoundInstance {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}}, - * since the failure could be due to lack of available channels. If the src does not have a supported extension or - * if there is no available plugin, a default AbstractSoundInstance will be returned which will not play any audio, but will not generate errors. - * - *

        Example

        - * - * createjs.Sound.on("fileload", handleLoad); - * createjs.Sound.registerSound("myAudioPath/mySound.mp3", "myID", 3); - * function handleLoad(event) { - * createjs.Sound.play("myID"); - * // store off AbstractSoundInstance for controlling - * var myInstance = createjs.Sound.play("myID", {interrupt: createjs.Sound.INTERRUPT_ANY, loop:-1}); - * } - * - * NOTE to create an audio sprite that has not already been registered, both startTime and duration need to be set. - * This is only when creating a new audio sprite, not when playing using the id of an already registered audio sprite. - * - * Parameters Deprecated
        - * The parameters for this method are deprecated in favor of a single parameter that is an Object or {{#crossLink "PlayPropsConfig"}}{{/crossLink}}. - * - * @method play - * @param {String} src The src or ID of the audio. - * @param {String | Object} [interrupt="none"|options] This parameter will be renamed playProps in the next release.
        - * This parameter can be an instance of {{#crossLink "PlayPropsConfig"}}{{/crossLink}} or an Object that contains any or all optional properties by name, - * including: interrupt, delay, offset, loop, volume, pan, startTime, and duration (see the above code sample). - *
        OR
        - * Deprecated How to interrupt any currently playing instances of audio with the same source, - * if the maximum number of instances of the sound are already playing. Values are defined as INTERRUPT_TYPE - * constants on the Sound class, with the default defined by {{#crossLink "Sound/defaultInterruptBehavior:property"}}{{/crossLink}}. - * @param {Number} [delay=0] Deprecated The amount of time to delay the start of audio playback, in milliseconds. - * @param {Number} [offset=0] Deprecated The offset from the start of the audio to begin playback, in milliseconds. - * @param {Number} [loop=0] Deprecated How many times the audio loops when it reaches the end of playback. The default is 0 (no - * loops), and -1 can be used for infinite playback. - * @param {Number} [volume=1] Deprecated The volume of the sound, between 0 and 1. Note that the master volume is applied - * against the individual volume. - * @param {Number} [pan=0] Deprecated The left-right pan of the sound (if supported), between -1 (left) and 1 (right). - * @param {Number} [startTime=null] Deprecated To create an audio sprite (with duration), the initial offset to start playback and loop from, in milliseconds. - * @param {Number} [duration=null] Deprecated To create an audio sprite (with startTime), the amount of time to play the clip for, in milliseconds. - * @return {AbstractSoundInstance} A {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} that can be controlled after it is created. - * @static - */ - s.play = function (src, interrupt, delay, offset, loop, volume, pan, startTime, duration) { - var playProps; - if (interrupt instanceof Object || interrupt instanceof createjs.PlayPropsConfig) { - playProps = createjs.PlayPropsConfig.create(interrupt); - } else { - playProps = createjs.PlayPropsConfig.create({interrupt:interrupt, delay:delay, offset:offset, loop:loop, volume:volume, pan:pan, startTime:startTime, duration:duration}); - } - var instance = s.createInstance(src, playProps.startTime, playProps.duration); - var ok = s._playInstance(instance, playProps); - if (!ok) {instance._playFailed();} - return instance; - }; - - /** - * Creates a {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} using the passed in src. If the src does not have a - * supported extension or if there is no available plugin, a default AbstractSoundInstance will be returned that can be - * called safely but does nothing. - * - *

        Example

        - * - * var myInstance = null; - * createjs.Sound.on("fileload", handleLoad); - * createjs.Sound.registerSound("myAudioPath/mySound.mp3", "myID", 3); - * function handleLoad(event) { - * myInstance = createjs.Sound.createInstance("myID"); - * // alternately we could call the following - * myInstance = createjs.Sound.createInstance("myAudioPath/mySound.mp3"); - * } - * - * NOTE to create an audio sprite that has not already been registered, both startTime and duration need to be set. - * This is only when creating a new audio sprite, not when playing using the id of an already registered audio sprite. - * - * @method createInstance - * @param {String} src The src or ID of the audio. - * @param {Number} [startTime=null] To create an audio sprite (with duration), the initial offset to start playback and loop from, in milliseconds. - * @param {Number} [duration=null] To create an audio sprite (with startTime), the amount of time to play the clip for, in milliseconds. - * @return {AbstractSoundInstance} A {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} that can be controlled after it is created. - * Unsupported extensions will return the default AbstractSoundInstance. - * @since 0.4.0 - * @static - */ - s.createInstance = function (src, startTime, duration) { - if (!s.initializeDefaultPlugins()) {return new createjs.DefaultSoundInstance(src, startTime, duration);} - - var defaultPlayProps = s._defaultPlayPropsHash[src]; // for audio sprites, which create and store defaults by id - src = s._getSrcById(src); - - var details = s._parsePath(src.src); - - var instance = null; - if (details != null && details.src != null) { - SoundChannel.create(details.src); - if (startTime == null) {startTime = src.startTime;} - instance = s.activePlugin.create(details.src, startTime, duration || src.duration); - - defaultPlayProps = defaultPlayProps || s._defaultPlayPropsHash[details.src]; - if(defaultPlayProps) { - instance.applyPlayProps(defaultPlayProps); - } - } else { - instance = new createjs.DefaultSoundInstance(src, startTime, duration); - } - - instance.uniqueId = s._lastID++; - - return instance; - }; - - /** - * Stop all audio (global stop). Stopped audio is reset, and not paused. To play audio that has been stopped, - * call AbstractSoundInstance {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}}. - * - *

        Example

        - * - * createjs.Sound.stop(); - * - * @method stop - * @static - */ - s.stop = function () { - var instances = this._instances; - for (var i = instances.length; i--; ) { - instances[i].stop(); // NOTE stop removes instance from this._instances - } - }; - - /** - * Deprecated, please use {{#crossLink "Sound/volume:property"}}{{/crossLink}} instead. - * - * @method setVolume - * @param {Number} value The master volume value. The acceptable range is 0-1. - * @static - * @deprecated - */ - s.setVolume = function (value) { - if (Number(value) == null) {return false;} - value = Math.max(0, Math.min(1, value)); - s._masterVolume = value; - if (!this.activePlugin || !this.activePlugin.setVolume || !this.activePlugin.setVolume(value)) { - var instances = this._instances; - for (var i = 0, l = instances.length; i < l; i++) { - instances[i].setMasterVolume(value); - } - } - }; - - /** - * Deprecated, please use {{#crossLink "Sound/volume:property"}}{{/crossLink}} instead. - * - * @method getVolume - * @return {Number} The master volume, in a range of 0-1. - * @static - * @deprecated - */ - s.getVolume = function () { - return this._masterVolume; - }; - - /** - * Deprecated, please use {{#crossLink "Sound/muted:property"}}{{/crossLink}} instead. - * - * @method setMute - * @param {Boolean} value Whether the audio should be muted or not. - * @return {Boolean} If the mute was set. - * @static - * @since 0.4.0 - * @deprecated - */ - s.setMute = function (value) { - if (value == null) {return false;} - - this._masterMute = value; - if (!this.activePlugin || !this.activePlugin.setMute || !this.activePlugin.setMute(value)) { - var instances = this._instances; - for (var i = 0, l = instances.length; i < l; i++) { - instances[i].setMasterMute(value); - } - } - return true; - }; - - /** - * Deprecated, please use {{#crossLink "Sound/muted:property"}}{{/crossLink}} instead. - * - * @method getMute - * @return {Boolean} The mute value of Sound. - * @static - * @since 0.4.0 - * @deprecated - */ - s.getMute = function () { - return this._masterMute; - }; - - /** - * Set the default playback properties for all new SoundInstances of the passed in src or ID. - * See {{#crossLink "PlayPropsConfig"}}{{/crossLink}} for available properties. - * - * @method setDefaultPlayProps - * @param {String} src The src or ID used to register the audio. - * @param {Object | PlayPropsConfig} playProps The playback properties you would like to set. - * @since 0.6.1 - */ - s.setDefaultPlayProps = function(src, playProps) { - src = s._getSrcById(src); - s._defaultPlayPropsHash[s._parsePath(src.src).src] = createjs.PlayPropsConfig.create(playProps); - }; - - /** - * Get the default playback properties for the passed in src or ID. These properties are applied to all - * new SoundInstances. Returns null if default does not exist. - * - * @method getDefaultPlayProps - * @param {String} src The src or ID used to register the audio. - * @returns {PlayPropsConfig} returns an existing PlayPropsConfig or null if one does not exist - * @since 0.6.1 - */ - s.getDefaultPlayProps = function(src) { - src = s._getSrcById(src); - return s._defaultPlayPropsHash[s._parsePath(src.src).src]; - }; - - - /* --------------- - Internal methods - --------------- */ - /** - * Play an instance. This is called by the static API, as well as from plugins. This allows the core class to - * control delays. - * @method _playInstance - * @param {AbstractSoundInstance} instance The {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} to start playing. - * @param {PlayPropsConfig} playProps A PlayPropsConfig object. - * @return {Boolean} If the sound can start playing. Sounds that fail immediately will return false. Sounds that - * have a delay will return true, but may still fail to play. - * @protected - * @static - */ - s._playInstance = function (instance, playProps) { - var defaultPlayProps = s._defaultPlayPropsHash[instance.src] || {}; - if (playProps.interrupt == null) {playProps.interrupt = defaultPlayProps.interrupt || s.defaultInterruptBehavior}; - if (playProps.delay == null) {playProps.delay = defaultPlayProps.delay || 0;} - if (playProps.offset == null) {playProps.offset = instance.getPosition();} - if (playProps.loop == null) {playProps.loop = instance.loop;} - if (playProps.volume == null) {playProps.volume = instance.volume;} - if (playProps.pan == null) {playProps.pan = instance.pan;} - - if (playProps.delay == 0) { - var ok = s._beginPlaying(instance, playProps); - if (!ok) {return false;} - } else { - //Note that we can't pass arguments to proxy OR setTimeout (IE only), so just wrap the function call. - // OJR WebAudio may want to handle this differently, so it might make sense to move this functionality into the plugins in the future - var delayTimeoutId = setTimeout(function () { - s._beginPlaying(instance, playProps); - }, playProps.delay); - instance.delayTimeoutId = delayTimeoutId; - } - - this._instances.push(instance); - - return true; - }; - - /** - * Begin playback. This is called immediately or after delay by {{#crossLink "Sound/playInstance"}}{{/crossLink}}. - * @method _beginPlaying - * @param {AbstractSoundInstance} instance A {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} to begin playback. - * @param {PlayPropsConfig} playProps A PlayPropsConfig object. - * @return {Boolean} If the sound can start playing. If there are no available channels, or the instance fails to - * start, this will return false. - * @protected - * @static - */ - s._beginPlaying = function (instance, playProps) { - if (!SoundChannel.add(instance, playProps.interrupt)) { - return false; - } - var result = instance._beginPlaying(playProps); - if (!result) { - var index = createjs.indexOf(this._instances, instance); - if (index > -1) {this._instances.splice(index, 1);} - return false; - } - return true; - }; - - /** - * Get the source of a sound via the ID passed in with a register call. If no ID is found the value is returned - * instead. - * @method _getSrcById - * @param {String} value The ID the sound was registered with. - * @return {String} The source of the sound if it has been registered with this ID or the value that was passed in. - * @protected - * @static - */ - s._getSrcById = function (value) { - return s._idHash[value] || {src: value}; - }; - - /** - * A sound has completed playback, been interrupted, failed, or been stopped. This method removes the instance from - * Sound management. It will be added again, if the sound re-plays. Note that this method is called from the - * instances themselves. - * @method _playFinished - * @param {AbstractSoundInstance} instance The instance that finished playback. - * @protected - * @static - */ - s._playFinished = function (instance) { - SoundChannel.remove(instance); - var index = createjs.indexOf(this._instances, instance); - if (index > -1) {this._instances.splice(index, 1);} // OJR this will always be > -1, there is no way for an instance to exist without being added to this._instances - }; - - createjs.Sound = Sound; - - /** - * An internal class that manages the number of active {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} instances for - * each sound type. This method is only used internally by the {{#crossLink "Sound"}}{{/crossLink}} class. - * - * The number of sounds is artificially limited by Sound in order to prevent over-saturation of a - * single sound, as well as to stay within hardware limitations, although the latter may disappear with better - * browser support. - * - * When a sound is played, this class ensures that there is an available instance, or interrupts an appropriate - * sound that is already playing. - * #class SoundChannel - * @param {String} src The source of the instances - * @param {Number} [max=1] The number of instances allowed - * @constructor - * @protected - */ - function SoundChannel(src, max) { - this.init(src, max); - } - - /* ------------ - Static API - ------------ */ - /** - * A hash of channel instances indexed by source. - * #property channels - * @type {Object} - * @static - */ - SoundChannel.channels = {}; - - /** - * Create a sound channel. Note that if the sound channel already exists, this will fail. - * #method create - * @param {String} src The source for the channel - * @param {Number} max The maximum amount this channel holds. The default is {{#crossLink "SoundChannel.maxDefault"}}{{/crossLink}}. - * @return {Boolean} If the channels were created. - * @static - */ - SoundChannel.create = function (src, max) { - var channel = SoundChannel.get(src); - if (channel == null) { - SoundChannel.channels[src] = new SoundChannel(src, max); - return true; - } - return false; - }; - /** - * Delete a sound channel, stop and delete all related instances. Note that if the sound channel does not exist, this will fail. - * #method remove - * @param {String} src The source for the channel - * @return {Boolean} If the channels were deleted. - * @static - */ - SoundChannel.removeSrc = function (src) { - var channel = SoundChannel.get(src); - if (channel == null) {return false;} - channel._removeAll(); // this stops and removes all active instances - delete(SoundChannel.channels[src]); - return true; - }; - /** - * Delete all sound channels, stop and delete all related instances. - * #method removeAll - * @static - */ - SoundChannel.removeAll = function () { - for(var channel in SoundChannel.channels) { - SoundChannel.channels[channel]._removeAll(); // this stops and removes all active instances - } - SoundChannel.channels = {}; - }; - /** - * Add an instance to a sound channel. - * #method add - * @param {AbstractSoundInstance} instance The instance to add to the channel - * @param {String} interrupt The interrupt value to use. Please see the {{#crossLink "Sound/play"}}{{/crossLink}} - * for details on interrupt modes. - * @return {Boolean} The success of the method call. If the channel is full, it will return false. - * @static - */ - SoundChannel.add = function (instance, interrupt) { - var channel = SoundChannel.get(instance.src); - if (channel == null) {return false;} - return channel._add(instance, interrupt); - }; - /** - * Remove an instance from the channel. - * #method remove - * @param {AbstractSoundInstance} instance The instance to remove from the channel - * @return The success of the method call. If there is no channel, it will return false. - * @static - */ - SoundChannel.remove = function (instance) { - var channel = SoundChannel.get(instance.src); - if (channel == null) {return false;} - channel._remove(instance); - return true; - }; - /** - * Get the maximum number of sounds you can have in a channel. - * #method maxPerChannel - * @return {Number} The maximum number of sounds you can have in a channel. - */ - SoundChannel.maxPerChannel = function () { - return p.maxDefault; - }; - /** - * Get a channel instance by its src. - * #method get - * @param {String} src The src to use to look up the channel - * @static - */ - SoundChannel.get = function (src) { - return SoundChannel.channels[src]; - }; - - var p = SoundChannel.prototype; - p.constructor = SoundChannel; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - - /** - * The source of the channel. - * #property src - * @type {String} - */ - p.src = null; - - /** - * The maximum number of instances in this channel. -1 indicates no limit - * #property max - * @type {Number} - */ - p.max = null; - - /** - * The default value to set for max, if it isn't passed in. Also used if -1 is passed. - * #property maxDefault - * @type {Number} - * @default 100 - * @since 0.4.0 - */ - p.maxDefault = 100; - - /** - * The current number of active instances. - * #property length - * @type {Number} - */ - p.length = 0; - - /** - * Initialize the channel. - * #method init - * @param {String} src The source of the channel - * @param {Number} max The maximum number of instances in the channel - * @protected - */ - p.init = function (src, max) { - this.src = src; - this.max = max || this.maxDefault; - if (this.max == -1) {this.max = this.maxDefault;} - this._instances = []; - }; - - /** - * Get an instance by index. - * #method get - * @param {Number} index The index to return. - * @return {AbstractSoundInstance} The AbstractSoundInstance at a specific instance. - */ - p._get = function (index) { - return this._instances[index]; - }; - - /** - * Add a new instance to the channel. - * #method add - * @param {AbstractSoundInstance} instance The instance to add. - * @return {Boolean} The success of the method call. If the channel is full, it will return false. - */ - p._add = function (instance, interrupt) { - if (!this._getSlot(interrupt, instance)) {return false;} - this._instances.push(instance); - this.length++; - return true; - }; - - /** - * Remove an instance from the channel, either when it has finished playing, or it has been interrupted. - * #method remove - * @param {AbstractSoundInstance} instance The instance to remove - * @return {Boolean} The success of the remove call. If the instance is not found in this channel, it will - * return false. - */ - p._remove = function (instance) { - var index = createjs.indexOf(this._instances, instance); - if (index == -1) {return false;} - this._instances.splice(index, 1); - this.length--; - return true; - }; - - /** - * Stop playback and remove all instances from the channel. Usually in response to a delete call. - * #method removeAll - */ - p._removeAll = function () { - // Note that stop() removes the item from the list - for (var i=this.length-1; i>=0; i--) { - this._instances[i].stop(); - } - }; - - /** - * Get an available slot depending on interrupt value and if slots are available. - * #method getSlot - * @param {String} interrupt The interrupt value to use. - * @param {AbstractSoundInstance} instance The sound instance that will go in the channel if successful. - * @return {Boolean} Determines if there is an available slot. Depending on the interrupt mode, if there are no slots, - * an existing AbstractSoundInstance may be interrupted. If there are no slots, this method returns false. - */ - p._getSlot = function (interrupt, instance) { - var target, replacement; - - if (interrupt != Sound.INTERRUPT_NONE) { - // First replacement candidate - replacement = this._get(0); - if (replacement == null) { - return true; - } - } - - for (var i = 0, l = this.max; i < l; i++) { - target = this._get(i); - - // Available Space - if (target == null) { - return true; - } - - // Audio is complete or not playing - if (target.playState == Sound.PLAY_FINISHED || - target.playState == Sound.PLAY_INTERRUPTED || - target.playState == Sound.PLAY_FAILED) { - replacement = target; - break; - } - - if (interrupt == Sound.INTERRUPT_NONE) { - continue; - } - - // Audio is a better candidate than the current target, according to playhead - if ((interrupt == Sound.INTERRUPT_EARLY && target.getPosition() < replacement.getPosition()) || - (interrupt == Sound.INTERRUPT_LATE && target.getPosition() > replacement.getPosition())) { - replacement = target; - } - } - - if (replacement != null) { - replacement._interrupt(); - this._remove(replacement); - return true; - } - return false; - }; - - p.toString = function () { - return "[Sound SoundChannel]"; - }; - // do not add SoundChannel to namespace - -}()); - -//############################################################################## -// AbstractSoundInstance.js -//############################################################################## - -this.createjs = this.createjs || {}; - -/** - * A AbstractSoundInstance is created when any calls to the Sound API method {{#crossLink "Sound/play"}}{{/crossLink}} or - * {{#crossLink "Sound/createInstance"}}{{/crossLink}} are made. The AbstractSoundInstance is returned by the active plugin - * for control by the user. - * - *

        Example

        - * - * var myInstance = createjs.Sound.play("myAssetPath/mySrcFile.mp3"); - * - * A number of additional parameters provide a quick way to determine how a sound is played. Please see the Sound - * API method {{#crossLink "Sound/play"}}{{/crossLink}} for a list of arguments. - * - * Once a AbstractSoundInstance is created, a reference can be stored that can be used to control the audio directly through - * the AbstractSoundInstance. If the reference is not stored, the AbstractSoundInstance will play out its audio (and any loops), and - * is then de-referenced from the {{#crossLink "Sound"}}{{/crossLink}} class so that it can be cleaned up. If audio - * playback has completed, a simple call to the {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}} instance method - * will rebuild the references the Sound class need to control it. - * - * var myInstance = createjs.Sound.play("myAssetPath/mySrcFile.mp3", {loop:2}); - * myInstance.on("loop", handleLoop); - * function handleLoop(event) { - * myInstance.volume = myInstance.volume * 0.5; - * } - * - * Events are dispatched from the instance to notify when the sound has completed, looped, or when playback fails - * - * var myInstance = createjs.Sound.play("myAssetPath/mySrcFile.mp3"); - * myInstance.on("complete", handleComplete); - * myInstance.on("loop", handleLoop); - * myInstance.on("failed", handleFailed); - * - * - * @class AbstractSoundInstance - * @param {String} src The path to and file name of the sound. - * @param {Number} startTime Audio sprite property used to apply an offset, in milliseconds. - * @param {Number} duration Audio sprite property used to set the time the clip plays for, in milliseconds. - * @param {Object} playbackResource Any resource needed by plugin to support audio playback. - * @extends EventDispatcher - * @constructor - */ - -(function () { - "use strict"; - - -// Constructor: - var AbstractSoundInstance = function (src, startTime, duration, playbackResource) { - this.EventDispatcher_constructor(); - - - // public properties: - /** - * The source of the sound. - * @property src - * @type {String} - * @default null - */ - this.src = src; - - /** - * The unique ID of the instance. This is set by {{#crossLink "Sound"}}{{/crossLink}}. - * @property uniqueId - * @type {String} | Number - * @default -1 - */ - this.uniqueId = -1; - - /** - * The play state of the sound. Play states are defined as constants on {{#crossLink "Sound"}}{{/crossLink}}. - * @property playState - * @type {String} - * @default null - */ - this.playState = null; - - /** - * A Timeout created by {{#crossLink "Sound"}}{{/crossLink}} when this AbstractSoundInstance is played with a delay. - * This allows AbstractSoundInstance to remove the delay if stop, pause, or cleanup are called before playback begins. - * @property delayTimeoutId - * @type {timeoutVariable} - * @default null - * @protected - * @since 0.4.0 - */ - this.delayTimeoutId = null; - // TODO consider moving delay into AbstractSoundInstance so it can be handled by plugins - - - // private properties - // Getter / Setter Properties - // OJR TODO find original reason that we didn't use defined functions. I think it was performance related - /** - * The volume of the sound, between 0 and 1. - * - * The actual output volume of a sound can be calculated using: - * myInstance.volume * createjs.Sound.getVolume(); - * - * @property volume - * @type {Number} - * @default 1 - */ - this._volume = 1; - Object.defineProperty(this, "volume", { - get: this.getVolume, - set: this.setVolume - }); - - /** - * The pan of the sound, between -1 (left) and 1 (right). Note that pan is not supported by HTML Audio. - * - *
        Note in WebAudioPlugin this only gives us the "x" value of what is actually 3D audio. - * - * @property pan - * @type {Number} - * @default 0 - */ - this._pan = 0; - Object.defineProperty(this, "pan", { - get: this.getPan, - set: this.setPan - }); - - /** - * Audio sprite property used to determine the starting offset. - * @property startTime - * @type {Number} - * @default 0 - * @since 0.6.1 - */ - this._startTime = Math.max(0, startTime || 0); - Object.defineProperty(this, "startTime", { - get: this.getStartTime, - set: this.setStartTime - }); - - /** - * Sets or gets the length of the audio clip, value is in milliseconds. - * - * @property duration - * @type {Number} - * @default 0 - * @since 0.6.0 - */ - this._duration = Math.max(0, duration || 0); - Object.defineProperty(this, "duration", { - get: this.getDuration, - set: this.setDuration - }); - - /** - * Object that holds plugin specific resource need for audio playback. - * This is set internally by the plugin. For example, WebAudioPlugin will set an array buffer, - * HTMLAudioPlugin will set a tag, FlashAudioPlugin will set a flash reference. - * - * @property playbackResource - * @type {Object} - * @default null - */ - this._playbackResource = null; - Object.defineProperty(this, "playbackResource", { - get: this.getPlaybackResource, - set: this.setPlaybackResource - }); - if(playbackResource !== false && playbackResource !== true) { this.setPlaybackResource(playbackResource); } - - /** - * The position of the playhead in milliseconds. This can be set while a sound is playing, paused, or stopped. - * - * @property position - * @type {Number} - * @default 0 - * @since 0.6.0 - */ - this._position = 0; - Object.defineProperty(this, "position", { - get: this.getPosition, - set: this.setPosition - }); - - /** - * The number of play loops remaining. Negative values will loop infinitely. - * - * @property loop - * @type {Number} - * @default 0 - * @public - * @since 0.6.0 - */ - this._loop = 0; - Object.defineProperty(this, "loop", { - get: this.getLoop, - set: this.setLoop - }); - - /** - * Mutes or unmutes the current audio instance. - * - * @property muted - * @type {Boolean} - * @default false - * @since 0.6.0 - */ - this._muted = false; - Object.defineProperty(this, "muted", { - get: this.getMuted, - set: this.setMuted - }); - - /** - * Pauses or resumes the current audio instance. - * - * @property paused - * @type {Boolean} - */ - this._paused = false; - Object.defineProperty(this, "paused", { - get: this.getPaused, - set: this.setPaused - }); - - - // Events - /** - * The event that is fired when playback has started successfully. - * @event succeeded - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.4.0 - */ - - /** - * The event that is fired when playback is interrupted. This happens when another sound with the same - * src property is played using an interrupt value that causes this instance to stop playing. - * @event interrupted - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.4.0 - */ - - /** - * The event that is fired when playback has failed. This happens when there are too many channels with the same - * src property already playing (and the interrupt value doesn't cause an interrupt of another instance), or - * the sound could not be played, perhaps due to a 404 error. - * @event failed - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.4.0 - */ - - /** - * The event that is fired when a sound has completed playing but has loops remaining. - * @event loop - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.4.0 - */ - - /** - * The event that is fired when playback completes. This means that the sound has finished playing in its - * entirety, including its loop iterations. - * @event complete - * @param {Object} target The object that dispatched the event. - * @param {String} type The event type. - * @since 0.4.0 - */ - }; - - var p = createjs.extend(AbstractSoundInstance, createjs.EventDispatcher); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// Public Methods: - /** - * Play an instance. This method is intended to be called on SoundInstances that already exist (created - * with the Sound API {{#crossLink "Sound/createInstance"}}{{/crossLink}} or {{#crossLink "Sound/play"}}{{/crossLink}}). - * - *

        Example

        - * - * var myInstance = createjs.Sound.createInstance(mySrc); - * myInstance.play({interrupt:createjs.Sound.INTERRUPT_ANY, loop:2, pan:0.5}); - * - * Note that if this sound is already playing, this call will still set the passed in parameters. - - * Parameters Deprecated
        - * The parameters for this method are deprecated in favor of a single parameter that is an Object or {{#crossLink "PlayPropsConfig"}}{{/crossLink}}. - * - * @method play - * @param {String | Object} [interrupt="none"|options] This parameter will be renamed playProps in the next release.
        - * This parameter can be an instance of {{#crossLink "PlayPropsConfig"}}{{/crossLink}} or an Object that contains any or all optional properties by name, - * including: interrupt, delay, offset, loop, volume, pan, startTime, and duration (see the above code sample). - *
        OR
        - * Deprecated How to interrupt any currently playing instances of audio with the same source, - * if the maximum number of instances of the sound are already playing. Values are defined as INTERRUPT_TYPE - * constants on the Sound class, with the default defined by {{#crossLink "Sound/defaultInterruptBehavior:property"}}{{/crossLink}}. - * @param {Number} [delay=0] Deprecated The amount of time to delay the start of audio playback, in milliseconds. - * @param {Number} [offset=0] Deprecated The offset from the start of the audio to begin playback, in milliseconds. - * @param {Number} [loop=0] Deprecated How many times the audio loops when it reaches the end of playback. The default is 0 (no - * loops), and -1 can be used for infinite playback. - * @param {Number} [volume=1] Deprecated The volume of the sound, between 0 and 1. Note that the master volume is applied - * against the individual volume. - * @param {Number} [pan=0] Deprecated The left-right pan of the sound (if supported), between -1 (left) and 1 (right). - * Note that pan is not supported for HTML Audio. - * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls. - */ - p.play = function (interrupt, delay, offset, loop, volume, pan) { - var playProps; - if (interrupt instanceof Object || interrupt instanceof createjs.PlayPropsConfig) { - playProps = createjs.PlayPropsConfig.create(interrupt); - } else { - playProps = createjs.PlayPropsConfig.create({interrupt:interrupt, delay:delay, offset:offset, loop:loop, volume:volume, pan:pan}); - } - - if (this.playState == createjs.Sound.PLAY_SUCCEEDED) { - this.applyPlayProps(playProps); - if (this._paused) { this.setPaused(false); } - return; - } - this._cleanUp(); - createjs.Sound._playInstance(this, playProps); // make this an event dispatch?? - return this; - }; - - /** - * Stop playback of the instance. Stopped sounds will reset their position to 0, and calls to {{#crossLink "AbstractSoundInstance/resume"}}{{/crossLink}} - * will fail. To start playback again, call {{#crossLink "AbstractSoundInstance/play"}}{{/crossLink}}. - * - * If you don't want to lose your position use yourSoundInstance.paused = true instead. {{#crossLink "AbstractSoundInstance/paused"}}{{/crossLink}}. - * - *

        Example

        - * - * myInstance.stop(); - * - * @method stop - * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls. - */ - p.stop = function () { - this._position = 0; - this._paused = false; - this._handleStop(); - this._cleanUp(); - this.playState = createjs.Sound.PLAY_FINISHED; - return this; - }; - - /** - * Remove all external references and resources from AbstractSoundInstance. Note this is irreversible and AbstractSoundInstance will no longer work - * @method destroy - * @since 0.6.0 - */ - p.destroy = function() { - this._cleanUp(); - this.src = null; - this.playbackResource = null; - - this.removeAllEventListeners(); - }; - - /** - * Takes an PlayPropsConfig or Object with the same properties and sets them on this instance. - * @method applyPlayProps - * @param {PlayPropsConfig | Object} playProps A PlayPropsConfig or object containing the same properties. - * @since 0.6.1 - * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls. - */ - p.applyPlayProps = function(playProps) { - if (playProps.offset != null) { this.setPosition(playProps.offset) } - if (playProps.loop != null) { this.setLoop(playProps.loop); } - if (playProps.volume != null) { this.setVolume(playProps.volume); } - if (playProps.pan != null) { this.setPan(playProps.pan); } - if (playProps.startTime != null) { - this.setStartTime(playProps.startTime); - this.setDuration(playProps.duration); - } - return this; - }; - - p.toString = function () { - return "[AbstractSoundInstance]"; - }; - -// get/set methods that allow support for IE8 - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/paused:property"}}{{/crossLink}} directly as a property, - * - * @deprecated - * @method getPaused - * @returns {boolean} If the instance is currently paused - * @since 0.6.0 - */ - p.getPaused = function() { - return this._paused; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/paused:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method setPaused - * @param {boolean} value - * @since 0.6.0 - * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls. - */ - p.setPaused = function (value) { - if ((value !== true && value !== false) || this._paused == value) {return;} - if (value == true && this.playState != createjs.Sound.PLAY_SUCCEEDED) {return;} - this._paused = value; - if(value) { - this._pause(); - } else { - this._resume(); - } - clearTimeout(this.delayTimeoutId); - return this; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/volume:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method setVolume - * @param {Number} value The volume to set, between 0 and 1. - * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls. - */ - p.setVolume = function (value) { - if (value == this._volume) { return this; } - this._volume = Math.max(0, Math.min(1, value)); - if (!this._muted) { - this._updateVolume(); - } - return this; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/volume:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method getVolume - * @return {Number} The current volume of the sound instance. - */ - p.getVolume = function () { - return this._volume; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/muted:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method setMuted - * @param {Boolean} value If the sound should be muted. - * @return {AbstractSoundInstance} A reference to itself, intended for chaining calls. - * @since 0.6.0 - */ - p.setMuted = function (value) { - if (value !== true && value !== false) {return;} - this._muted = value; - this._updateVolume(); - return this; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/muted:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method getMuted - * @return {Boolean} If the sound is muted. - * @since 0.6.0 - */ - p.getMuted = function () { - return this._muted; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/pan:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method setPan - * @param {Number} value The pan value, between -1 (left) and 1 (right). - * @return {AbstractSoundInstance} Returns reference to itself for chaining calls - */ - p.setPan = function (value) { - if(value == this._pan) { return this; } - this._pan = Math.max(-1, Math.min(1, value)); - this._updatePan(); - return this; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/pan:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method getPan - * @return {Number} The value of the pan, between -1 (left) and 1 (right). - */ - p.getPan = function () { - return this._pan; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/position:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method getPosition - * @return {Number} The position of the playhead in the sound, in milliseconds. - */ - p.getPosition = function () { - if (!this._paused && this.playState == createjs.Sound.PLAY_SUCCEEDED) { - this._position = this._calculateCurrentPosition(); - } - return this._position; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/position:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method setPosition - * @param {Number} value The position to place the playhead, in milliseconds. - * @return {AbstractSoundInstance} Returns reference to itself for chaining calls - */ - p.setPosition = function (value) { - this._position = Math.max(0, value); - if (this.playState == createjs.Sound.PLAY_SUCCEEDED) { - this._updatePosition(); - } - return this; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/startTime:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method getStartTime - * @return {Number} The startTime of the sound instance in milliseconds. - */ - p.getStartTime = function () { - return this._startTime; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/startTime:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method setStartTime - * @param {number} value The new startTime time in milli seconds. - * @return {AbstractSoundInstance} Returns reference to itself for chaining calls - */ - p.setStartTime = function (value) { - if (value == this._startTime) { return this; } - this._startTime = Math.max(0, value || 0); - this._updateStartTime(); - return this; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/duration:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method getDuration - * @return {Number} The duration of the sound instance in milliseconds. - */ - p.getDuration = function () { - return this._duration; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/duration:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method setDuration - * @param {number} value The new duration time in milli seconds. - * @return {AbstractSoundInstance} Returns reference to itself for chaining calls - * @since 0.6.0 - */ - p.setDuration = function (value) { - if (value == this._duration) { return this; } - this._duration = Math.max(0, value || 0); - this._updateDuration(); - return this; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/playbackResource:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method setPlayback - * @param {Object} value The new playback resource. - * @return {AbstractSoundInstance} Returns reference to itself for chaining calls - * @since 0.6.0 - **/ - p.setPlaybackResource = function (value) { - this._playbackResource = value; - if (this._duration == 0) { this._setDurationFromSource(); } - return this; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/playbackResource:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method setPlayback - * @param {Object} value The new playback resource. - * @return {Object} playback resource used for playing audio - * @since 0.6.0 - **/ - p.getPlaybackResource = function () { - return this._playbackResource; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/loop:property"}}{{/crossLink}} directly as a property - * - * @deprecated - * @method getLoop - * @return {number} - * @since 0.6.0 - **/ - p.getLoop = function () { - return this._loop; - }; - - /** - * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/loop:property"}}{{/crossLink}} directly as a property, - * - * @deprecated - * @method setLoop - * @param {number} value The number of times to loop after play. - * @since 0.6.0 - */ - p.setLoop = function (value) { - if(this._playbackResource != null) { - // remove looping - if (this._loop != 0 && value == 0) { - this._removeLooping(value); - } - // add looping - else if (this._loop == 0 && value != 0) { - this._addLooping(value); - } - } - this._loop = value; - }; - - -// Private Methods: - /** - * A helper method that dispatches all events for AbstractSoundInstance. - * @method _sendEvent - * @param {String} type The event type - * @protected - */ - p._sendEvent = function (type) { - var event = new createjs.Event(type); - this.dispatchEvent(event); - }; - - /** - * Clean up the instance. Remove references and clean up any additional properties such as timers. - * @method _cleanUp - * @protected - */ - p._cleanUp = function () { - clearTimeout(this.delayTimeoutId); // clear timeout that plays delayed sound - this._handleCleanUp(); - this._paused = false; - - createjs.Sound._playFinished(this); // TODO change to an event - }; - - /** - * The sound has been interrupted. - * @method _interrupt - * @protected - */ - p._interrupt = function () { - this._cleanUp(); - this.playState = createjs.Sound.PLAY_INTERRUPTED; - this._sendEvent("interrupted"); - }; - - /** - * Called by the Sound class when the audio is ready to play (delay has completed). Starts sound playing if the - * src is loaded, otherwise playback will fail. - * @method _beginPlaying - * @param {PlayPropsConfig} playProps A PlayPropsConfig object. - * @return {Boolean} If playback succeeded. - * @protected - */ - // OJR FlashAudioSoundInstance overwrites - p._beginPlaying = function (playProps) { - this.setPosition(playProps.offset); - this.setLoop(playProps.loop); - this.setVolume(playProps.volume); - this.setPan(playProps.pan); - if (playProps.startTime != null) { - this.setStartTime(playProps.startTime); - this.setDuration(playProps.duration); - } - - if (this._playbackResource != null && this._position < this._duration) { - this._paused = false; - this._handleSoundReady(); - this.playState = createjs.Sound.PLAY_SUCCEEDED; - this._sendEvent("succeeded"); - return true; - } else { - this._playFailed(); - return false; - } - }; - - /** - * Play has failed, which can happen for a variety of reasons. - * Cleans up instance and dispatches failed event - * @method _playFailed - * @private - */ - p._playFailed = function () { - this._cleanUp(); - this.playState = createjs.Sound.PLAY_FAILED; - this._sendEvent("failed"); - }; - - /** - * Audio has finished playing. Manually loop it if required. - * @method _handleSoundComplete - * @param event - * @protected - */ - p._handleSoundComplete = function (event) { - this._position = 0; // have to set this as it can be set by pause during playback - - if (this._loop != 0) { - this._loop--; // NOTE this introduces a theoretical limit on loops = float max size x 2 - 1 - this._handleLoop(); - this._sendEvent("loop"); - return; - } - - this._cleanUp(); - this.playState = createjs.Sound.PLAY_FINISHED; - this._sendEvent("complete"); - }; - -// Plugin specific code - /** - * Handles starting playback when the sound is ready for playing. - * @method _handleSoundReady - * @protected - */ - p._handleSoundReady = function () { - // plugin specific code - }; - - /** - * Internal function used to update the volume based on the instance volume, master volume, instance mute value, - * and master mute value. - * @method _updateVolume - * @protected - */ - p._updateVolume = function () { - // plugin specific code - }; - - /** - * Internal function used to update the pan - * @method _updatePan - * @protected - * @since 0.6.0 - */ - p._updatePan = function () { - // plugin specific code - }; - - /** - * Internal function used to update the startTime of the audio. - * @method _updateStartTime - * @protected - * @since 0.6.1 - */ - p._updateStartTime = function () { - // plugin specific code - }; - - /** - * Internal function used to update the duration of the audio. - * @method _updateDuration - * @protected - * @since 0.6.0 - */ - p._updateDuration = function () { - // plugin specific code - }; - - /** - * Internal function used to get the duration of the audio from the source we'll be playing. - * @method _updateDuration - * @protected - * @since 0.6.0 - */ - p._setDurationFromSource = function () { - // plugin specific code - }; - - /** - * Internal function that calculates the current position of the playhead and sets this._position to that value - * @method _calculateCurrentPosition - * @protected - * @since 0.6.0 - */ - p._calculateCurrentPosition = function () { - // plugin specific code that sets this.position - }; - - /** - * Internal function used to update the position of the playhead. - * @method _updatePosition - * @protected - * @since 0.6.0 - */ - p._updatePosition = function () { - // plugin specific code - }; - - /** - * Internal function called when looping is removed during playback. - * @method _removeLooping - * @param {number} value The number of times to loop after play. - * @protected - * @since 0.6.0 - */ - p._removeLooping = function (value) { - // plugin specific code - }; - - /** - * Internal function called when looping is added during playback. - * @method _addLooping - * @param {number} value The number of times to loop after play. - * @protected - * @since 0.6.0 - */ - p._addLooping = function (value) { - // plugin specific code - }; - - /** - * Internal function called when pausing playback - * @method _pause - * @protected - * @since 0.6.0 - */ - p._pause = function () { - // plugin specific code - }; - - /** - * Internal function called when resuming playback - * @method _resume - * @protected - * @since 0.6.0 - */ - p._resume = function () { - // plugin specific code - }; - - /** - * Internal function called when stopping playback - * @method _handleStop - * @protected - * @since 0.6.0 - */ - p._handleStop = function() { - // plugin specific code - }; - - /** - * Internal function called when AbstractSoundInstance is being cleaned up - * @method _handleCleanUp - * @protected - * @since 0.6.0 - */ - p._handleCleanUp = function() { - // plugin specific code - }; - - /** - * Internal function called when AbstractSoundInstance has played to end and is looping - * @method _handleLoop - * @protected - * @since 0.6.0 - */ - p._handleLoop = function () { - // plugin specific code - }; - - createjs.AbstractSoundInstance = createjs.promote(AbstractSoundInstance, "EventDispatcher"); - createjs.DefaultSoundInstance = createjs.AbstractSoundInstance; // used when no plugin is supported -}()); - -//############################################################################## -// AbstractPlugin.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - -// constructor: - /** - * A default plugin class used as a base for all other plugins. - * @class AbstractPlugin - * @constructor - * @since 0.6.0 - */ - - var AbstractPlugin = function () { - // private properties: - /** - * The capabilities of the plugin. - * method and is used internally. - * @property _capabilities - * @type {Object} - * @default null - * @protected - * @static - */ - this._capabilities = null; - - /** - * Object hash indexed by the source URI of all created loaders, used to properly destroy them if sources are removed. - * @type {Object} - * @protected - */ - this._loaders = {}; - - /** - * Object hash indexed by the source URI of each file to indicate if an audio source has begun loading, - * is currently loading, or has completed loading. Can be used to store non boolean data after loading - * is complete (for example arrayBuffers for web audio). - * @property _audioSources - * @type {Object} - * @protected - */ - this._audioSources = {}; - - /** - * Object hash indexed by the source URI of all created SoundInstances, updates the playbackResource if it loads after they are created, - * and properly destroy them if sources are removed - * @type {Object} - * @protected - */ - this._soundInstances = {}; - - /** - * The internal master volume value of the plugin. - * @property _volume - * @type {Number} - * @default 1 - * @protected - */ - this._volume = 1; - - /** - * A reference to a loader class used by a plugin that must be set. - * @type {Object} - * @protected - */ - this._loaderClass; - - /** - * A reference to an AbstractSoundInstance class used by a plugin that must be set. - * @type {Object} - * @protected; - */ - this._soundInstanceClass; - }; - var p = AbstractPlugin.prototype; - - /** - * REMOVED. Removed in favor of using `MySuperClass_constructor`. - * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} - * for details. - * - * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. - * - * @method initialize - * @protected - * @deprecated - */ - // p.initialize = function() {}; // searchable for devs wondering where it is. - - -// Static Properties: -// NOTE THESE PROPERTIES NEED TO BE ADDED TO EACH PLUGIN - /** - * The capabilities of the plugin. This is generated via the _generateCapabilities method and is used internally. - * @property _capabilities - * @type {Object} - * @default null - * @protected - * @static - */ - AbstractPlugin._capabilities = null; - - /** - * Determine if the plugin can be used in the current browser/OS. - * @method isSupported - * @return {Boolean} If the plugin can be initialized. - * @static - */ - AbstractPlugin.isSupported = function () { - return true; - }; - - -// public methods: - /** - * Pre-register a sound for preloading and setup. This is called by {{#crossLink "Sound"}}{{/crossLink}}. - * Note all plugins provide a Loader instance, which PreloadJS - * can use to assist with preloading. - * @method register - * @param {String} loadItem An Object containing the source of the audio - * Note that not every plugin will manage this value. - * @return {Object} A result object, containing a "tag" for preloading purposes. - */ - p.register = function (loadItem) { - var loader = this._loaders[loadItem.src]; - if(loader && !loader.canceled) {return this._loaders[loadItem.src];} // already loading/loaded this, so don't load twice - // OJR potential issue that we won't be firing loaded event, might need to trigger if this is already loaded? - this._audioSources[loadItem.src] = true; - this._soundInstances[loadItem.src] = []; - loader = new this._loaderClass(loadItem); - loader.on("complete", this._handlePreloadComplete, this); - this._loaders[loadItem.src] = loader; - return loader; - }; - - // note sound calls register before calling preload - /** - * Internally preload a sound. - * @method preload - * @param {Loader} loader The sound URI to load. - */ - p.preload = function (loader) { - loader.on("error", this._handlePreloadError, this); - loader.load(); - }; - - /** - * Checks if preloading has started for a specific source. If the source is found, we can assume it is loading, - * or has already finished loading. - * @method isPreloadStarted - * @param {String} src The sound URI to check. - * @return {Boolean} - */ - p.isPreloadStarted = function (src) { - return (this._audioSources[src] != null); - }; - - /** - * Checks if preloading has finished for a specific source. - * @method isPreloadComplete - * @param {String} src The sound URI to load. - * @return {Boolean} - */ - p.isPreloadComplete = function (src) { - return (!(this._audioSources[src] == null || this._audioSources[src] == true)); - }; - - /** - * Remove a sound added using {{#crossLink "WebAudioPlugin/register"}}{{/crossLink}}. Note this does not cancel a preload. - * @method removeSound - * @param {String} src The sound URI to unload. - */ - p.removeSound = function (src) { - if (!this._soundInstances[src]) { return; } - for (var i = this._soundInstances[src].length; i--; ) { - var item = this._soundInstances[src][i]; - item.destroy(); - } - delete(this._soundInstances[src]); - delete(this._audioSources[src]); - if(this._loaders[src]) { this._loaders[src].destroy(); } - delete(this._loaders[src]); - }; - - /** - * Remove all sounds added using {{#crossLink "WebAudioPlugin/register"}}{{/crossLink}}. Note this does not cancel a preload. - * @method removeAllSounds - * @param {String} src The sound URI to unload. - */ - p.removeAllSounds = function () { - for(var key in this._audioSources) { - this.removeSound(key); - } - }; - - /** - * Create a sound instance. If the sound has not been preloaded, it is internally preloaded here. - * @method create - * @param {String} src The sound source to use. - * @param {Number} startTime Audio sprite property used to apply an offset, in milliseconds. - * @param {Number} duration Audio sprite property used to set the time the clip plays for, in milliseconds. - * @return {AbstractSoundInstance} A sound instance for playback and control. - */ - p.create = function (src, startTime, duration) { - if (!this.isPreloadStarted(src)) { - this.preload(this.register(src)); - } - var si = new this._soundInstanceClass(src, startTime, duration, this._audioSources[src]); - this._soundInstances[src].push(si); - return si; - }; - - // if a plugin does not support volume and mute, it should set these to null - /** - * Set the master volume of the plugin, which affects all SoundInstances. - * @method setVolume - * @param {Number} value The volume to set, between 0 and 1. - * @return {Boolean} If the plugin processes the setVolume call (true). The Sound class will affect all the - * instances manually otherwise. - */ - p.setVolume = function (value) { - this._volume = value; - this._updateVolume(); - return true; - }; - - /** - * Get the master volume of the plugin, which affects all SoundInstances. - * @method getVolume - * @return {Number} The volume level, between 0 and 1. - */ - p.getVolume = function () { - return this._volume; - }; - - /** - * Mute all sounds via the plugin. - * @method setMute - * @param {Boolean} value If all sound should be muted or not. Note that plugin-level muting just looks up - * the mute value of Sound {{#crossLink "Sound/getMute"}}{{/crossLink}}, so this property is not used here. - * @return {Boolean} If the mute call succeeds. - */ - p.setMute = function (value) { - this._updateVolume(); - return true; - }; - - // plugins should overwrite this method - p.toString = function () { - return "[AbstractPlugin]"; - }; - - -// private methods: - /** - * Handles internal preload completion. - * @method _handlePreloadComplete - * @protected - */ - p._handlePreloadComplete = function (event) { - var src = event.target.getItem().src; - this._audioSources[src] = event.result; - for (var i = 0, l = this._soundInstances[src].length; i < l; i++) { - var item = this._soundInstances[src][i]; - item.setPlaybackResource(this._audioSources[src]); - // ToDo consider adding play call here if playstate == playfailed - } - }; - - /** - * Handles internal preload erros - * @method _handlePreloadError - * @param event - * @protected - */ - p._handlePreloadError = function(event) { - //delete(this._audioSources[src]); - }; - - /** - * Set the gain value for master audio. Should not be called externally. - * @method _updateVolume - * @protected - */ - p._updateVolume = function () { - // Plugin Specific code - }; - - createjs.AbstractPlugin = AbstractPlugin; -}()); - -//############################################################################## -// WebAudioLoader.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - /** - * Loader provides a mechanism to preload Web Audio content via PreloadJS or internally. Instances are returned to - * the preloader, and the load method is called when the asset needs to be requested. - * - * @class WebAudioLoader - * @param {String} loadItem The item to be loaded - * @extends XHRRequest - * @protected - */ - function Loader(loadItem) { - this.AbstractLoader_constructor(loadItem, true, createjs.AbstractLoader.SOUND); - - }; - var p = createjs.extend(Loader, createjs.AbstractLoader); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - - /** - * web audio context required for decoding audio - * @property context - * @type {AudioContext} - * @static - */ - Loader.context = null; - - -// public methods - p.toString = function () { - return "[WebAudioLoader]"; - }; - - -// private methods - p._createRequest = function() { - this._request = new createjs.XHRRequest(this._item, false); - this._request.setResponseType("arraybuffer"); - }; - - p._sendComplete = function (event) { - // OJR we leave this wrapped in Loader because we need to reference src and the handler only receives a single argument, the decodedAudio - Loader.context.decodeAudioData(this._rawResult, - createjs.proxy(this._handleAudioDecoded, this), - createjs.proxy(this._sendError, this)); - }; - - - /** - * The audio has been decoded. - * @method handleAudioDecoded - * @param decoded - * @protected - */ - p._handleAudioDecoded = function (decodedAudio) { - this._result = decodedAudio; - this.AbstractLoader__sendComplete(); - }; - - createjs.WebAudioLoader = createjs.promote(Loader, "AbstractLoader"); -}()); - -//############################################################################## -// WebAudioSoundInstance.js -//############################################################################## - -this.createjs = this.createjs || {}; - -/** - * WebAudioSoundInstance extends the base api of {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} and is used by - * {{#crossLink "WebAudioPlugin"}}{{/crossLink}}. - * - * WebAudioSoundInstance exposes audioNodes for advanced users. - * - * @param {String} src The path to and file name of the sound. - * @param {Number} startTime Audio sprite property used to apply an offset, in milliseconds. - * @param {Number} duration Audio sprite property used to set the time the clip plays for, in milliseconds. - * @param {Object} playbackResource Any resource needed by plugin to support audio playback. - * @class WebAudioSoundInstance - * @extends AbstractSoundInstance - * @constructor - */ -(function () { - "use strict"; - - function WebAudioSoundInstance(src, startTime, duration, playbackResource) { - this.AbstractSoundInstance_constructor(src, startTime, duration, playbackResource); - - -// public properties - /** - * NOTE this is only intended for use by advanced users. - *
        GainNode for controlling WebAudioSoundInstance volume. Connected to the {{#crossLink "WebAudioSoundInstance/destinationNode:property"}}{{/crossLink}}. - * @property gainNode - * @type {AudioGainNode} - * @since 0.4.0 - * - */ - this.gainNode = s.context.createGain(); - - /** - * NOTE this is only intended for use by advanced users. - *
        A panNode allowing left and right audio channel panning only. Connected to WebAudioSoundInstance {{#crossLink "WebAudioSoundInstance/gainNode:property"}}{{/crossLink}}. - * @property panNode - * @type {AudioPannerNode} - * @since 0.4.0 - */ - this.panNode = s.context.createPanner(); - this.panNode.panningModel = s._panningModel; - this.panNode.connect(this.gainNode); - this._updatePan(); - - /** - * NOTE this is only intended for use by advanced users. - *
        sourceNode is the audio source. Connected to WebAudioSoundInstance {{#crossLink "WebAudioSoundInstance/panNode:property"}}{{/crossLink}}. - * @property sourceNode - * @type {AudioNode} - * @since 0.4.0 - * - */ - this.sourceNode = null; - - -// private properties - /** - * Timeout that is created internally to handle sound playing to completion. - * Stored so we can remove it when stop, pause, or cleanup are called - * @property _soundCompleteTimeout - * @type {timeoutVariable} - * @default null - * @protected - * @since 0.4.0 - */ - this._soundCompleteTimeout = null; - - /** - * NOTE this is only intended for use by very advanced users. - * _sourceNodeNext is the audio source for the next loop, inserted in a look ahead approach to allow for smooth - * looping. Connected to {{#crossLink "WebAudioSoundInstance/gainNode:property"}}{{/crossLink}}. - * @property _sourceNodeNext - * @type {AudioNode} - * @default null - * @protected - * @since 0.4.1 - * - */ - this._sourceNodeNext = null; - - /** - * Time audio started playback, in seconds. Used to handle set position, get position, and resuming from paused. - * @property _playbackStartTime - * @type {Number} - * @default 0 - * @protected - * @since 0.4.0 - */ - this._playbackStartTime = 0; - - // Proxies, make removing listeners easier. - this._endedHandler = createjs.proxy(this._handleSoundComplete, this); - }; - var p = createjs.extend(WebAudioSoundInstance, createjs.AbstractSoundInstance); - var s = WebAudioSoundInstance; - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - - /** - * Note this is only intended for use by advanced users. - *
        Audio context used to create nodes. This is and needs to be the same context used by {{#crossLink "WebAudioPlugin"}}{{/crossLink}}. - * @property context - * @type {AudioContext} - * @static - * @since 0.6.0 - */ - s.context = null; - - /** - * Note this is only intended for use by advanced users. - *
        The scratch buffer that will be assigned to the buffer property of a source node on close. - * This is and should be the same scratch buffer referenced by {{#crossLink "WebAudioPlugin"}}{{/crossLink}}. - * @property _scratchBuffer - * @type {AudioBufferSourceNode} - * @static - */ - s._scratchBuffer = null; - - /** - * Note this is only intended for use by advanced users. - *
        Audio node from WebAudioPlugin that sequences to context.destination - * @property destinationNode - * @type {AudioNode} - * @static - * @since 0.6.0 - */ - s.destinationNode = null; - - /** - * Value to set panning model to equal power for WebAudioSoundInstance. Can be "equalpower" or 0 depending on browser implementation. - * @property _panningModel - * @type {Number / String} - * @protected - * @static - * @since 0.6.0 - */ - s._panningModel = "equalpower"; - - -// Public methods - p.destroy = function() { - this.AbstractSoundInstance_destroy(); - - this.panNode.disconnect(0); - this.panNode = null; - this.gainNode.disconnect(0); - this.gainNode = null; - }; - - p.toString = function () { - return "[WebAudioSoundInstance]"; - }; - - -// Private Methods - p._updatePan = function() { - this.panNode.setPosition(this._pan, 0, -0.5); - // z need to be -0.5 otherwise the sound only plays in left, right, or center - }; - - p._removeLooping = function(value) { - this._sourceNodeNext = this._cleanUpAudioNode(this._sourceNodeNext); - }; - - p._addLooping = function(value) { - if (this.playState != createjs.Sound.PLAY_SUCCEEDED) { return; } - this._sourceNodeNext = this._createAndPlayAudioNode(this._playbackStartTime, 0); - }; - - p._setDurationFromSource = function () { - this._duration = this.playbackResource.duration * 1000; - }; - - p._handleCleanUp = function () { - if (this.sourceNode && this.playState == createjs.Sound.PLAY_SUCCEEDED) { - this.sourceNode = this._cleanUpAudioNode(this.sourceNode); - this._sourceNodeNext = this._cleanUpAudioNode(this._sourceNodeNext); - } - - if (this.gainNode.numberOfOutputs != 0) {this.gainNode.disconnect(0);} - // OJR there appears to be a bug that this doesn't always work in webkit (Chrome and Safari). According to the documentation, this should work. - - clearTimeout(this._soundCompleteTimeout); - - this._playbackStartTime = 0; // This is used by getPosition - }; - - /** - * Turn off and disconnect an audioNode, then set reference to null to release it for garbage collection - * @method _cleanUpAudioNode - * @param audioNode - * @return {audioNode} - * @protected - * @since 0.4.1 - */ - p._cleanUpAudioNode = function(audioNode) { - if(audioNode) { - audioNode.stop(0); - audioNode.disconnect(0); - // necessary to prevent leak on iOS Safari 7-9. will throw in almost all other - // browser implementations. - try { audioNode.buffer = s._scratchBuffer; } catch(e) {} - audioNode = null; - } - return audioNode; - }; - - p._handleSoundReady = function (event) { - this.gainNode.connect(s.destinationNode); // this line can cause a memory leak. Nodes need to be disconnected from the audioDestination or any sequence that leads to it. - - var dur = this._duration * 0.001; - var pos = this._position * 0.001; - if (pos > dur) {pos = dur;} - this.sourceNode = this._createAndPlayAudioNode((s.context.currentTime - dur), pos); - this._playbackStartTime = this.sourceNode.startTime - pos; - - this._soundCompleteTimeout = setTimeout(this._endedHandler, (dur - pos) * 1000); - - if(this._loop != 0) { - this._sourceNodeNext = this._createAndPlayAudioNode(this._playbackStartTime, 0); - } - }; - - /** - * Creates an audio node using the current src and context, connects it to the gain node, and starts playback. - * @method _createAndPlayAudioNode - * @param {Number} startTime The time to add this to the web audio context, in seconds. - * @param {Number} offset The amount of time into the src audio to start playback, in seconds. - * @return {audioNode} - * @protected - * @since 0.4.1 - */ - p._createAndPlayAudioNode = function(startTime, offset) { - var audioNode = s.context.createBufferSource(); - audioNode.buffer = this.playbackResource; - audioNode.connect(this.panNode); - var dur = this._duration * 0.001; - audioNode.startTime = startTime + dur; - audioNode.start(audioNode.startTime, offset+(this._startTime*0.001), dur - offset); - return audioNode; - }; - - p._pause = function () { - this._position = (s.context.currentTime - this._playbackStartTime) * 1000; // * 1000 to give milliseconds, lets us restart at same point - this.sourceNode = this._cleanUpAudioNode(this.sourceNode); - this._sourceNodeNext = this._cleanUpAudioNode(this._sourceNodeNext); - - if (this.gainNode.numberOfOutputs != 0) {this.gainNode.disconnect(0);} - - clearTimeout(this._soundCompleteTimeout); - }; - - p._resume = function () { - this._handleSoundReady(); - }; - - /* - p._handleStop = function () { - // web audio does not need to do anything extra - }; - */ - - p._updateVolume = function () { - var newVolume = this._muted ? 0 : this._volume; - if (newVolume != this.gainNode.gain.value) { - this.gainNode.gain.value = newVolume; - } - }; - - p._calculateCurrentPosition = function () { - return ((s.context.currentTime - this._playbackStartTime) * 1000); // pos in seconds * 1000 to give milliseconds - }; - - p._updatePosition = function () { - this.sourceNode = this._cleanUpAudioNode(this.sourceNode); - this._sourceNodeNext = this._cleanUpAudioNode(this._sourceNodeNext); - clearTimeout(this._soundCompleteTimeout); - - if (!this._paused) {this._handleSoundReady();} - }; - - // OJR we are using a look ahead approach to ensure smooth looping. - // We add _sourceNodeNext to the audio context so that it starts playing even if this callback is delayed. - // This technique is described here: http://www.html5rocks.com/en/tutorials/audio/scheduling/ - // NOTE the cost of this is that our audio loop may not always match the loop event timing precisely. - p._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); - }; - - p._updateDuration = function () { - if(this.playState == createjs.Sound.PLAY_SUCCEEDED) { - this._pause(); - this._resume(); - } - }; - - createjs.WebAudioSoundInstance = createjs.promote(WebAudioSoundInstance, "AbstractSoundInstance"); -}()); - -//############################################################################## -// WebAudioPlugin.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - - "use strict"; - - /** - * Play sounds using Web Audio in the browser. The WebAudioPlugin is currently the default plugin, and will be used - * anywhere that it is supported. To change plugin priority, check out the Sound API - * {{#crossLink "Sound/registerPlugins"}}{{/crossLink}} method. - - *

        Known Browser and OS issues for Web Audio

        - * Firefox 25 - *
      • - * mp3 audio files do not load properly on all windows machines, reported here. - *
        For this reason it is recommended to pass another FireFox-supported type (i.e. ogg) as the default - * extension, until this bug is resolved - *
      • - * - * Webkit (Chrome and Safari) - *
      • - * AudioNode.disconnect does not always seem to work. This can cause the file size to grow over time if you - * are playing a lot of audio files. - *
      • - * - * iOS 6 limitations - *
          - *
        • - * Sound is initially muted and will only unmute through play being called inside a user initiated event - * (touch/click). Please read the mobile playback notes in the the {{#crossLink "Sound"}}{{/crossLink}} - * class for a full overview of the limitations, and how to get around them. - *
        • - *
        • - * A bug exists that will distort un-cached audio when a video element is present in the DOM. You can avoid - * this bug by ensuring the audio and video audio share the same sample rate. - *
        • - *
        - * @class WebAudioPlugin - * @extends AbstractPlugin - * @constructor - * @since 0.4.0 - */ - function WebAudioPlugin() { - this.AbstractPlugin_constructor(); - - -// Private Properties - /** - * Value to set panning model to equal power for WebAudioSoundInstance. Can be "equalpower" or 0 depending on browser implementation. - * @property _panningModel - * @type {Number / String} - * @protected - */ - this._panningModel = s._panningModel;; - - /** - * The web audio context, which WebAudio uses to play audio. All nodes that interact with the WebAudioPlugin - * need to be created within this context. - * @property context - * @type {AudioContext} - */ - this.context = s.context; - - /** - * A DynamicsCompressorNode, which is used to improve sound quality and prevent audio distortion. - * It is connected to context.destination. - * - * Can be accessed by advanced users through createjs.Sound.activePlugin.dynamicsCompressorNode. - * @property dynamicsCompressorNode - * @type {AudioNode} - */ - this.dynamicsCompressorNode = this.context.createDynamicsCompressor(); - this.dynamicsCompressorNode.connect(this.context.destination); - - /** - * A GainNode for controlling master volume. It is connected to {{#crossLink "WebAudioPlugin/dynamicsCompressorNode:property"}}{{/crossLink}}. - * - * Can be accessed by advanced users through createjs.Sound.activePlugin.gainNode. - * @property gainNode - * @type {AudioGainNode} - */ - this.gainNode = this.context.createGain(); - this.gainNode.connect(this.dynamicsCompressorNode); - createjs.WebAudioSoundInstance.destinationNode = this.gainNode; - - this._capabilities = s._capabilities; - - this._loaderClass = createjs.WebAudioLoader; - this._soundInstanceClass = createjs.WebAudioSoundInstance; - - this._addPropsToClasses(); - } - var p = createjs.extend(WebAudioPlugin, createjs.AbstractPlugin); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// Static Properties - var s = WebAudioPlugin; - /** - * The capabilities of the plugin. This is generated via the {{#crossLink "WebAudioPlugin/_generateCapabilities:method"}}{{/crossLink}} - * method and is used internally. - * @property _capabilities - * @type {Object} - * @default null - * @protected - * @static - */ - s._capabilities = null; - - /** - * Value to set panning model to equal power for WebAudioSoundInstance. Can be "equalpower" or 0 depending on browser implementation. - * @property _panningModel - * @type {Number / String} - * @protected - * @static - */ - s._panningModel = "equalpower"; - - /** - * The web audio context, which WebAudio uses to play audio. All nodes that interact with the WebAudioPlugin - * need to be created within this context. - * - * Advanced users can set this to an existing context, but must do so before they call - * {{#crossLink "Sound/registerPlugins"}}{{/crossLink}} or {{#crossLink "Sound/initializeDefaultPlugins"}}{{/crossLink}}. - * - * @property context - * @type {AudioContext} - * @static - */ - s.context = null; - - /** - * The scratch buffer that will be assigned to the buffer property of a source node on close. - * Works around an iOS Safari bug: https://github.com/CreateJS/SoundJS/issues/102 - * - * Advanced users can set this to an existing source node, but must do so before they call - * {{#crossLink "Sound/registerPlugins"}}{{/crossLink}} or {{#crossLink "Sound/initializeDefaultPlugins"}}{{/crossLink}}. - * - * @property _scratchBuffer - * @type {AudioBuffer} - * @protected - * @static - */ - s._scratchBuffer = null; - - /** - * Indicated whether audio on iOS has been unlocked, which requires a touchend/mousedown event that plays an - * empty sound. - * @property _unlocked - * @type {boolean} - * @since 0.6.2 - * @private - */ - s._unlocked = false; - - -// Static Public Methods - /** - * Determine if the plugin can be used in the current browser/OS. - * @method isSupported - * @return {Boolean} If the plugin can be initialized. - * @static - */ - s.isSupported = function () { - // check if this is some kind of mobile device, Web Audio works with local protocol under PhoneGap and it is unlikely someone is trying to run a local file - var isMobilePhoneGap = createjs.BrowserDetect.isIOS || createjs.BrowserDetect.isAndroid || createjs.BrowserDetect.isBlackberry; - // OJR isMobile may be redundant with _isFileXHRSupported available. Consider removing. - if (location.protocol == "file:" && !isMobilePhoneGap && !this._isFileXHRSupported()) { return false; } // Web Audio requires XHR, which is not usually available locally - s._generateCapabilities(); - if (s.context == null) {return false;} - return true; - }; - - /** - * Plays an empty sound in the web audio context. This is used to enable web audio on iOS devices, as they - * require the first sound to be played inside of a user initiated event (touch/click). This is called when - * {{#crossLink "WebAudioPlugin"}}{{/crossLink}} is initialized (by Sound {{#crossLink "Sound/initializeDefaultPlugins"}}{{/crossLink}} - * for example). - * - *

        Example

        - * - * function handleTouch(event) { - * createjs.WebAudioPlugin.playEmptySound(); - * } - * - * @method playEmptySound - * @static - * @since 0.4.1 - */ - s.playEmptySound = function() { - if (s.context == null) {return;} - var source = s.context.createBufferSource(); - source.buffer = s._scratchBuffer; - source.connect(s.context.destination); - source.start(0, 0, 0); - }; - - -// Static Private Methods - /** - * Determine if XHR is supported, which is necessary for web audio. - * @method _isFileXHRSupported - * @return {Boolean} If XHR is supported. - * @since 0.4.2 - * @protected - * @static - */ - s._isFileXHRSupported = function() { - // it's much easier to detect when something goes wrong, so let's start optimistically - var supported = true; - - var xhr = new XMLHttpRequest(); - try { - xhr.open("GET", "WebAudioPluginTest.fail", false); // loading non-existant file triggers 404 only if it could load (synchronous call) - } catch (error) { - // catch errors in cases where the onerror is passed by - supported = false; - return supported; - } - xhr.onerror = function() { supported = false; }; // cause irrelevant - // with security turned off, we can get empty success results, which is actually a failed read (status code 0?) - xhr.onload = function() { supported = this.status == 404 || (this.status == 200 || (this.status == 0 && this.response != "")); }; - try { - xhr.send(); - } catch (error) { - // catch errors in cases where the onerror is passed by - supported = false; - } - - return supported; - }; - - /** - * Determine the capabilities of the plugin. Used internally. Please see the Sound API {{#crossLink "Sound/getCapabilities"}}{{/crossLink}} - * method for an overview of plugin capabilities. - * @method _generateCapabilities - * @static - * @protected - */ - s._generateCapabilities = function () { - if (s._capabilities != null) {return;} - // Web Audio can be in any formats supported by the audio element, from http://www.w3.org/TR/webaudio/#AudioContext-section - var t = document.createElement("audio"); - if (t.canPlayType == null) {return null;} - - if (s.context == null) { - if (window.AudioContext) { - s.context = new AudioContext(); - } else if (window.webkitAudioContext) { - s.context = new webkitAudioContext(); - } else { - return null; - } - } - if (s._scratchBuffer == null) { - s._scratchBuffer = s.context.createBuffer(1, 1, 22050); - } - - s._compatibilitySetUp(); - - // Listen for document level clicks to unlock WebAudio on iOS. See the _unlock method. - if ("ontouchstart" in window && s.context.state != "running") { - s._unlock(); // When played inside of a touch event, this will enable audio on iOS immediately. - document.addEventListener("mousedown", s._unlock, true); - document.addEventListener("touchend", s._unlock, true); - } - - - s._capabilities = { - panning:true, - volume:true, - tracks:-1 - }; - - // determine which extensions our browser supports for this plugin by iterating through Sound.SUPPORTED_EXTENSIONS - var supportedExtensions = createjs.Sound.SUPPORTED_EXTENSIONS; - var extensionMap = createjs.Sound.EXTENSION_MAP; - for (var i = 0, l = supportedExtensions.length; i < l; i++) { - var ext = supportedExtensions[i]; - var playType = extensionMap[ext] || ext; - s._capabilities[ext] = (t.canPlayType("audio/" + ext) != "no" && t.canPlayType("audio/" + ext) != "") || (t.canPlayType("audio/" + playType) != "no" && t.canPlayType("audio/" + playType) != ""); - } // OJR another way to do this might be canPlayType:"m4a", codex: mp4 - - // 0=no output, 1=mono, 2=stereo, 4=surround, 6=5.1 surround. - // See http://www.w3.org/TR/webaudio/#AudioChannelSplitter for more details on channels. - if (s.context.destination.numberOfChannels < 2) { - s._capabilities.panning = false; - } - }; - - /** - * Set up compatibility if only deprecated web audio calls are supported. - * See http://www.w3.org/TR/webaudio/#DeprecationNotes - * Needed so we can support new browsers that don't support deprecated calls (Firefox) as well as old browsers that - * don't support new calls. - * - * @method _compatibilitySetUp - * @static - * @protected - * @since 0.4.2 - */ - s._compatibilitySetUp = function() { - s._panningModel = "equalpower"; - //assume that if one new call is supported, they all are - if (s.context.createGain) { return; } - - // simple name change, functionality the same - s.context.createGain = s.context.createGainNode; - - // source node, add to prototype - var audioNode = s.context.createBufferSource(); - audioNode.__proto__.start = audioNode.__proto__.noteGrainOn; // note that noteGrainOn requires all 3 parameters - audioNode.__proto__.stop = audioNode.__proto__.noteOff; - - // panningModel - s._panningModel = 0; - }; - - /** - * Try to unlock audio on iOS. This is triggered from either WebAudio plugin setup (which will work if inside of - * a `mousedown` or `touchend` event stack), or the first document touchend/mousedown event. If it fails (touchend - * will fail if the user presses for too long, indicating a scroll event instead of a click event. - * - * Note that earlier versions of iOS supported `touchstart` for this, but iOS9 removed this functionality. Adding - * a `touchstart` event to support older platforms may preclude a `mousedown` even from getting fired on iOS9, so we - * stick with `mousedown` and `touchend`. - * @method _unlock - * @since 0.6.2 - * @private - */ - s._unlock = function() { - if (s._unlocked) { return; } - s.playEmptySound(); - if (s.context.state == "running") { - document.removeEventListener("mousedown", s._unlock, true); - document.removeEventListener("touchend", s._unlock, true); - s._unlocked = true; - } - }; - - -// Public Methods - p.toString = function () { - return "[WebAudioPlugin]"; - }; - - -// Private Methods - /** - * Set up needed properties on supported classes WebAudioSoundInstance and WebAudioLoader. - * @method _addPropsToClasses - * @static - * @protected - * @since 0.6.0 - */ - p._addPropsToClasses = function() { - var c = this._soundInstanceClass; - c.context = this.context; - c._scratchBuffer = s._scratchBuffer; - c.destinationNode = this.gainNode; - c._panningModel = this._panningModel; - - this._loaderClass.context = this.context; - }; - - - /** - * Set the gain value for master audio. Should not be called externally. - * @method _updateVolume - * @protected - */ - p._updateVolume = function () { - var newVolume = createjs.Sound._masterMute ? 0 : this._volume; - if (newVolume != this.gainNode.gain.value) { - this.gainNode.gain.value = newVolume; - } - }; - - createjs.WebAudioPlugin = createjs.promote(WebAudioPlugin, "AbstractPlugin"); -}()); - -//############################################################################## -// HTMLAudioTagPool.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - /** - * HTMLAudioTagPool is an object pool for HTMLAudio tag instances. - * @class HTMLAudioTagPool - * @param {String} src The source of the channel. - * @protected - */ - function HTMLAudioTagPool() { - throw "HTMLAudioTagPool cannot be instantiated"; - } - - var s = HTMLAudioTagPool; - -// Static Properties - /** - * A hash lookup of each base audio tag, indexed by the audio source. - * @property _tags - * @type {{}} - * @static - * @protected - */ - s._tags = {}; - - /** - * An object pool for html audio tags - * @property _tagPool - * @type {TagPool} - * @static - * @protected - */ - s._tagPool = new TagPool(); - - /** - * A hash lookup of if a base audio tag is available, indexed by the audio source - * @property _tagsUsed - * @type {{}} - * @protected - * @static - */ - s._tagUsed = {}; - -// Static Methods - /** - * Get an audio tag with the given source. - * @method get - * @param {String} src The source file used by the audio tag. - * @static - */ - s.get = function (src) { - var t = s._tags[src]; - if (t == null) { - // create new base tag - t = s._tags[src] = s._tagPool.get(); - t.src = src; - } else { - // get base or pool - if (s._tagUsed[src]) { - t = s._tagPool.get(); - t.src = src; - } else { - s._tagUsed[src] = true; - } - } - return t; - }; - - /** - * Return an audio tag to the pool. - * @method set - * @param {String} src The source file used by the audio tag. - * @param {HTMLElement} tag Audio tag to set. - * @static - */ - s.set = function (src, tag) { - // check if this is base, if yes set boolean if not return to pool - if(tag == s._tags[src]) { - s._tagUsed[src] = false; - } else { - s._tagPool.set(tag); - } - }; - - /** - * Delete stored tag reference and return them to pool. Note that if the tag reference does not exist, this will fail. - * @method remove - * @param {String} src The source for the tag - * @return {Boolean} If the TagPool was deleted. - * @static - */ - s.remove = function (src) { - var tag = s._tags[src]; - if (tag == null) {return false;} - s._tagPool.set(tag); - delete(s._tags[src]); - delete(s._tagUsed[src]); - return true; - }; - - /** - * Gets the duration of the src audio in milliseconds - * @method getDuration - * @param {String} src The source file used by the audio tag. - * @return {Number} Duration of src in milliseconds - * @static - */ - s.getDuration= function (src) { - var t = s._tags[src]; - if (t == null || !t.duration) {return 0;} // OJR duration is NaN if loading has not completed - return t.duration * 1000; - }; - - createjs.HTMLAudioTagPool = HTMLAudioTagPool; - - -// ************************************************************************************************************ - /** - * The TagPool is an object pool for HTMLAudio tag instances. - * #class TagPool - * @param {String} src The source of the channel. - * @protected - */ - function TagPool(src) { - -// Public Properties - /** - * A list of all available tags in the pool. - * #property tags - * @type {Array} - * @protected - */ - this._tags = []; - }; - - var p = TagPool.prototype; - p.constructor = TagPool; - - -// Public Methods - /** - * Get an HTMLAudioElement for immediate playback. This takes it out of the pool. - * #method get - * @return {HTMLAudioElement} An HTML audio tag. - */ - p.get = function () { - var tag; - if (this._tags.length == 0) { - tag = this._createTag(); - } else { - tag = this._tags.pop(); - } - if (tag.parentNode == null) {document.body.appendChild(tag);} - return tag; - }; - - /** - * Put an HTMLAudioElement back in the pool for use. - * #method set - * @param {HTMLAudioElement} tag HTML audio tag - */ - p.set = function (tag) { - // OJR this first step seems unnecessary - var index = createjs.indexOf(this._tags, tag); - if (index == -1) { - this._tags.src = null; - this._tags.push(tag); - } - }; - - p.toString = function () { - return "[TagPool]"; - }; - - -// Private Methods - /** - * Create an HTML audio tag. - * #method _createTag - * @param {String} src The source file to set for the audio tag. - * @return {HTMLElement} Returns an HTML audio tag. - * @protected - */ - p._createTag = function () { - var tag = document.createElement("audio"); - tag.autoplay = false; - tag.preload = "none"; - //LM: Firefox fails when this the preload="none" for other tags, but it needs to be "none" to ensure PreloadJS works. - return tag; - }; - -}()); - -//############################################################################## -// HTMLAudioSoundInstance.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - "use strict"; - - /** - * HTMLAudioSoundInstance extends the base api of {{#crossLink "AbstractSoundInstance"}}{{/crossLink}} and is used by - * {{#crossLink "HTMLAudioPlugin"}}{{/crossLink}}. - * - * @param {String} src The path to and file name of the sound. - * @param {Number} startTime Audio sprite property used to apply an offset, in milliseconds. - * @param {Number} duration Audio sprite property used to set the time the clip plays for, in milliseconds. - * @param {Object} playbackResource Any resource needed by plugin to support audio playback. - * @class HTMLAudioSoundInstance - * @extends AbstractSoundInstance - * @constructor - */ - function HTMLAudioSoundInstance(src, startTime, duration, playbackResource) { - this.AbstractSoundInstance_constructor(src, startTime, duration, playbackResource); - - -// Private Properties - this._audioSpriteStopTime = null; - this._delayTimeoutId = null; - - // Proxies, make removing listeners easier. - 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); - - if (duration) { - this._audioSpriteStopTime = (startTime + duration) * 0.001; - } else { - this._duration = createjs.HTMLAudioTagPool.getDuration(this.src); - } - } - var p = createjs.extend(HTMLAudioSoundInstance, createjs.AbstractSoundInstance); - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// Public Methods - /** - * Called by {{#crossLink "Sound"}}{{/crossLink}} when plugin does not handle master volume. - * undoc'd because it is not meant to be used outside of Sound - * #method setMasterVolume - * @param value - */ - p.setMasterVolume = function (value) { - this._updateVolume(); - }; - - /** - * Called by {{#crossLink "Sound"}}{{/crossLink}} when plugin does not handle master mute. - * undoc'd because it is not meant to be used outside of Sound - * #method setMasterMute - * @param value - */ - p.setMasterMute = function (isMuted) { - this._updateVolume(); - }; - - p.toString = function () { - return "[HTMLAudioSoundInstance]"; - }; - -//Private Methods - p._removeLooping = function() { - if(this._playbackResource == null) {return;} - this._playbackResource.loop = false; - this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false); - }; - - p._addLooping = function() { - if(this._playbackResource == null || this._audioSpriteStopTime) {return;} - this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false); - this._playbackResource.loop = true; - }; - - p._handleCleanUp = function () { - var tag = this._playbackResource; - if (tag != null) { - tag.pause(); - tag.loop = false; - tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED, this._endedHandler, false); - tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_READY, this._readyHandler, false); - tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED, this._stalledHandler, false); - tag.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false); - tag.removeEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE, this._audioSpriteEndHandler, false); - - try { - tag.currentTime = this._startTime; - } catch (e) { - } // Reset Position - createjs.HTMLAudioTagPool.set(this.src, tag); - this._playbackResource = null; - } - }; - - p._beginPlaying = function (playProps) { - this._playbackResource = createjs.HTMLAudioTagPool.get(this.src); - return this.AbstractSoundInstance__beginPlaying(playProps); - }; - - p._handleSoundReady = function (event) { - if (this._playbackResource.readyState !== 4) { - var tag = this._playbackResource; - tag.addEventListener(createjs.HTMLAudioPlugin._AUDIO_READY, this._readyHandler, false); - tag.addEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED, this._stalledHandler, false); - tag.preload = "auto"; // This is necessary for Firefox, as it won't ever "load" until this is set. - tag.load(); - return; - } - - this._updateVolume(); - this._playbackResource.currentTime = (this._startTime + this._position) * 0.001; - if (this._audioSpriteStopTime) { - this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE, this._audioSpriteEndHandler, false); - } else { - this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED, this._endedHandler, false); - if(this._loop != 0) { - this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false); - this._playbackResource.loop = true; - } - } - - this._playbackResource.play(); - }; - - /** - * Used to handle when a tag is not ready for immediate playback when it is returned from the HTMLAudioTagPool. - * @method _handleTagReady - * @param event - * @protected - */ - p._handleTagReady = function (event) { - this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_READY, this._readyHandler, false); - this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED, this._stalledHandler, false); - - this._handleSoundReady(); - }; - - p._pause = function () { - this._playbackResource.pause(); - }; - - p._resume = function () { - this._playbackResource.play(); - }; - - p._updateVolume = function () { - if (this._playbackResource != null) { - var newVolume = (this._muted || createjs.Sound._masterMute) ? 0 : this._volume * createjs.Sound._masterVolume; - if (newVolume != this._playbackResource.volume) {this._playbackResource.volume = newVolume;} - } - }; - - p._calculateCurrentPosition = function() { - return (this._playbackResource.currentTime * 1000) - this._startTime; - }; - - p._updatePosition = function() { - this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false); - this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._handleSetPositionSeek, false); - try { - this._playbackResource.currentTime = (this._position + this._startTime) * 0.001; - } catch (error) { // Out of range - this._handleSetPositionSeek(null); - } - }; - - /** - * Used to enable setting position, as we need to wait for that seek to be done before we add back our loop handling seek listener - * @method _handleSetPositionSeek - * @param event - * @protected - */ - p._handleSetPositionSeek = function(event) { - if (this._playbackResource == null) { return; } - this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._handleSetPositionSeek, false); - this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false); - }; - - /** - * Timer used to loop audio sprites. - * NOTE because of the inaccuracies in the timeupdate event (15 - 250ms) and in setting the tag to the desired timed - * (up to 300ms), it is strongly recommended not to loop audio sprites with HTML Audio if smooth looping is desired - * - * @method _handleAudioSpriteLoop - * @param event - * @private - */ - p._handleAudioSpriteLoop = function (event) { - if(this._playbackResource.currentTime <= this._audioSpriteStopTime) {return;} - this._playbackResource.pause(); - if(this._loop == 0) { - this._handleSoundComplete(null); - } else { - this._position = 0; - this._loop--; - this._playbackResource.currentTime = this._startTime * 0.001; - if(!this._paused) {this._playbackResource.play();} - this._sendEvent("loop"); - } - }; - - // NOTE with this approach audio will loop as reliably as the browser allows - // but we could end up sending the loop event after next loop playback begins - p._handleLoop = function (event) { - if(this._loop == 0) { - this._playbackResource.loop = false; - this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED, this._loopHandler, false); - } - }; - - p._updateStartTime = function () { - this._audioSpriteStopTime = (this._startTime + this._duration) * 0.001; - - if(this.playState == createjs.Sound.PLAY_SUCCEEDED) { - this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED, this._endedHandler, false); - this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE, this._audioSpriteEndHandler, false); - } - }; - - p._updateDuration = function () { - this._audioSpriteStopTime = (this._startTime + this._duration) * 0.001; - - if(this.playState == createjs.Sound.PLAY_SUCCEEDED) { - this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED, this._endedHandler, false); - this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE, this._audioSpriteEndHandler, false); - } - }; - - p._setDurationFromSource = function () { - this._duration = createjs.HTMLAudioTagPool.getDuration(this.src); - this._playbackResource = null; - }; - - createjs.HTMLAudioSoundInstance = createjs.promote(HTMLAudioSoundInstance, "AbstractSoundInstance"); -}()); - -//############################################################################## -// HTMLAudioPlugin.js -//############################################################################## - -this.createjs = this.createjs || {}; - -(function () { - - "use strict"; - - /** - * Play sounds using HTML <audio> tags in the browser. This plugin is the second priority plugin installed - * by default, after the {{#crossLink "WebAudioPlugin"}}{{/crossLink}}. For older browsers that do not support html - * audio, include and install the {{#crossLink "FlashAudioPlugin"}}{{/crossLink}}. - * - *

        Known Browser and OS issues for HTML Audio

        - * All browsers
        - * Testing has shown in all browsers there is a limit to how many audio tag instances you are allowed. If you exceed - * this limit, you can expect to see unpredictable results. Please use {{#crossLink "Sound.MAX_INSTANCES"}}{{/crossLink}} as - * a guide to how many total audio tags you can safely use in all browsers. This issue is primarily limited to IE9. - * - * IE html limitations
        - *
        • There is a delay in applying volume changes to tags that occurs once playback is started. So if you have - * muted all sounds, they will all play during this delay until the mute applies internally. This happens regardless of - * when or how you apply the volume change, as the tag seems to need to play to apply it.
        • - *
        • MP3 encoding will not always work for audio tags if it's not default. We've found default encoding with - * 64kbps works.
        • - *
        • Occasionally very short samples will get cut off.
        • - *
        • There is a limit to how many audio tags you can load or play at once, which appears to be determined by - * hardware and browser settings. See {{#crossLink "HTMLAudioPlugin.MAX_INSTANCES"}}{{/crossLink}} for a safe estimate. - * Note that audio sprites can be used as a solution to this issue.
        - * - * Safari limitations
        - *
        • Safari requires Quicktime to be installed for audio playback.
        - * - * iOS 6 limitations
        - *
        • can only have one <audio> tag
        • - *
        • can not preload or autoplay the audio
        • - *
        • can not cache the audio
        • - *
        • can not play the audio except inside a user initiated event.
        • - *
        • Note it is recommended to use {{#crossLink "WebAudioPlugin"}}{{/crossLink}} for iOS (6+)
        • - *
        • audio sprites can be used to mitigate some of these issues and are strongly recommended on iOS
        • - *
        - * - * Android Native Browser limitations
        - *
        • We have no control over audio volume. Only the user can set volume on their device.
        • - *
        • We can only play audio inside a user event (touch/click). This currently means you cannot loop sound or use a delay.
        - * Android Chrome 26.0.1410.58 specific limitations
        - *
        • Can only play 1 sound at a time.
        • - *
        • Sound is not cached.
        • - *
        • Sound can only be loaded in a user initiated touch/click event.
        • - *
        • There is a delay before a sound is played, presumably while the src is loaded.
        • - *
        - * - * See {{#crossLink "Sound"}}{{/crossLink}} for general notes on known issues. - * - * @class HTMLAudioPlugin - * @extends AbstractPlugin - * @constructor - */ - function HTMLAudioPlugin() { - this.AbstractPlugin_constructor(); - - - // Public Properties - /** - * This is no longer needed as we are now using object pooling for tags. - * - * NOTE this property only exists as a limitation of HTML audio. - * @property defaultNumChannels - * @type {Number} - * @default 2 - * @since 0.4.0 - * @deprecated - */ - this.defaultNumChannels = 2; - - this._capabilities = s._capabilities; - - this._loaderClass = createjs.SoundLoader; - this._soundInstanceClass = createjs.HTMLAudioSoundInstance; - } - - var p = createjs.extend(HTMLAudioPlugin, createjs.AbstractPlugin); - var s = HTMLAudioPlugin; - - // TODO: deprecated - // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. - - -// Static Properties - /** - * The maximum number of instances that can be loaded or played. This is a browser limitation, primarily limited to IE9. - * The actual number varies from browser to browser (and is largely hardware dependant), but this is a safe estimate. - * Audio sprites work around this limitation. - * @property MAX_INSTANCES - * @type {Number} - * @default 30 - * @static - */ - s.MAX_INSTANCES = 30; - - /** - * Event constant for the "canPlayThrough" event for cleaner code. - * @property _AUDIO_READY - * @type {String} - * @default canplaythrough - * @static - * @protected - */ - s._AUDIO_READY = "canplaythrough"; - - /** - * Event constant for the "ended" event for cleaner code. - * @property _AUDIO_ENDED - * @type {String} - * @default ended - * @static - * @protected - */ - s._AUDIO_ENDED = "ended"; - - /** - * Event constant for the "seeked" event for cleaner code. We utilize this event for maintaining loop events. - * @property _AUDIO_SEEKED - * @type {String} - * @default seeked - * @static - * @protected - */ - s._AUDIO_SEEKED = "seeked"; - - /** - * Event constant for the "stalled" event for cleaner code. - * @property _AUDIO_STALLED - * @type {String} - * @default stalled - * @static - * @protected - */ - s._AUDIO_STALLED = "stalled"; - - /** - * Event constant for the "timeupdate" event for cleaner code. Utilized for looping audio sprites. - * This event callsback ever 15 to 250ms and can be dropped by the browser for performance. - * @property _TIME_UPDATE - * @type {String} - * @default timeupdate - * @static - * @protected - */ - s._TIME_UPDATE = "timeupdate"; - - /** - * The capabilities of the plugin. This is generated via the {{#crossLink "HTMLAudioPlugin/_generateCapabilities"}}{{/crossLink}} - * method. Please see the Sound {{#crossLink "Sound/getCapabilities"}}{{/crossLink}} method for an overview of all - * of the available properties. - * @property _capabilities - * @type {Object} - * @protected - * @static - */ - s._capabilities = null; - - -// Static Methods - /** - * Determine if the plugin can be used in the current browser/OS. Note that HTML audio is available in most modern - * browsers, but is disabled in iOS because of its limitations. - * @method isSupported - * @return {Boolean} If the plugin can be initialized. - * @static - */ - s.isSupported = function () { - s._generateCapabilities(); - return (s._capabilities != null); - }; - - /** - * Determine the capabilities of the plugin. Used internally. Please see the Sound API {{#crossLink "Sound/getCapabilities"}}{{/crossLink}} - * method for an overview of plugin capabilities. - * @method _generateCapabilities - * @static - * @protected - */ - s._generateCapabilities = function () { - if (s._capabilities != null) {return;} - var t = document.createElement("audio"); - if (t.canPlayType == null) {return null;} - - s._capabilities = { - panning:false, - volume:true, - tracks:-1 - }; - - // determine which extensions our browser supports for this plugin by iterating through Sound.SUPPORTED_EXTENSIONS - var supportedExtensions = createjs.Sound.SUPPORTED_EXTENSIONS; - var extensionMap = createjs.Sound.EXTENSION_MAP; - for (var i = 0, l = supportedExtensions.length; i < l; i++) { - var ext = supportedExtensions[i]; - var playType = extensionMap[ext] || ext; - s._capabilities[ext] = (t.canPlayType("audio/" + ext) != "no" && t.canPlayType("audio/" + ext) != "") || (t.canPlayType("audio/" + playType) != "no" && t.canPlayType("audio/" + playType) != ""); - } // OJR another way to do this might be canPlayType:"m4a", codex: mp4 - }; - - -// public methods - p.register = function (loadItem) { - var tag = createjs.HTMLAudioTagPool.get(loadItem.src); - var loader = this.AbstractPlugin_register(loadItem); - loader.setTag(tag); - - return loader; - }; - - p.removeSound = function (src) { - this.AbstractPlugin_removeSound(src); - createjs.HTMLAudioTagPool.remove(src); - }; - - p.create = function (src, startTime, duration) { - var si = this.AbstractPlugin_create(src, startTime, duration); - si.setPlaybackResource(null); - return si; - }; - - p.toString = function () { - return "[HTMLAudioPlugin]"; - }; - - // plugin does not support these - p.setVolume = p.getVolume = p.setMute = null; - - - createjs.HTMLAudioPlugin = createjs.promote(HTMLAudioPlugin, "AbstractPlugin"); -}()); \ No newline at end of file diff --git a/bomberman/frontend/src/main/webapp/sound/bomb.mp3 b/bomberman/frontend/src/main/webapp/sound/bomb.mp3 deleted file mode 100644 index e419cb6f43..0000000000 Binary files a/bomberman/frontend/src/main/webapp/sound/bomb.mp3 and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/sound/bomb.ogg b/bomberman/frontend/src/main/webapp/sound/bomb.ogg deleted file mode 100644 index 59912972df..0000000000 Binary files a/bomberman/frontend/src/main/webapp/sound/bomb.ogg and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/sound/game.mp3 b/bomberman/frontend/src/main/webapp/sound/game.mp3 deleted file mode 100644 index fe931af90a..0000000000 Binary files a/bomberman/frontend/src/main/webapp/sound/game.mp3 and /dev/null differ diff --git a/bomberman/frontend/src/main/webapp/sound/game.ogg b/bomberman/frontend/src/main/webapp/sound/game.ogg deleted file mode 100644 index 46a859f37f..0000000000 Binary files a/bomberman/frontend/src/main/webapp/sound/game.ogg and /dev/null differ diff --git a/lecture04/gradlew b/lecture04/gradlew index cccdd3d517..af6708ff22 100755 --- a/lecture04/gradlew +++ b/lecture04/gradlew @@ -28,7 +28,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" diff --git a/lecture04/gradlew.bat b/lecture04/gradlew.bat index e95643d6a2..0f8d5937c4 100644 --- a/lecture04/gradlew.bat +++ b/lecture04/gradlew.bat @@ -14,7 +14,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/lecture05/gradle/wrapper/gradle-wrapper.properties b/lecture05/gradle/wrapper/gradle-wrapper.properties index 568c50bf3a..577d4c5d62 100644 --- a/lecture05/gradle/wrapper/gradle-wrapper.properties +++ b/lecture05/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Mon Sep 09 10:32:45 MSK 2019 +distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip +zipStoreBase=GRADLE_USER_HOME diff --git a/lecture05/src/main/java/ru/atom/mm/MatchMakerApp.java b/lecture05/src/main/java/ru/atom/mm/MatchMakerApp.java index 57cc119384..df1a64292b 100644 --- a/lecture05/src/main/java/ru/atom/mm/MatchMakerApp.java +++ b/lecture05/src/main/java/ru/atom/mm/MatchMakerApp.java @@ -2,6 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Scope; + +import java.util.Date; @SpringBootApplication @@ -9,4 +13,16 @@ public class MatchMakerApp { public static void main(String[] args) throws Exception { SpringApplication.run(MatchMakerApp.class, args); } + + @Bean + @Scope("prototype") + Date time() { + return new Date(); + } + + @Bean + @Scope("prototype") + Date timeFirst() { + return new Date(0); + } } diff --git a/lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java b/lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java index 17cf04d52a..b17391a79d 100644 --- a/lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java +++ b/lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java @@ -4,8 +4,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -14,8 +16,12 @@ import ru.atom.mm.model.Connection; import ru.atom.mm.service.ConnectionQueue; +import java.util.List; +import java.util.stream.Collectors; + @Controller +@Scope("singleton") @RequestMapping("/connection") public class ConnectionController { private static final Logger log = LoggerFactory.getLogger(ConnectionController.class); @@ -47,9 +53,12 @@ public void connect(@RequestParam("id") long id, * * curl -i localhost:8080/connection/list' */ + @RequestMapping( + path = "list", + method = RequestMethod.GET, + produces = MediaType.TEXT_PLAIN_VALUE) public String list() { - throw new UnsupportedOperationException(); - } - - + String list = String.join("\n", (List) connectionQueue.getQueue()); + return list; + } } diff --git a/lecture05/src/main/java/ru/atom/mm/controller/GameController.java b/lecture05/src/main/java/ru/atom/mm/controller/GameController.java index a38b1f1f6f..6be886f71f 100644 --- a/lecture05/src/main/java/ru/atom/mm/controller/GameController.java +++ b/lecture05/src/main/java/ru/atom/mm/controller/GameController.java @@ -3,6 +3,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Scope; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @@ -10,11 +12,14 @@ import org.springframework.web.bind.annotation.ResponseBody; import ru.atom.mm.service.GameRepository; +import java.util.Date; + /** * Created by sergey on 3/15/17. */ @Controller +@Scope("request") @RequestMapping("/game") public class GameController { private static final Logger log = LoggerFactory.getLogger(GameController.class); @@ -23,6 +28,9 @@ public class GameController { @Autowired private GameRepository gameRepository; + @Autowired + @Qualifier("time") + private Date now; /** * curl test * @@ -37,4 +45,13 @@ public String list() { log.info("Games list request"); return gameRepository.getAll().toString(); } + + @RequestMapping( + path = "time", + method = RequestMethod.GET, + produces = MediaType.TEXT_PLAIN_VALUE) + @ResponseBody + public String time() { + return now.toString(); + } } diff --git a/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java index b53356ba2d..149c93a6d0 100644 --- a/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java +++ b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java @@ -11,6 +11,7 @@ import org.springframework.test.web.servlet.MockMvc; import static org.junit.Assert.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -22,7 +23,6 @@ public class ConnectionControllerIntegrationTest { MockMvc mockMvc; @Test - @Ignore public void connect() throws Exception { mockMvc.perform(post("/connection/connect") .content("id=1&name=a") @@ -31,9 +31,10 @@ public void connect() throws Exception { } @Test - @Ignore public void list() throws Exception { - assertTrue(false); + mockMvc.perform(get("/connection/list") + .contentType(MediaType.TEXT_PLAIN_VALUE)) + .andExpect(status().isOk()); } } \ No newline at end of file diff --git a/lecture06/build.gradle b/lecture06/build.gradle index f522afc734..8cc8bd3b50 100644 --- a/lecture06/build.gradle +++ b/lecture06/build.gradle @@ -1,31 +1,38 @@ -dependencies { - compile rootProject.libraries.spring_boot - compile rootProject.libraries.log4j - compile rootProject.libraries.postgres - compile rootProject.libraries.jetbrainsAnnotations - - testCompile rootProject.libraries.junit - testCompile rootProject.libraries.spring_boot_test +plugins { + id 'org.springframework.boot' version '2.0.0.RELEASE' } -configurations { - compile.exclude group:'ch.qos.logback' +repositories { + mavenCentral() + maven { + url "http://clojars.org/repo/" + } } -springBoot { - mainClass = "ru.atom.lecture06.server.ChatApplication" -} +apply plugin: 'java' +apply plugin: 'checkstyle' +dependencies { + // https://mvnrepository.com/artifact/org.slf4j/slf4j-api + compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' + // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl + //compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.10.0' + // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web + compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.0.RELEASE' + // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator + compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '2.0.0.RELEASE' + // https://mvnrepository.com/artifact/postgresql/postgresql + compile group: 'postgresql', name: 'postgresql', version: '9.3-1102.jdbc41' -sourceSets { - main { - java { - srcDirs = ['src/main/java'] - } - } - test { - java { - srcDirs = ['src/test/java'] - } - } + + // https://mvnrepository.com/artifact/junit/junit + testCompile group: 'junit', name: 'junit', version: '4.4' + // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test + testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.0.0.RELEASE' } + +checkstyle { + ignoreFailures = false + toolVersion = '7.5' + configFile = new File('../config/checkstyle/checkstyle.xml') +} \ No newline at end of file diff --git a/lecture06/gradle/wrapper/gradle-wrapper.jar b/lecture06/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..c44b679acd Binary files /dev/null and b/lecture06/gradle/wrapper/gradle-wrapper.jar differ diff --git a/lecture06/gradle/wrapper/gradle-wrapper.properties b/lecture06/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..f51202dd25 --- /dev/null +++ b/lecture06/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/lecture06/gradlew b/lecture06/gradlew new file mode 100755 index 0000000000..cccdd3d517 --- /dev/null +++ b/lecture06/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/lecture06/gradlew.bat b/lecture06/gradlew.bat new file mode 100644 index 0000000000..e95643d6a2 --- /dev/null +++ b/lecture06/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/lecture06/lecture06.iml b/lecture06/lecture06.iml new file mode 100644 index 0000000000..87da47998c --- /dev/null +++ b/lecture06/lecture06.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/lecture06/presentation/PITCHME.md b/lecture06/presentation/PITCHME.md index d3bc01d6ac..7f619f2990 100644 --- a/lecture06/presentation/PITCHME.md +++ b/lecture06/presentation/PITCHME.md @@ -1,19 +1,21 @@ -#HSLIDE +--- # Java lecture 6 ## Java + DB -#HSLIDE +--- ## Отметьтесь на портале -https://atom.mail.ru/ +https://sphere.mail.ru/ -#HSLIDE +--- ### get ready #1 +[https://github.com/rybalkinsd/atom](https://github.com/rybalkinsd/atom) ```bash > git fetch upstream > git checkout -b lecture06 upstream/lecture06 +> cd lecture06 Refresh gradle project ``` @@ -21,13 +23,13 @@ Refresh gradle project Refresh gradle project -#HSLIDE +--- ### get ready #2 PostgreSQL client linux ```bash -apt-get install postgresql-9.4 +apt-get install postgresql-9.5 ``` windows [[Download page]](https://www.postgresql.org/download/windows/) @@ -38,10 +40,10 @@ mac > brew install postgres ``` -#HSLIDE +--- ### get ready #3 ```bash -> psql -h 34.229.108.81 -U -d atomN +> psql -h 54.224.37.210 -U atomN -d chatdb_atomN > enter your password >> psql (9.6.2, server 9.2.18) >> Type "help" for help. @@ -50,22 +52,35 @@ mac select * from pg_catalog.pg_tables; ``` -`\q to exit :)` +--- +### psql commands +```bash +#exit +\q +#list all schemas +\dn +#list all tables in all schemas +\dt *. +#describe table +\d+ tablename +``` + -#HSLIDE +--- ### Agenda -1. Retrospective 1. DB or not DB 1. Database baseline 1. SQL baseline 1. Java + DB +--- +### Agenda +1. **[DB or not DB]** +1. Database baseline +1. SQL baseline +1. Java + DB -#HSLIDE -process - - -#HSLIDE +--- ### Storage comparison **RAM** vs **File** - Capacity @@ -73,7 +88,7 @@ select * from pg_catalog.pg_tables; - Durability -#HSLIDE +--- ### Storage comparison **File** vs **Database** - Store overhead @@ -81,7 +96,7 @@ select * from pg_catalog.pg_tables; - Guarantees - Speed -#HSLIDE +--- ### Database (RDBMS) Is a @@ -96,14 +111,13 @@ Within Management system -#HSLIDE -### DB types -- SQL -- NoSQL -- In-memory -- embedded +--- +### Many different types of DBs +- SQL/[NoSQL](https://en.wikipedia.org/wiki/NoSQL) +- In-memory/disk storage +- stand-alone/embedded -#HSLIDE +--- ### Transaction Transaction is a unit of work @@ -115,17 +129,17 @@ Transaction is a unit of work - Durability -#HSLIDE +--- ## All examples below are in PostgreSQL [[Official doc]](https://www.postgresql.org/docs/9.2/static/index.html) -#HSLIDE +--- ### Table ```postgresql create table user ( id serial not null, - login varchar(20) unique not null, + login varchar(20) unique not null ); ``` **There is an error in create query** @@ -133,7 +147,7 @@ create table user ( [[Read more about `serial`]](https://www.tutorialspoint.com/postgresql/postgresql_using_autoincrement.htm) -#HSLIDE +--- ### Primary key Indicates that a column or group of columns can be used as a unique identifier for rows in the table @@ -147,7 +161,7 @@ create table chat.user ( ``` -#HSLIDE +--- ### Schema A schema is essentially a namespace. @@ -164,12 +178,12 @@ create table chat.user ( [[Read more]](https://www.postgresql.org/docs/9.3/static/sql-createschema.html) -#HSLIDE +--- ### First schema @See resources/sql/schema/schema-1-simple.sql -#HSLIDE +--- ### CRUD 1. **insert** for create 1. **select** for read @@ -177,7 +191,7 @@ create table chat.user ( 1. **delete** for delete -#HSLIDE +--- ### select ```postgresql select * @@ -187,7 +201,7 @@ where time > '2017-03-25'; [[Read more]](https://www.postgresql.org/docs/9.2/static/sql-select.html) -#HSLIDE +--- ### insert ```postgresql insert into chat.user (login) @@ -196,7 +210,7 @@ values ('admin'); [[Read more]](https://www.postgresql.org/docs/9.2/static/sql-insert.html) -#HSLIDE +--- ### delete ```postgresql delete from chat.user @@ -206,14 +220,14 @@ where login = 'admin'; [[Read more]](https://www.postgresql.org/docs/9.2/static/sql-delete.html) -#HSLIDE +--- ### Constraints Imagine a user with lots of messages in history. What happens when we delete this user? -#HSLIDE +--- ### Constraints ```postgresql drop table if exists chat.message; @@ -232,12 +246,12 @@ What if chat.user has a complex pk? [[Read more]](https://www.postgresql.org/docs/9.2/static/ddl-constraints.html) -#HSLIDE +--- ### Second schema @See resources/sql/schema/schema-2-constraints.sql -#HSLIDE +--- ### What if one of queries is broken? ```postgresql create table "user"(); @@ -249,8 +263,8 @@ values ('admin', now(), 'super message') ``` -#HSLIDE -### Transation +--- +### Transaction ```postgresql begin; {statements} @@ -258,17 +272,17 @@ commit; ``` -#HSLIDE +--- ### Third schema @See resources/sql/schema/schema-3-transaction.sql -#HSLIDE +--- ### Java Database Connectivity process -#HSLIDE +--- ### Connection ```java import java.sql.*; @@ -279,7 +293,7 @@ Statement stm = con.createStatement(); ResultSet rs = stm.executeQuery("select * from chat.user"); ``` -#HSLIDE +--- ### Dao @See ru.atom.lecture06.server.model @See ru.atom.lecture06.server.dao @@ -289,11 +303,11 @@ ResultSet rs = stm.executeQuery("select * from chat.user"); - dbConnection -#HSLIDE +--- ### Types mapping process -#HSLIDE +--- ### Practice 0) Check that DbConnector uses right **login**, **password** and **database** @@ -305,7 +319,7 @@ Implement it using **MessageDao** **Implement UserDao.getByName(String name)** -#HSLIDE +--- ### Summary 1. JDBC is simple 1. JDBC leads to tones of boiler plate code @@ -313,7 +327,7 @@ Implement it using **MessageDao** 1. Use transactions for atomic operations -#HSLIDE +--- **Оставьте обратную связь** (вам на почту придет анкета) diff --git a/lecture06/presentation/PITCHME.yaml b/lecture06/presentation/PITCHME.yaml index ea67549844..aa3a413189 100644 --- a/lecture06/presentation/PITCHME.yaml +++ b/lecture06/presentation/PITCHME.yaml @@ -1,3 +1,3 @@ theme-override : lecture02/presentation/assets/css/PITCHME.css -logo : lecture01/presentation/assets/img/atom.png -slide-number: true +logo : lecture01/presentation/assets/img/sphere.png +slide-number: true \ No newline at end of file diff --git a/lecture06/src/main/java/ru/atom/lecture06/server/ChatApplication.java b/lecture06/src/main/java/ru/atom/ChatApplication.java similarity index 89% rename from lecture06/src/main/java/ru/atom/lecture06/server/ChatApplication.java rename to lecture06/src/main/java/ru/atom/ChatApplication.java index a34cb79822..97a0753dc1 100644 --- a/lecture06/src/main/java/ru/atom/lecture06/server/ChatApplication.java +++ b/lecture06/src/main/java/ru/atom/ChatApplication.java @@ -1,4 +1,4 @@ -package ru.atom.lecture06.server; +package ru.atom; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/lecture06/src/main/java/ru/atom/lecture06/server/controller/ChatController.java b/lecture06/src/main/java/ru/atom/controller/ChatController.java similarity index 92% rename from lecture06/src/main/java/ru/atom/lecture06/server/controller/ChatController.java rename to lecture06/src/main/java/ru/atom/controller/ChatController.java index c91a7af219..3ce7296ee4 100644 --- a/lecture06/src/main/java/ru/atom/lecture06/server/controller/ChatController.java +++ b/lecture06/src/main/java/ru/atom/controller/ChatController.java @@ -1,7 +1,7 @@ -package ru.atom.lecture06.server.controller; +package ru.atom.controller; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -10,10 +10,10 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; -import ru.atom.lecture06.server.model.Message; -import ru.atom.lecture06.server.model.User; -import ru.atom.lecture06.server.dao.MessageDao; -import ru.atom.lecture06.server.dao.UserDao; +import ru.atom.dao.MessageDao; +import ru.atom.dao.UserDao; +import ru.atom.model.Message; +import ru.atom.model.User; import java.util.List; import java.util.stream.Collectors; @@ -21,7 +21,7 @@ @Controller @RequestMapping("chat") public class ChatController { - private static final Logger log = LogManager.getLogger(ChatController.class); + private static final Logger log = LoggerFactory.getLogger(ChatController.class); private final UserDao userDao = new UserDao(); private final MessageDao messageDao = new MessageDao(); diff --git a/lecture06/src/main/java/ru/atom/lecture06/server/dao/Dao.java b/lecture06/src/main/java/ru/atom/dao/Dao.java similarity index 94% rename from lecture06/src/main/java/ru/atom/lecture06/server/dao/Dao.java rename to lecture06/src/main/java/ru/atom/dao/Dao.java index 84aa019cdf..4ae3c798bd 100644 --- a/lecture06/src/main/java/ru/atom/lecture06/server/dao/Dao.java +++ b/lecture06/src/main/java/ru/atom/dao/Dao.java @@ -1,4 +1,4 @@ -package ru.atom.lecture06.server.dao; +package ru.atom.dao; import java.util.List; import java.util.Optional; diff --git a/lecture06/src/main/java/ru/atom/lecture06/server/dao/DbConnector.java b/lecture06/src/main/java/ru/atom/dao/DbConnector.java similarity index 74% rename from lecture06/src/main/java/ru/atom/lecture06/server/dao/DbConnector.java rename to lecture06/src/main/java/ru/atom/dao/DbConnector.java index 3dcfb76ada..90d1c56728 100644 --- a/lecture06/src/main/java/ru/atom/lecture06/server/dao/DbConnector.java +++ b/lecture06/src/main/java/ru/atom/dao/DbConnector.java @@ -1,10 +1,11 @@ -package ru.atom.lecture06.server.dao; +package ru.atom.dao; /** * Created by sergey on 3/25/17. */ -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.sql.Connection; import java.sql.DriverManager; @@ -12,13 +13,13 @@ class DbConnector { - private static final Logger log = LogManager.getLogger(DbConnector.class); + private static final Logger log = LoggerFactory.getLogger(DbConnector.class); private static final String URL_TEMPLATE = "jdbc:postgresql://%s:%d/%s"; private static final String URL; - private static final String HOST = "34.229.108.81"; + private static final String HOST = "54.224.37.210"; private static final int PORT = 5432; - private static final String DB_NAME = "atomN"; + private static final String DB_NAME = "chatdb_atomN"; private static final String USER = "atomN"; private static final String PASSWORD = "atomN"; diff --git a/lecture06/src/main/java/ru/atom/lecture06/server/dao/MessageDao.java b/lecture06/src/main/java/ru/atom/dao/MessageDao.java similarity index 85% rename from lecture06/src/main/java/ru/atom/lecture06/server/dao/MessageDao.java rename to lecture06/src/main/java/ru/atom/dao/MessageDao.java index bcf39b5b27..f77766d4ec 100644 --- a/lecture06/src/main/java/ru/atom/lecture06/server/dao/MessageDao.java +++ b/lecture06/src/main/java/ru/atom/dao/MessageDao.java @@ -1,10 +1,9 @@ -package ru.atom.lecture06.server.dao; +package ru.atom.dao; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.intellij.lang.annotations.Language; -import ru.atom.lecture06.server.model.Message; -import ru.atom.lecture06.server.model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.atom.model.Message; +import ru.atom.model.User; import java.sql.Connection; import java.sql.ResultSet; @@ -18,9 +17,8 @@ * Created by sergey on 3/25/17. */ public class MessageDao implements Dao { - private static final Logger log = LogManager.getLogger(MessageDao.class); + private static final Logger log = LoggerFactory.getLogger(MessageDao.class); - @Language("sql") private static final String SELECT_ALL_MESSAGES = "select m.time, m.value, u.* " + "from chat.message as m " + @@ -28,7 +26,6 @@ public class MessageDao implements Dao { " on m.user = u.id " + "order by m.time"; - @Language("sql") private static final String INSERT_MESSAGE_TEMPLATE = "insert into chat.message (\"user\", time, value) " + "values (%d, now(), '%s')"; diff --git a/lecture06/src/main/java/ru/atom/lecture06/server/dao/UserDao.java b/lecture06/src/main/java/ru/atom/dao/UserDao.java similarity index 87% rename from lecture06/src/main/java/ru/atom/lecture06/server/dao/UserDao.java rename to lecture06/src/main/java/ru/atom/dao/UserDao.java index 70c14133cf..05424d05b9 100644 --- a/lecture06/src/main/java/ru/atom/lecture06/server/dao/UserDao.java +++ b/lecture06/src/main/java/ru/atom/dao/UserDao.java @@ -1,9 +1,8 @@ -package ru.atom.lecture06.server.dao; +package ru.atom.dao; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.intellij.lang.annotations.Language; -import ru.atom.lecture06.server.model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.atom.model.User; import java.sql.Connection; import java.sql.ResultSet; @@ -17,20 +16,17 @@ * Created by sergey on 3/25/17. */ public class UserDao implements Dao { - private static final Logger log = LogManager.getLogger(UserDao.class); + private static final Logger log = LoggerFactory.getLogger(UserDao.class); - @Language("sql") private static final String SELECT_ALL_USERS = "select * " + "from chat.user"; - @Language("sql") private static final String SELECT_ALL_USERS_WHERE = "select * " + "from chat.user " + "where "; - @Language("sql") private static final String INSERT_USER_TEMPLATE = "insert into chat.user (login) " + "values ('%s');"; diff --git a/lecture06/src/main/java/ru/atom/lecture06/server/model/Message.java b/lecture06/src/main/java/ru/atom/model/Message.java similarity index 95% rename from lecture06/src/main/java/ru/atom/lecture06/server/model/Message.java rename to lecture06/src/main/java/ru/atom/model/Message.java index 413b8b4cb7..55dea52cb0 100644 --- a/lecture06/src/main/java/ru/atom/lecture06/server/model/Message.java +++ b/lecture06/src/main/java/ru/atom/model/Message.java @@ -1,4 +1,4 @@ -package ru.atom.lecture06.server.model; +package ru.atom.model; import java.util.Date; diff --git a/lecture06/src/main/java/ru/atom/lecture06/server/model/User.java b/lecture06/src/main/java/ru/atom/model/User.java similarity index 93% rename from lecture06/src/main/java/ru/atom/lecture06/server/model/User.java rename to lecture06/src/main/java/ru/atom/model/User.java index e0bbd2393b..19f78e6739 100644 --- a/lecture06/src/main/java/ru/atom/lecture06/server/model/User.java +++ b/lecture06/src/main/java/ru/atom/model/User.java @@ -1,4 +1,4 @@ -package ru.atom.lecture06.server.model; +package ru.atom.model; /** * Created by sergey on 3/25/17. diff --git a/lecture06/src/main/resources/static/index.html b/lecture06/src/main/resources/static/index.html index 378a9849ae..b5bd89a21b 100644 --- a/lecture06/src/main/resources/static/index.html +++ b/lecture06/src/main/resources/static/index.html @@ -1,49 +1,7 @@ - - + + + - -