diff --git a/.tzgox9arysnj004720992~ b/.tzgox9arysnj004720992~ deleted file mode 100644 index e69de29..0000000 diff --git a/Attribution.md b/Attribution.md deleted file mode 100644 index 1bbc6f0..0000000 --- a/Attribution.md +++ /dev/null @@ -1,11 +0,0 @@ -# Attribution - -This document is to credit all designers for their work in svgMotion. - --------------------- - -## Vector Images -Original [Easing icon from onlinewebfonts](https://www.onlinewebfonts.com/icon/433408) -Original [Motion icon from onlinewebfonts](https://www.onlinewebfonts.com/icon/180234) - -The rest of the artwork was designed by [Michael Schwartz](https://michaelsboost.com/). \ No newline at end of file diff --git a/README.md b/README.md index 076cffb..94ac0e1 100644 --- a/README.md +++ b/README.md @@ -8,16 +8,12 @@ I love making vector animations but finding an app to make vector animations on Version ------------- -0.401 +1.000-release To Do: ------------- * Tool to Edit Paths (Bezier Curves), Polygons, Lines and Polylines - * Integrate the ability to render frame by frame animation - * Incorporate controllers to handle character rigging for tweens and frame by frame animation * Integrate filters for user to animate (blur, hue, brightness, contrast, saturate, grayscale, sepia, invert) (adds to element via css: `filter: hue-rotate(119deg) grayscale(30%);`) - * Show group/class list for what's already animated to jump to it (fast way instead of re-selecting those objects again) - * Add help link License ------------- diff --git a/release/android-chrome-192x192.png b/android-chrome-192x192.png similarity index 100% rename from release/android-chrome-192x192.png rename to android-chrome-192x192.png diff --git a/release/android-chrome-512x512.png b/android-chrome-512x512.png similarity index 100% rename from release/android-chrome-512x512.png rename to android-chrome-512x512.png diff --git a/release/apple-touch-icon.png b/apple-touch-icon.png similarity index 100% rename from release/apple-touch-icon.png rename to apple-touch-icon.png diff --git a/dev/index.html b/character-walking.svg similarity index 56% rename from dev/index.html rename to character-walking.svg index 4d82d85..bccff87 100644 --- a/dev/index.html +++ b/character-walking.svg @@ -1,459 +1,4 @@ - - - - - - svgMotion: My Project - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - -
- -
- - + @@ -496,385 +41,39 @@ - + - + - + - + - + - + - + - + - -
-
- - -
-
-
-

Width:

-

Height:

-
-
- - -
- -

Presets:

-
- - - - - - - - - - - - - - - - -
- -

Frames Per Second: (fps)

- - - -
-
-
-

Width:

-

Height:

-
-
- - -
- -

Presets:

-
- - - - - - - - - - - - - - - - -
- -
-

Frames Per Second: (fps):

-

Font Size:

-
-
- - -
- -

Project Name:

- - -

Notepad:

- -
-
- - -
-
-
- -
-
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
-
-
- -
-
- -
-
-
- -
-
-
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/darkkeys.png b/darkkeys.png deleted file mode 100644 index 3c06329..0000000 Binary files a/darkkeys.png and /dev/null differ diff --git a/darklibrary.png b/darklibrary.png deleted file mode 100644 index e156ea7..0000000 Binary files a/darklibrary.png and /dev/null differ diff --git a/darkmain.png b/darkmain.png deleted file mode 100644 index 4db5908..0000000 Binary files a/darkmain.png and /dev/null differ diff --git a/demos/signature-demo.json b/demos/signature-demo.json deleted file mode 100644 index eab0938..0000000 --- a/demos/signature-demo.json +++ /dev/null @@ -1 +0,0 @@ -{"version":0.4,"svg":"\n \n \n \n \n \n \n \n \n \n ","keys":"
g:nth-child(2) > path
g:nth-child(3) > path
rect
","groups":"
  • g > g:nth-child(4) > g
    g > g:nth-child(4) > g
  • g > g:nth-child(2) > path:nth-child(1)
    g > g:nth-child(2) > path:nth-child(1)
  • g > g:nth-child(2) > path:nth-child(2)
    g > g:nth-child(2) > path:nth-child(2)
  • g:nth-child(2) > path
    g:nth-child(2) > path
  • g:nth-child(3) > path
    g:nth-child(3) > path
  • rect
    rect
  • ","settings":[{"theme":"dark","name":"Signature Demo","size":"600x300","fps":"30","selectioncolor":"rgba(52, 52, 62, 1)","swatches":["rgba(239, 154, 154, 1)","rgba(144, 202, 249, 1)","rgba(165, 214, 167, 1)","rgba(255, 245, 157, 1)","rgba(255, 204, 128, 1)","rgba(188, 170, 164, 1)","rgba(238, 238, 238, 1)","rgba(244, 67, 54, 1)","rgba(33, 150, 243, 1)","rgba(76, 175, 80, 1)","rgba(255, 235, 59, 1)","rgba(255, 152, 0, 1)","rgba(121, 85, 72, 1)","rgba(158, 158, 158, 1)"],"notepad":""}]} \ No newline at end of file diff --git a/demos/signature.svg b/demos/signature.svg deleted file mode 100644 index 51dfe9d..0000000 --- a/demos/signature.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/dev/README.md b/dev/README.md deleted file mode 100644 index ec2f99f..0000000 --- a/dev/README.md +++ /dev/null @@ -1,55 +0,0 @@ -svgMotion -=================== - -This version is constantly updating and changing. Note that your project files may unexpectedly not work as this is a dev version NOT an alpha, beta or release candidate. - -You can view the live development page at - https://svgmotion.michaelsboost.repl.co/dev/ - -![](https://raw.githubusercontent.com/michaelsboost/svgMotion/gh-pages/preview.png) - -Version -------------- - -1.000-dev - -License -------------- - -[MIT](https://github.com/michaelsboost/svgMotion/blob/gh-pages/LICENSE) - -Tech -------------- - -svgMotion uses a number of open source projects to work properly: - -* [SweetAlert](https://sweetalert.js.org/guides/) - For the awesome and stylish alert dialogs -* [AlertifyJS](http://alertifyjs.com/) - For the awesome and stylish notification dialogs -* [Font Awesome](https://fontawesome.com/) - a font and icon toolkit -* [GifShot](https://yahoo.github.io/gifshot/) - Library to create gif animations from an image sequence -* [Greensock](https://greensock.com/) - Library responsible for the whole animation process -* [jQuery](http://jquery.com/) - duh -* [JQuery MiniColors](https://labs.abeautifulsite.net/jquery-minicolors/index.html) - For the color picker -* [JSZip](https://stuk.github.io/jszip/) - package zip files in javascript -* [Normalize](https://github.com/necolas/normalize.css) - CSS reset library -* [FileSaver.js](https://github.com/eligrey/FileSaver.js/) - Client-side solution for saving files - -Development -------------- - -Want to contribute? Great! - -You can submit a pull request or simply share the project :) - -Of course svgMotion is free and open source, so you can always fork the project and have fun :) - -[![ko-fi](https://az743702.vo.msecnd.net/cdn/kofi2.png?v=0)](https://ko-fi.com/michaelsboost) - -If svgMotion was at all helpful for you. You can show your appreciation a few ways... - -1) Check out my Graphic Design Course: https://michaelsboost.com/graphicdesign -2) Registering on my store as a customer: https://michaelsboost.com/store -3) Buying me a coffee! http://ko-fi.com/michaelsboost -4) Purchasing one of my t-shirts: https://michaelsboost.com/gear -5) Purchasing any of my art: https://deviantart.com/michaelsboost/prints -6) Donating via PayPal: https://michaelsboost.com/donate -7) Donating via SquareCash: https://cash.me/$michaelsboost \ No newline at end of file diff --git a/dev/css/style.css b/dev/css/style.css deleted file mode 100644 index 40b46fa..0000000 --- a/dev/css/style.css +++ /dev/null @@ -1,839 +0,0 @@ -/* - Version: 1.000-dev - svgMotion, copyright (c) by Michael Schwartz - Distributed under an MIT license: https://github.com/michaelsboost/svgMotion/blob/gh-pages/LICENSE - - This is svgMotion (https://michaelsboost.github.io/svgMotion/), A vector animation tool -*/ - -/* resets */ -@font-face { - font-family: Lato; - src: url("Lato-Light.ttf"); -} -body { - font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 18.45px; - font-weight: 400; - line-height: 20px; -} -a { - cursor: pointer; - text-decoration: none; -} -.alertify-log { - font-size: 14px; - text-shadow: 0 0 #000; -} -.alertify-log-success { -/* background: #1e7eeb;*/ - background: #0ed277; -} -.alertify-log-error { - background: #ec4040; -} -.alertify-log h1, -.alertify-log h5 { - font-weight: 100; -} -.swal2-show h1, .swal2-show h5 { - margin: 20px; - font-weight: 100; -} -button { - background: transparent; - border: 0; -} -input[type=range] { - position: relative; - top: -4px; - width: calc(100vw - 300px); - margin-top: -3.1px; - background-color: transparent; - -webkit-appearance: none; -} -select { - background: transparent; - border: 0; - outline: none; - padding: 0; - font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: 400; - line-height: 20px; - text-transform: capitalize; -} -select option { - background: #fff; - color: #000; - font-weight: 600; -} - -/* Hide Arrows From Input Number */ -/* Chrome, Safari, Edge, Opera */ -input::-webkit-outer-spin-button, -input::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; -} - -/* Hide Arrows From Input Number */ -/* Firefox */ -input[type=number] { - -moz-appearance: textfield; -} - -/* scrollbar */ -::-webkit-scrollbar { - width: 2px; - height: 2px; -} -::-webkit-scrollbar-button { - width: 0; - height: 0; -} -::-webkit-scrollbar-thumb { - background: #1e7eeb; - border: 0; - border-radius: 50px; -} -::-webkit-scrollbar-thumb:hover { - background: #fff; -} -::-webkit-scrollbar-thumb:active { - background: #000; -} -::-webkit-scrollbar-track { - background: #242424; - border: 0 none #fff; - border-radius: 50px; -} -::-webkit-scrollbar-track:hover { - background: #404040; -} -::-webkit-scrollbar-track:active { - background: #1b1b1b; -} -::-webkit-scrollbar-corner { - background: transparent; -} -/* firefox*/ -body, -select, select option { - scrollbar-width: thin; - scrollbar-color: #1e7eeb #2a2e39; -} - -/* input range slider */ -input[type=range]:focus { - outline: none; -} -input[type=range]::-webkit-slider-runnable-track { - background: #282c36; - border: 0; - width: 100%; - height: 1px; - cursor: pointer; -} -input[type=range]::-webkit-slider-thumb { - margin-top: -0.75em; - width: 1.5em; - height: 1.5em; - background: #1e7eeb; - border: 0; - border-radius: 100%; - cursor: pointer; - -webkit-appearance: none; -} -input[type=range]:focus::-webkit-slider-runnable-track { - background: #35353a; -} -input[type=range]::-moz-range-track { - background-color: #282c36; - width: 100%; - height: 1px; - cursor: pointer; -} -input[type=range]::-moz-range-thumb { - margin-top: -0.75em; - width: 1.5em; - height: 1.5em; - background: #1e7eeb; - border: 0; - border-radius: 100%; - cursor: pointer; -} -input[type=range]::-ms-track { - background: transparent; - border-color: transparent; - border-width: 0 0; - color: transparent; - width: 100%; - height: 10px; - cursor: pointer; -} -input[type=range]::-ms-fill-lower { - background: #351d22; - border: 0; -} -input[type=range]::-ms-fill-upper { - background: #351d22; - border: 0; -} -input[type=range]::-ms-thumb { - width: 1.5em; - height: 1.5em; - background: #1e7eeb; - border: 0; - border-radius: 20px; - cursor: pointer; - margin-top: 0; - /*Needed to keep the Edge thumb centred*/ -} -input[type=range]:focus::-ms-fill-lower { - background: #351d22; -} -input[type=range]:focus::-ms-fill-upper { - background: #351d22; -} -/*TODO: Use one of the selectors from https://stackoverflow.com/a/20541859/7077589 and figure out -how to remove the virtical space around the range input in IE*/ -@supports (-ms-ime-align:auto) { - /* Pre-Chromium Edge only styles, selector taken from hhttps://stackoverflow.com/a/32202953/7077589 */ - input[type=range] { - margin: 0; - /*Edge starts the margin from the thumb, not the track as other browsers do*/ - } -} - -/* input[type=number] styles */ -input.numinhead { - background: transparent; - border: 0; - margin: 0; - padding: 0; -} -input.numinhead[type=number] { - width: 75px; - font-size: 4vh; - text-align: center; -} -input.numinhead[type=text] { - width: 150px; -} - -/* SWAL */ -.swal2-icon { - font-size: initial!important; -} -.swal2-icon.swal2-warning, -.swal2-icon.swal2-question { - font-size: inherit!important; - line-height: initial!important; -} -.swal2-icon.swal2-warning > .swal2-icon-text, -.swal2-icon.swal2-question > .swal2-icon-text { - margin: auto; -} -.swal2-popup #swal2-content { - margin-top: 12px; -} - -/* top menu */ -.topmenu { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 30px; - white-space: nowrap; - padding: 10px 0; - z-index: 1; - user-select: none; - overflow: auto; -} -.topmenu > div:not(:first) { - display: none; -} -.topmenu > div, .toolsmenu { - display: flex; - justify-content: space-between; - height: 0; -} -.topmenu img, -.topmenu svg { - cursor: pointer; - fill: currentcolor; - height: 25px; - padding: 0 15px; -} -.topmenu .txt { - position: relative; - top: -3px; -} -.topmenu a.txt { - padding: 1px 6px; -} -.topmenu a { - position: relative; - top: 2px; -} -.topmenu .pointer { - cursor: pointer; -} -svg.checkbox { - position: relative; - top: 4px; - margin: -3px 15px; - height: 25px; - cursor: pointer; - overflow: visible; -} -svg.checkbox path { - transform-origin: center; - transform: scale(1.5) translate(2px, -3px); - stroke: transparent; -} -.librarylinks a { - position: relative; - top: 3px; - padding: 0 calc(3vw); -} -.playback a { - padding: 0 calc(2vw); -} -[data-midbtns] a { - position: relative; - top: 2px; - padding: 0 7px; -} -[data-menubuttons] { - position: relative; - top: -1px; -} - -/* color picker/palette */ -.pcr-button { - display: none; -} -.pcr-app { - display: none; - margin: 0; - width: 0; - height: 0; -} -.pcr-app.visible { - display: flex; - margin: -12px -12px; -/* - width: calc(100vw - 100px); - height: calc(100% - 22px); -*/ - width: calc(100vw - 142px); - height: calc(100% - 5px); -} -.pcr-last-color { - display: none; -} -.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-preview .pcr-current-color { - height: 100%; -} -.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-palette { - height: auto; -} - -/* canvas and dialogs */ -.dialog { - position: absolute; - top: 50px; - left: 0; - right: 0; - bottom: 0; - overflow: auto; -} -.dialog:not([data-canvasbg], .animationtype, .CodeMirror, .CodeMirror *) { - padding: 1em; - font-size: 14px; -} -.dialog[data-canvasbg] { - padding: 0; - background: transparent; -} -[data-canvas] { - line-height: 0; -} -[data-canvas] svg, -[data-dialog=layers] .origsvg svg, -[data-dialog=render] svg { - width: 100%; - height: 100%; -} - -/* dialog */ -.dialogs > .dialog { - display: none; -} -.dialog:not(.colorpicker) h2 { - font-weight: 100; -} -.dialog:not(.colorpicker) input, -.dialog:not(.colorpicker) textarea { - display: block; - margin: 0; - padding: 10px; - resize: none; - border-radius: 0; - outline: 0; - font-size: x-large; - border: 0; - background: transparent; -} -.dimensions { - display: flex; - justify-content: space-between; - flex-direction: row; - flex-wrap: nowrap; -} -.inputs { - display: flex; - justify-content: space-between; -} -.inputs input { - width: calc(50vw - 66px); - padding: 0; - text-align: center; -} -.input { - width: calc(100vw - 50px); -} -.dialog:not(.colorpicker) button { - width: 100%; - padding: 15px 30px; - border: 0; - border-radius: 0.4em; - text-transform: uppercase; - font-size: 0.875em; -/* font-weight: bold;*/ - transition: opacity 0.3s; - display: block; - margin: 1.42857em 0; -} -.dialog:not(.colorpicker) textarea { - width: calc(100vw - 50px); -/* height: calc(100% - 251px);*/ - height: calc(50vh - 130px); - min-height: 100px; - padding: 10px; -} -.dialog:not(.colorpicker) .hscroll { - white-space: nowrap; - overflow: auto; - width: 100%; -} -.dialog:not(.colorpicker) .hscroll button { - display: inline-block; - width: auto; -} -[data-dialog=layers].layers.right { - position: absolute; - top: 50px; - left: 50%; - right: 0; - bottom: 0; -} -[data-dialog=layers].layers ul { - font-family: "Helvetica","Arial",sans-serif; - font-size: 14px; - font-weight: 400; - line-height: 20px; - - list-style: none; - margin: 0; - padding: 0; -} -[data-dialog=layers].layers ul li { - cursor: pointer; - padding: 10px; -} -[data-dialog=keys].timelinewindow.bottom { - position: absolute; - top: 50%; - left: 0; - right: 0; - bottom: 0; -} - -/* bottom menu */ -.props-container { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 85px; - z-index: 1; - overflow: auto; -} -.props-container > .tc > a { - color: #1e7eeb; -} -.props-container > .tc { - text-align: center; -} -.props-container button.addsnippet { - width: calc(100% - 25px); - margin-left: 10px; - margin-right: 10px; -} -.props-container > .selectors > textarea.css { - display: none; -} -.props-container > .selectors > textarea.js { - padding: 10px; - width: calc(100% - 42px); - height: calc(100% - 42px); - border: 0; - background: transparent; - font-size: 14px; -} -.props-container > .selectors { - padding: 10px; - width: calc(100% - 20px); - height: calc(100% - 20px); - border: 0; - background: transparent; -} -.props-container > .selectors input { - font-size: 14px; - padding: 0; - border: 0!important; - display: inline-block; -} -.props-container > .selectors input[type=checkbox] { - float: right; -} -.tl-top { - position: absolute; - bottom: 30px; - left: 0; - right: 0; - height: 30px; - white-space: nowrap; - padding: 10px 0; - z-index: 1; - user-select: none; - overflow: hidden; -} -.tl-top .timeline { - position: relative; - height: 8px; - margin-left: 15px; - margin-right: 15px; - overflow: visible; -} -.tl-top .progress-bar, .tl-top .timeline-track { - height: 8px; - width: 100%; - position: absolute; - top: 0; - left: 0; -} -.tl-top .timeline-track { - background-color: #999; - opacity: .6; -} -.tl-top .progress-bar { - background-color: #3d99ff; - height: 8px; - top: 0; - width: 0; - pointer-events: none; -} -.tl-top .seek-bar { - width: 100%; - position: absolute; - height: 24px; - top: -12px; - left: 0; - background-color: transparent; -} -.tl-top .playhead { - position: absolute; - top: -5px; - transform: translate(-50%,0); - border-radius: 50%; - width: 16px; - height: 16px; - border: 1px solid #3d99ff; - background-color: #3d99ff; - - touch-action: manipulation; - cursor: ew-resize; - user-select: none; - left: 0%; -} - -.tl-bottom { - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 30px; - white-space: nowrap; - padding: 10px 0; - z-index: 1; - user-select: none; - overflow: auto; - - font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 18.45px; - font-weight: 400; - line-height: 20px; -} -.tl-bottom > div:not(:first) { - display: none; -} -.tl-bottom > div { - display: flex; - justify-content: space-between; - height: 0; -} -.tl-bottom svg { - cursor: pointer; - fill: currentcolor; - height: 25px; - padding: 0; - margin: -10px; -} -.tl-bottom .txt { - position: relative; - top: -3px; -} -.tl-bottom a.txt { - padding: 1px 6px; -} -.tl-bottom a { - position: relative; - top: 2px; -} -.tl-bottom .pointer { - cursor: pointer; -} -.tl-bottom select { - font-size: 18.45px; -} -.tl-bottom > div > span:first-child { - position: relative; - top: 4px; - margin-left: 15px; -} -.tl-bottom > div > span:last-child { - position: relative; - top: 8px; - margin-right: 15px; -} -.tl-bottom > div > span > select.timescale { - position: relative; - top: 5px; -} -[data-play] svg { - transform: scale(1.25); - transform-origin: center; -} -[data-repeat=true] path, -[data-repeat=true] circle { - fill: #1e7eeb; -} -[data-delit] svg { - height: 18px; - margin-bottom: -2px; - margin-right: 2px; -} - -/* editor */ -.CodeMirror { - z-index: 0; - font-family: monospace; - font-size: 14px; - font-weight: normal; - display: block; - width: 100%; -} -.CodeMirror, .CodeMirror-gutters { - height: 100%!important; -} -.lint-error { - font-family: arial; - font-size: 70%; - padding: 2px 5px 3px; -} -.lint-error-icon { - font-weight: bold; - border-radius: 50%; - padding: 0 3px; - margin-right: 7px; -} -.CodeMirror .cm-palette-hint { - display: inline-block; - box-sizing: border-box; - margin: -2px 2px 0 6px; - border-radius: 50%; - vertical-align: middle; - width: 10px; - height: 10px; - box-shadow: 0 0 1px 2px #fff, - 0 0 1px 3px #a0a09c; -} -#pickerHolder { - margin-top: 65px; - margin-left: 56px; -/* margin-left: 49px;*/ -} - -/* vertical center */ -.table { - display: table; - position: absolute; - top: 49px; - left: 0; - width: 100%; - height: 100%; -} -.cell { - display: table-cell; - vertical-align: middle; - text-align: center; -} - -/* gif export preloader */ -.preloader svg { - width: 100%; -} -.preloader tspan { - stroke: #666; - stroke-dasharray: 1000; - stroke-dashoffset: 1000; - animation: draw 5s linear alternate infinite; -} -@keyframes draw { - 0% { - stroke-dashoffset: 1000; - } - 100% { - stroke-dashoffset: 0; - } -} - -/* colors */ -body { - background-color: #131722; - background-image: linear-gradient(45deg, #1a1f2c 25%, transparent 25%), linear-gradient(-45deg, #1a1f2c 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #1a1f2c 75%), linear-gradient(-45deg, transparent 75%, #1a1f2c 75%); - background-size: 20px 20px; - background-position: 0 0, 0 10px, 10px -10px, -10px 0px; -} - -/* active tool color = #1e7eeb */ -/* active frame color = #e4eb1e */ - -/* header colors */ -[data-canvasbg], .dialog { - border: 1px solid #1e7eeb; -} - -/* white color */ -.topmenu, -[data-play], [data-playit], -.topmenu a, -.topmenu button, -.dialog:not(.colorpicker), -.dialog:not(.colorpicker) input, -.dialog:not(.colorpicker) textarea, -.dialog:not(.colorpicker) button, -input.numinhead, -.toolsmenu select, -.toolsmenu select option { - color: #fff; -} -.preloader tspan { - stroke: #fff; -} - -/* filter for original blue image */ -.active img { - filter: brightness(1)!important; -} - -/* dark background */ -.topmenu, -.preloaderbg { - background: #030a1e; -} - -/* black background */ -.dialog { - background: #191e2a; -} -input.numinhead, -.toolsmenu select, -.toolsmenu select option { - background: #000; -} - -/* filter for white */ -[data-call=settings] img, -.logo { - fill: currentcolor; - filter: brightness(10); -} -[data-midbtns] img { - fill: currentcolor; - filter: brightness(10); -} - -/* blue color */ -.dialog:not(.colorpicker) input, -.dialog:not(.colorpicker) textarea { - border: 1px solid #1e7eeb; -/* - border: 0; - border-bottom: 1px solid #1e7eeb; -*/ -} -.dialog:not(.colorpicker) button { - background-color: #1e7eeb; -} -.dialog:not(.colorpicker) button.green { - background-color: #19bfa4; -} -.mainmenu a.active, -.mainmenu button.active { - color: #1e7eeb; -} -[data-canvas] { - border: 1px solid #1e7eeb; -} -[data-toolsoption=colorpicker] button.active { - color: #1e7eeb; -} -[data-zoom=true] img { - fill: currentcolor; - filter: brightness(1); -} -.dialog ul li.selector { - color: #1e7eeb; -} - -/* misc colors */ -.spacer { - color: transparent!important; -} -.topmenu [data-donate] { - color: #e85b46; -} -.topmenu [data-render], -.topmenu [data-export], -.topmenu > .mainmenu:not(.keysh) [data-exportzip], -.topmenu .green { - color: #2be71f; -} -[disabled] { - opacity: 0.2; -} \ No newline at end of file diff --git a/dev/js/app.js b/dev/js/app.js deleted file mode 100644 index 03fe824..0000000 --- a/dev/js/app.js +++ /dev/null @@ -1,1759 +0,0 @@ -/* - Version: 1.000-dev - svgMotion, copyright (c) by Michael Schwartz - Distributed under an MIT license: https://github.com/michaelsboost/svgMotion/blob/gh-pages/LICENSE - - This is svgMotion (https://michaelsboost.github.io/svgMotion/), A vector animation tool -*/ - -// variables -var version = '1.000', - counter = 0, - remStr = "html > body > div:nth-child(2) > div > svg > ", - $this, $str, $code, jsStr, origSVG, thisTool, anim, $selector, - detectInt, totalInt, getPerc, arr = [], - loadedJSON = {}, projectJSON = "", - saveAsPNG = function(value) { - saveSvgAsPng(document.querySelector(".canvas > svg"), value + ".png"); - }; - -// init code editor -$('.editor-container').show(); -$('.selectors').hide(); -var editor = CodeMirror(document.getElementById("editor"), { - tabMode: "indent", - theme: 'nord', - styleActiveLine: true, - lineNumbers: true, - lineWrapping: true, - autoCloseTags: true, - foldGutter: true, - dragDrop: true, - lint: false, - autoCloseBrackets: true, - gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], - mode: {name: "javascript", globalVars: false}, - paletteHints: true -}); -Inlet(editor); -editor.on('change', function() { - $('[data-keyselector="'+ elms.value +'"] textarea').val(editor.getValue()).trigger('change'); -}); - -// alertify log -$('[data-log]').on('click', function() { - var val = $(this).attr('data-log'); - alertify.log(val); -}); - -// svgMotion info -$('[data-info]').click(function() { -// alertify.log('

    svgMotion

    Version '+ version +'-dev
    '); - -// swal({ -// html: '

    svgMotion

    Version '+ version +'-dev
    Open Source License' -// }); - swal({ - html: '

    svgMotion

    Version '+ version +'-dev
    Open Source License' - }); -// $('.swal2-show').css('background', '#000'); - $('.swal2-show').css('font-size', '14px'); - $('.swal2-show').css('background', '#131722'); - $('.swal2-show a').css('color', '#3085d6'); - $('.swal2-show h1, .swal2-show h5').css({ - 'font-weight': '100', - 'color': '#fff' - }); -}); - -// init new project -function newProj() { - // first clear the canvas - $('[data-canvas]').empty(); - - // reset project name - $('[data-projectname]').text('My Project'); - - // reset fps - $('[data-fps]').val( $('[data-new=fps]').val() ); - - // clear audio - $('[data-audio]').val(''); - - // clear notepad - $('[data-notepad]').val(''); - - // clear keys - $('[data-dialog=keys]').empty(); - - // reset filters - $('[data-blurfilter]').val(0); - $('[data-huefilter]').val(0); - $('[data-brightnessfilter]').val(1); - $('[data-contrastfilter]').val(1); - $('[data-saturatefilter]').val(1); - $('[data-grayscalefilter]').val(0); - $('[data-sepiafilter]').val(0); - $('[data-invertfilter]').val(0).trigger('change'); -} -$('[data-confirm="newproject"]').click(function() { - swal({ - title: 'Proceed with new project?', - text: "Are you sure? All your data will be lost!", - type: 'question', - showCancelButton: true - }).then((result) => { - if (result.value) { - // initiate a new project - newProj(); - - // close new icon - $('[data-call=new].active').removeClass('active'); - $('[data-dialog=new]').hide(); - - // init zoom tool by default - $('[data-tools=zoom]').trigger('click'); - } else { - return false; - } - }) -}); - -// load file function -function loadfile(input) { - var reader = new FileReader(); - var path = input.value; - reader.onload = function(e) { - if (path.toLowerCase().substring(path.length - 4) === ".svg") { - // is animation playing? If so stop - if ($('[data-play]').attr('data-play') === 'stop') { - // trigger stop - $('[data-play=stop]').trigger('click'); - } - - var keys = $("[data-keyscode]"); - if (keys.find('[data-keyselector]').length > 1) { - swal({ - title: 'Keyframes Detected!', - text: "Would you like to clear these?", - type: 'question', - showCancelButton: true - }).then((result) => { - if (result.value) { - keys.find('[data-keyselector]').not('[data-keyselector=misc]').remove(); - // now update select element (#elms) to reflect cleared keys - $("select#elms option").not('select#elms option[value=misc]').remove(); - keys.find('[data-keyselector=misc]').val('').trigger('change'); - editor.setValue(''); - $('[data-clear=filters]').trigger('click'); - } - }) - } else { - // no keyframes detected - $("select#elms option").not('select#elms option[value=misc]').remove(); - keys.find('[data-keyselector=misc]').val('').trigger('change'); - editor.setValue(''); - $('[data-clear=filters]').trigger('click'); - } - - document.querySelector(".canvas").innerHTML = e.target.result; - origSVG = $('.canvas').html(); - svgLoaded(); - } else if (path.toLowerCase().substring(path.length - 5) === ".json") { - if ($('[data-keys]').html()) { - swal({ - title: 'Keys Detected!', - text: "Would you like to clear these?", - type: 'question', - showCancelButton: true - }).then((result) => { - if (result.value) { - $("[data-keyscode]").empty(); - loadedJSON = JSON.parse(e.target.result); - loadJSON(); - origSVG = $('.canvas').html(); - svgLoaded(); - $('#elms option:last').prop('selected', true).trigger('change'); - $('[data-open=keys]').trigger('click'); - setTimeout(function() { - $('[data-playit=firstframe]').trigger('click'); - }, 100) - - $(document.body).append('
    '); - $("[data-action=fadeOut]").fadeOut(400, function() { - $("[data-action=fadeOut]").remove(); - }); - } - }) - } else { - $("[data-keyscode]").empty(); - loadedJSON = JSON.parse(e.target.result); - loadJSON(); - origSVG = $('.canvas').html(); - svgLoaded(); - $('#elms option:last').prop('selected', true).trigger('change'); - $('[data-open=keys]').trigger('click'); - setTimeout(function() { - $('[data-playit=firstframe]').trigger('click'); - }, 100) - - $(document.body).append('
    '); - $("[data-action=fadeOut]").fadeOut(400, function() { - $("[data-action=fadeOut]").remove(); - }); - } - } else { - alertify.error('Error: File type not supported'); - } - }; - reader.readAsText(input.files[0]); -} -function loadJSON() { - $("#elms").empty(); - $("[data-canvas]").html(loadedJSON.originalSVG.toString()); - $("#elms").html(loadedJSON.elmkeys); - $("[data-keyscode]").html(loadedJSON.keys); - - if (parseFloat(loadedJSON.version) <= 0.1) { - swal({ - title: 'Warning!', - text: "This project is using a version of svgMotion that's no longer supported.", - type: 'warning', - }) - } else - if (parseFloat(version) > parseFloat(loadedJSON.version)) { - swal({ - title: 'Warning!', - text: "This project is using an older version of svgMotion. Some features may not work!", - type: 'warning', - }) - } - - $('#blurfilter').val(loadedJSON.filters[0].blurfilter); - $('#huefilter').val(loadedJSON.filters[0].huefilter); - $('#brightnessfilter').val(loadedJSON.filters[0].brightnessfilter); - $('#contrastfilter').val(loadedJSON.filters[0].contrastfilter); - $('#saturatefilter').val(loadedJSON.filters[0].saturatefilter); - $('#grayscalefilter').val(loadedJSON.filters[0].grayscalefilter); - $('#sepiafilter').val(loadedJSON.filters[0].sepiafilter); - $('#invertfilter').val(loadedJSON.filters[0].invertfilter).trigger('change'); - - $('[data-projectname]').text(loadedJSON.settings[0].name); - $('[data-project=width]').val(loadedJSON.settings[0].width); - $('[data-project=height]').val(loadedJSON.settings[0].height).trigger('change'); - $('[data-fps], [data-new=fps]').val(loadedJSON.settings[0].framerate); - $('[data-fontsize]').val(loadedJSON.settings[0].fontsize); - $('[data-notepad]').val(loadedJSON.settings[0].notepad); -} - -// update document title when project name changes -$('[data-projectname]').on('keyup change', function() { - document.title = 'svgMotion: ' + this.value; -}); - -// detect if selector meets frame by frame animation parameters -function detectForFrameByFrame() { - // first detect if there's a selection - if (!$('[data-selectorlist].selector').is(':visible')) { - $('.librarylinks [data-init]').hide(); - return false; - } else { - $('.librarylinks [data-init]').show(); - } - - // detect that this is the only selector - if ($('[data-selected]').length === 1) { - $('.librarylinks [data-init=framebyframe]').show(); - - // draw is available for these elements - if ($.inArray($('[data-selected]').prop('tagName').toLowerCase(), ['text', 'ellipse', 'circle', 'rect', 'line', 'path', 'textPath', 'polygon', 'polyline']) !== -1) { - $('.librarylinks [data-init=draw]').show(); - } else { - $('.librarylinks [data-init=draw]').hide(); - } - - // if it's the only selector then... - // detect if the children are group elements - $('[data-selected]').find('> *').each(function(index) { - if ($(this).prop('tagName').toLowerCase() != 'g') { - $('.librarylinks [data-init=framebyframe]').hide(); - return false; - } else { - $('.librarylinks [data-init=framebyframe]').show(); - } - }); - - // only show frame by frame if there's an array of only group children - if ($('[data-selected]').children().length === 0) { - $('.librarylinks [data-init=framebyframe]').hide(); - return false; - } - } else { - // hide because this is not the only selector - $('.librarylinks [data-init=framebyframe]').hide(); - $('.librarylinks [data-init=draw]').hide(); - } -} -var svgLoaded = function() { - // clear canvas from layers window - $('[data-display=selector]').empty(); - - // locate SVG - var $Canvas = document.querySelector(".canvas > svg"); - if ($Canvas) { - // canvas interactive selection - canvasClickSelect(); - - // remove width/height attributes if detected - if ($Canvas.getAttribute("width") || $Canvas.getAttribute("height")) { - w = $Canvas.viewBox.baseVal.width; - h = $Canvas.viewBox.baseVal.height; - $("[data-project=width]").val(w); - $("[data-project=height]").val(h).trigger('change'); - $Canvas.removeAttribute("width"); - $Canvas.removeAttribute("height"); - alertify.log("Width/Height attributes removed for fullscreen display."); - } - - $(".canvas > svg *").removeAttr("vector-effect"); -// $(".canvas > svg").attr("preserveAspectRatio", "xMidYMin"); - - $(document.body).append('
    '); - $("[data-action=fadeOut]").fadeOut(400, function() { - $("[data-action=fadeOut]").remove(); - }); - $("[data-projectname]").trigger("keyup"); - - // list all elements as list - var fullSVGlength = $(".canvas svg *").length; - $(".canvas svg *").each(function(i) { -// $val = $(this).getPath(); - $val = $(this).getPath().split(remStr).join(''); - - // append layers - $elm = '
  • ' + $val + '
  • '; - $('[data-display=selector]').append($elm); - - // trigger selected element on layer click - if (i === parseInt(fullSVGlength - 1)) { - $("[data-selectorlist]").on('click', function() { - $val = $(this).data('selectorlist'); - - // single or an array? user selects - $(this).toggleClass('selector'); - $str = ""; - - // clear canvas selector(s) - if ($('[data-selected]').is(':visible')) { - $("[data-selected]").removeAttr("data-selected"); - } - - if ($('[data-selectorlist].selector').is(':visible')) { - // show tween and framebyframe init buttons - $('.librarylinks [data-init]').show(); - } else { - // hide tween and framebyframe init buttons - $('.librarylinks [data-init]').hide(); - } - - // render selectors in canvas - $('[data-selectorlist].selector').each(function() { - if ($str === "") { - $str = ".canvas svg > " + $(this).find('span').text(); - } else { - $str += ", .canvas svg > " + $(this).find('span').text(); - } - $($str).attr("data-selected", ""); - - // only show animation frame by frame init button if parameters are met - detectForFrameByFrame(); - }); - return false; - }); - } - }); - - origSVG = $('.canvas').html(); - } else { - alertify.error("Error: No svg element detected!"); - } -} -svgLoaded(); - -// canvas interactive selection -function canvasClickSelect() { - $('.canvas svg *').on('click', function() { - // is library visible? if so proceed - if ($('.libraryh').is(':visible') && $('[data-zoom=false]').is(':visible')) { - // is selected already visible? If so remove to select active one - if ($('[data-selected]').is(':visible')) { - $("[data-selected]").removeAttr("data-selected"); - $(this).attr('data-selected', ''); - - // display selection in library - $('[data-display=selector] li').removeClass('selector'); - - // remember selector(s) via string - $str = ""; - - // activate selection in libary from canvas - $(".canvas svg [data-selected]").each(function() { - $str = $(this).getPath().split(remStr).join(''); - $('[data-selectorlist]').each(function() { - if ($(this).find('span').text() === $str) { - $(this).addClass('selector'); - } - }); - }); - - // show tween and framebyframe init buttons - $('.librarylinks [data-init]').show(); - - // only show frame by frame if there's an array of only group children - detectForFrameByFrame(); - } else { - $(this).attr('data-selected', ''); - - // display selection in library - $('[data-display=selector] li').removeClass('selector'); - - // remember selector(s) via string - $str = ""; - - // activate selection in libary from canvas - $(".canvas svg [data-selected]").each(function() { - $str = $(this).getPath().split(remStr).join(''); - $('[data-selectorlist]').each(function() { - if ($(this).find('span').text() === $str) { - $(this).addClass('selector'); - } - }); - }); - - // show tween and framebyframe init buttons - $('.librarylinks [data-init]').show(); - - // only show frame by frame if there's an array of only group children - detectForFrameByFrame(); - } - } - return false; - }); -} - -// size presets -$('[data-size]').on('click', function() { - str = $(this).attr('data-size'); - w = str.substr(0, str.indexOf('x')); - h = str.substring(str.length, str.indexOf('x') + 1); - - $('[data-new=width]').val(w); - $('[data-new=height]').val(h); -}); -$('[data-projectsize]').on('click', function() { - str = $(this).attr('data-projectsize'); - w = str.substr(0, str.indexOf('x')); - h = str.substring(str.length, str.indexOf('x') + 1); - - $('[data-project=width]').val(w); - $('[data-project=height]').val(h).trigger('change'); -}); -$('[data-project=width], [data-project=height]').on('change', function() { - $('[data-canvas]').css('width', $('[data-project=width]').val() + 'px'); - $('[data-canvas]').css('height', $('[data-project=height]').val() + 'px'); -}); - -// init panzoom -var drawArea = document.querySelector('[data-canvas]'); -var instance = panzoom(drawArea, { - bounds: true, - boundsPadding: 0.1 -}); - -// toggle dialogs -function openDialog(dialog) { - // detect active tool - $('[data-dialogs] [data-dialog]').hide(); - $('[data-dialogs] [data-dialog='+ dialog.toString().toLowerCase() +']').show(); -} -function closeDialogs() { - $('[data-dialogs] [data-dialog]').hide(); -} -$('[data-call]').on('click', function(val) { - thisTool = $(this).attr('data-call').toString().toLowerCase(); - val = thisTool; - - // if tool is not active - if (!$('[data-call].active').is(':visible')) { - $(this).addClass('active'); - openDialog(val); - } else { - // if tool is active - // are you clicking on same tool or not? - $(this).each(function(i) { - // if you are remove the class - if ($('[data-call].active').attr('data-call').toString().toLowerCase() === thisTool) { - $('[data-call].active').removeClass('active'); - closeDialogs() - - // if not remove the class from the original and then add it - } else { - $('[data-call].active').removeClass('active'); - $(this).addClass('active'); - openDialog(val); - } - }); - } -}); - -// tools -// layers -$('[data-open=layers]').on('click', function() { - $('[data-topmenu] .mainmenu').hide(); - $('[data-library]').show(); - $('[data-canvasbg]').css('right', '50%'); - $('[data-canvasbg]').css('border-right', '0'); - - // render selector(s) in canvas - $('[data-selectorlist].selector').each(function() { - if ($str === "") { - $str = ".canvas svg > " + $(this).find('span').text(); - } else { - $str += ", .canvas svg > " + $(this).find('span').text(); - } - $($str).attr("data-selected", ""); - }); -}); -$('[data-close=layers]').on('click', function() { - $('[data-open=layers].active').removeClass('active'); - $('[data-topmenu] .mainmenu').hide(); - $('[data-dialog=layers]').hide(); - $('[data-mainmenu]').show(); - $('[data-canvasbg]').css('right', ''); - $('[data-canvasbg]').css('border', ''); - $('[data-selected]').removeAttr("data-selected"); -}); -$('[data-init=draw]').on('click', function() { - swal({ - title: 'Give your animation a name!', - input: 'text', - inputPlaceholder: "something", - showCancelButton: true, - confirmButtonText: 'Save', - showLoaderOnConfirm: true - }).then((result) => { - if (result.value) { - $this = $('#elms option:selected').text(); - if ($('[data-keyname='+ result.value.toString().toLowerCase() +']').length === 1) { - alertify.error('Error: That name already exists!'); - $('#elms option:selected').text($this); - } else { - counter++; - - // append the option - $('#elms').append(''); - - // now append the code - $('[data-keyscode]').append('
    '); - $('#elms option[value="'+ $('[data-selectorlist].selector').text() +'"]').prop('selected', true); - } - - alertify.success('Successfully added the "'+ result.value +'" drawPath animation.'); - - // close layers and open the newly added keyframe - $('[data-close=layers]').trigger('click'); - $('[data-open=keys]').trigger('click'); - } else { - swal( - 'Oops!', - console.error().toString(), - 'error' - ); - } - }); -}); -$('[data-init=tween]').on('click', function() { - if ($('[data-selectorlist].selector').length === 1) { -// if ($('[data-selected]')[0].tagName.toLowerCase() === 'path' || $('[data-selected]')[0].tagName.toLowerCase() === 'polygon' || $('[data-selected]')[0].tagName.toLowerCase() === 'line') { -//// $('[data-open=editpath]').removeClass('hide'); -// } else { -//// $('[data-open=editpath]').addClass('hide'); -// } - - $selector = '.svgmotion ' + $('[data-selectorlist].selector').text(); - - swal({ - title: 'Give your tween a name!', - input: 'text', - inputPlaceholder: "something", - showCancelButton: true, - confirmButtonText: 'Save', - showLoaderOnConfirm: true - }).then((result) => { - if (result.value) { - $this = $('#elms option:selected').text(); - if ($('[data-keyname='+ result.value.toString().toLowerCase() +']').length === 1) { - alertify.error('Error: That name already exists!'); - $('#elms option:selected').text($this); - } else { - // append the option - $('#elms').append(''); - - // now append the code - $('[data-keyscode]').append('
    '); - // $('#elms option[value="'+ $('[data-selectorlist].selector').text() +'"]')[0].selected = true; - $('#elms option[value="'+ $selector +'"]').prop('selected', true); - } - - alertify.success('Successfully added the "'+ result.value +'" tween.'); - - // close layers and open the newly added keyframe - $('[data-close=layers]').trigger('click'); - $('[data-open=keys]').trigger('click'); - } else { - swal( - 'Oops!', - console.error().toString(), - 'error' - ); - } - }); - } else { - arr = []; - $('[data-selectorlist].selector').each(function() { - arr.push('.svgmotion ' + this.textContent); - }); - $selector = arr.join(', '); - - swal({ - title: 'Give your tween a name!', - input: 'text', - inputPlaceholder: "something", - showCancelButton: true, - confirmButtonText: 'Save', - showLoaderOnConfirm: true - }).then((result) => { - if (result.value) { - $this = $('#elms option:selected').text(); - if ($('[data-keyname='+ result.value.toString().toLowerCase() +']').length === 1) { - alertify.error('Error: That name already exists!'); - $('#elms option:selected').text($this); - } else { - // append the option - $('#elms').append(''); - - // now append the code - $('[data-keyscode]').append('
    '); - // $('#elms option[value="'+ $('[data-selectorlist].selector').text() +'"]')[0].selected = true; - $('#elms option[value="'+ $selector +'"]').prop('selected', true); - } - - alertify.success('Successfully added the "'+ result.value +'" tween.'); - - // close layers and open the newly added keyframe - $('[data-close=layers]').trigger('click'); - $('[data-open=keys]').trigger('click'); - } else { - swal( - 'Oops!', - console.error().toString(), - 'error' - ); - } - }); - } -}); -$('[data-init=framebyframe]').on('click', function() { - swal({ - title: 'Give your animation a name!', - input: 'text', - inputPlaceholder: "something", - showCancelButton: true, - confirmButtonText: 'Save', - showLoaderOnConfirm: true - }).then((result) => { - if (result.value) { - $this = $('#elms option:selected').text(); - if ($('[data-keyname='+ result.value.toString().toLowerCase() +']').length === 1) { - alertify.error('Error: That name already exists!'); - $('#elms option:selected').text($this); - } else { - counter++; - - // append the option - $('#elms').append(''); - - // now append the code - $('[data-keyscode]').append('
    '); - $('#elms option[value="'+ $('[data-selectorlist].selector').text() +'"]').prop('selected', true); - } - - alertify.success('Successfully added the "'+ result.value +'" frame by frame animation.'); - - // close layers and open the newly added keyframe - $('[data-close=layers]').trigger('click'); - $('[data-open=keys]').trigger('click'); - } else { - swal( - 'Oops!', - console.error().toString(), - 'error' - ); - } - }); -}); - -// keyframes -$('[data-add=snippet]').click(function() { - var addSnippet = "mainTL.to('"+ elms.value +"', {\n x: 0,\n y: 0,\n scaleX: 1,\n scaleY: 1,\n scale: 1,\n rotation: 0,\n transformOrigin: 'center center',\n opacity: '100%',\n fill: #fff,\n stroke: #fff,\n strokeWidth: 0,\n borderRadius: 0,\n // eases: none, power1, power2, power3, power4, back, elastic, bounce, rough, slow, steps, circ, expo, and sine\n ease: 'power1.inOut',\n duration: 1,\n delay: 0,\n motionPath: {path: \"path\"},\n attr: {d: \"m84.75,23.25l1,1l131,128l-129,121l-3,2l0,-252z\"},\n onStart: function() {\n // call function onstart\n },\n onComplete: function() {\n // call function oncomplete\n },\n onUpdate: function() {\n // call function onupdate\n }\n}, 0.0)"; - - $('[data-keyselector="'+ elms.value +'"] textarea').val($('[data-keyselector="'+ elms.value +'"] textarea').val() + '\n\n' + addSnippet); - editor.setValue($('[data-keyselector="'+ elms.value +'"] textarea').val()); -// $('[data-add=snippet]').hide(); -}); -$('[data-open=keys]').on('click', function() { - $('[data-topmenu] .mainmenu').hide(); - $('[data-keys]').show(); - $('[data-canvasbg]').css('bottom', '50%'); - $('[data-canvasbg]').css('border-bottom', '0'); - $('[data-selected]').removeAttr("data-selected"); - - // only show the selectable key's value - $('#elms').trigger('change'); - editor.setValue($('[data-keyselector="'+ elms.value +'"] textarea').val()); -}); -$('[data-close=keys]').on('click', function() { - $('[data-open=keys].active').removeClass('active'); - $('[data-topmenu] .mainmenu').hide(); - $('[data-dialog=keys]').hide(); - $('[data-mainmenu]').show(); - $('[data-canvasbg]').css('bottom', ''); - $('[data-canvasbg]').css('border', ''); -}); -$('#elms').on('keyup change', function() { - $('[data-keyselector]').hide(); - $('[data-keyselector="'+ this.value +'"]').show(); - - // hide sample snippet button if frame by frame is visible - if ($('[data-keyselector="'+ this.value +'"]').attr('data-animtype').toLowerCase() === 'framebyframe' || $('[data-keyselector="'+ this.value +'"]').attr('data-animtype').toLowerCase() === 'drawpath') { - $('[data-add=snippet]').hide(); - } else { - $('[data-add=snippet]').show(); - } - - // set code editor value - editor.setValue($('[data-keyselector="'+ elms.value +'"] textarea').val()); -// mainTL.progress(parseFloat(getDecimal).toFixed(2)); - $('[data-playit=nextframe]').trigger('click'); - $('[data-playit=prevframe]').trigger('click'); -}); - -// selectors for layers -$('[data-select]').on('click', function() { - $val = $(this).data('select'); - - if ($val === 'all') { - if (!$('[data-selected]').is(':visible')) { - $('[data-display=selector] li').trigger('click'); - - // remember selector(s) via string - $str = ""; - - // render selector(s) in canvas - $('[data-selectorlist].selector').each(function() { - if ($str === "") { - $str = ".canvas svg > " + $(this).find('span').text(); - } else { - $str += ", .canvas svg > " + $(this).find('span').text(); - } - $($str).attr("data-selected", ""); - }); - return false; - } - - // select all the same tags inside the same parent - $('[data-selected]').each(function() { - var tagNombre = $('[data-selected]').prop("tagName").toLowerCase(); - $(this).removeAttr("data-selected").parent().find(tagNombre).attr("data-selected", ""); - }); - - // remember selector(s) via string - $str = ""; - - // activate selection in libary from canvas - $(".canvas svg [data-selected]").each(function() { - $str = $(this).getPath().split(remStr).join(''); - $('[data-selectorlist]').each(function() { - if ($(this).find('span').text() === $str) { - $(this).addClass('selector'); - } - }); - }); - - detectForFrameByFrame(); - } else - if ($val === 'none') { - $('[data-display=selector] li').removeClass('selector'); - - // clear canvas selector(s) - if ($('[data-selected]').is(':visible')) { - $("[data-selected]").removeAttr("data-selected"); - } - - // hide tween and framebyframe init buttons - $('.librarylinks [data-init]').hide(); - return false; - } else - if ($val === 'parent') { - if ($('.canvas svg > [data-selected]').is(':visible')) { - alertify.error('Error: Cannot select higher than the svg itself.'); - return false; - } - - if (!$('[data-selected]').is(':visible')) { - $('[data-display=selector] li').trigger('click'); - - // remember selector(s) via string - $str = ""; - - // render selector(s) in canvas - $('[data-selectorlist].selector').each(function() { - if ($str === "") { - $str = ".canvas svg > " + $(this).find('span').text(); - } else { - $str += ", .canvas svg > " + $(this).find('span').text(); - } - $($str).attr("data-selected", ""); - }); - return false; - } - - $('[data-display=selector] li').removeClass('selector'); - - // select all the same tags inside the same parent - $('[data-selected]').each(function() { - $(this).removeAttr("data-selected").parent().attr("data-selected", ""); - return false; - }); - - // remember selector(s) via string - $str = ""; - - // activate selection in libary from canvas - $(".canvas svg [data-selected]").each(function() { - $str = $(this).getPath().split(remStr).join(''); - $('[data-selectorlist]').each(function() { - if ($(this).find('span').text() === $str) { - $(this).addClass('selector'); - return false; - } - }); - }); - - detectForFrameByFrame(); - return false; - } else - if ($val === 'next') { - if (!$('[data-selected]').is(':visible')) { - $('[data-display=selector] li').trigger('click'); - - // remember selector(s) via string - $str = ""; - - // render selector(s) in canvas - $('[data-selectorlist].selector').each(function() { - if ($str === "") { - $str = ".canvas svg > " + $(this).find('span').text(); - } else { - $str += ", .canvas svg > " + $(this).find('span').text(); - } - $($str).attr("data-selected", ""); - }); - return false; - } - - $('[data-display=selector] li').removeClass('selector'); - - // select all the same tags inside the same parent - $('[data-selected]').each(function() { - $(this).removeAttr("data-selected").next().attr("data-selected", ""); - }); - - // remember selector(s) via string - $str = ""; - - // activate selection in libary from canvas - $(".canvas svg [data-selected]").each(function() { - $str = $(this).getPath().split(remStr).join(''); - $('[data-selectorlist]').each(function() { - if ($(this).find('span').text() === $str) { - $(this).addClass('selector'); - } - }); - }); - - detectForFrameByFrame(); - return false; - } else - if ($val === 'prev') { - if (!$('[data-selected]').is(':visible')) { - $('[data-display=selector] li').trigger('click'); - - // remember selector(s) via string - $str = ""; - - // render selector(s) in canvas - $('[data-selectorlist].selector').each(function() { - if ($str === "") { - $str = ".canvas svg > " + $(this).find('span').text(); - } else { - $str += ", .canvas svg > " + $(this).find('span').text(); - } - $($str).attr("data-selected", ""); - }); - return false; - } - - $('[data-display=selector] li').removeClass('selector'); - - // select all the same tags inside the same parent - $('[data-selected]').each(function() { - $(this).removeAttr("data-selected").prev().attr("data-selected", ""); - }); - - // remember selector(s) via string - $str = ""; - - // activate selection in libary from canvas - $(".canvas svg [data-selected]").each(function() { - $str = $(this).getPath().split(remStr).join(''); - $('[data-selectorlist]').each(function() { - if ($(this).find('span').text() === $str) { - $(this).addClass('selector'); - } - }); - }); - - detectForFrameByFrame(); - return false; - } else - if ($val === 'even') { - if (!$('[data-selected]').is(':visible')) { - $('[data-display=selector] li:even').trigger('click'); - - // remember selector(s) via string - $str = ""; - - // render selector(s) in canvas - $('[data-selectorlist].selector').each(function() { - if ($str === "") { - $str = ".canvas svg > " + $(this).find('span').text(); - } else { - $str += ", .canvas svg > " + $(this).find('span').text(); - } - $($str).attr("data-selected", ""); - }); - return false; - } - - $('[data-display=selector] li').removeClass('selector'); - - // select all the same tags inside the same parent - $('[data-selected]').each(function() { - var tagNombre = $('[data-selected]').prop("tagName").toLowerCase(); - $(this).removeAttr("data-selected").parent().find(tagNombre + ":even").attr("data-selected", ""); - }); - - // remember selector(s) via string - $str = ""; - - // activate selection in libary from canvas - $(".canvas svg [data-selected]").each(function() { - $str = $(this).getPath().split(remStr).join(''); - $('[data-selectorlist]').each(function() { - if ($(this).find('span').text() === $str) { - $(this).addClass('selector'); - } - }); - }); - - detectForFrameByFrame(); - } else - if ($val === 'odd') { - if (!$('[data-selected]').is(':visible')) { - $('[data-display=selector] li:odd').trigger('click'); - - // remember selector(s) via string - $str = ""; - - // render selector(s) in canvas - $('[data-selectorlist].selector').each(function() { - if ($str === "") { - $str = ".canvas svg > " + $(this).find('span').text(); - } else { - $str += ", .canvas svg > " + $(this).find('span').text(); - } - $($str).attr("data-selected", ""); - }); - return false; - } - - $('[data-display=selector] li').removeClass('selector'); - - // select all the same tags inside the same parent - $('[data-selected]').each(function() { - var tagNombre = $('[data-selected]').prop("tagName").toLowerCase(); - $(this).removeAttr("data-selected").parent().find(tagNombre + ":odd").attr("data-selected", ""); - }); - - // remember selector(s) via string - $str = ""; - - // activate selection in libary from canvas - $(".canvas svg [data-selected]").each(function() { - $str = $(this).getPath().split(remStr).join(''); - $('[data-selectorlist]').each(function() { - if ($(this).find('span').text() === $str) { - $(this).addClass('selector'); - } - }); - }); - - detectForFrameByFrame(); - } else - if ($val === 'custom') { - swal({ - title: 'Custom selector', - input: 'text', - showCancelButton: true - }).then((result) => { - if (result.value) { - // remove currect selection(s) - $('[data-display=selector] li').removeClass('selector'); - - // clear canvas selector(s) - if ($('[data-selected]').is(':visible')) { - $("[data-selected]").removeAttr("data-selected"); - } - - // user's custom selector - $elm = result.value.split(',').join(', .canvas svg > '); - - // activate selection in canvas - $(".canvas svg > " + $elm).each(function() { - $str = $(this).getPath().split(remStr).join(''); - $(this).attr("data-selected", ""); - }); - - // activate selection in libary from canvas - $(".canvas svg [data-selected]").each(function() { - $str = $(this).getPath().split(remStr).join(''); - $('[data-selectorlist]').each(function() { - if ($(this).find('span').html() === $str) { - $(this).addClass('selector'); - } - }); - }); - - return false; - } - }); - - detectForFrameByFrame(); - } else { - alertify.error('Selection error'); - } - - // clear canvas selector(s) - if ($('[data-selected]').is(':visible')) { - $("[data-selected]").removeAttr("data-selected"); - } - - // remember selector(s) via string - $str = ""; - - // render selector(s) in canvas - $('[data-selectorlist].selector').each(function() { - if ($str === "") { - $str = ".canvas svg > " + $(this).find('span').text(); - } else { - $str += ", .canvas svg > " + $(this).find('span').text(); - } - $($str).attr("data-selected", ""); - - // show tween and framebyframe init buttons - detectForFrameByFrame(); - }); -}); - -// filters -$('[data-open=filters]').on('click', function() { - if ($('[data-call].active').is(':visible')) { - $('[data-call].active').trigger('click'); - } - $('[data-topmenu] .mainmenu').hide(); - $('[data-filtericons]').show(); -}); -$('[data-filter]').on('click', function() { - $this = $(this).attr('data-filter'); - $('[data-topmenu] .mainmenu').hide(); - $('[data-toolsoption]').hide(); - $('[data-filters]').show(); - $('[data-toolsoption='+ $this +']').show(); -}); -$('[data-close=filters]').on('click', function() { - $('[data-topmenu] .mainmenu').hide(); - $('[data-mainmenu]').show(); -}); -$('[data-close=filter]').on('click', function() { - $('[data-topmenu] .mainmenu').hide(); - $('[data-filtericons]').show(); -}); -$('[data-clear=filters]').on('click', function() { - $('.canvas svg').css('filter', ''); - $('[data-canvas] svg').css('filter', ''); - blurfilter.value = 0; - huefilter.value = 0; - brightnessfilter.value = 1; - contrastfilter.value = 1; - saturatefilter.value = 1; - grayscalefilter.value = 0; - sepiafilter.value = 0; - invertfilter.value = 0; - - $('[data-close=filters]').trigger('click'); - applyFilters(); -}); - -// apply filters -function applyFilters() { - $('[data-canvas] svg').css('filter', 'blur('+ blurfilter.value +'px) hue-rotate('+ huefilter.value +'deg) brightness('+ brightnessfilter.value +') contrast('+ contrastfilter.value +') saturate('+ saturatefilter.value +') grayscale('+ grayscalefilter.value +'%) sepia('+ sepiafilter.value +'%) invert('+ invertfilter.value +'%)'); -} -$('.filterval').change(function() { - applyFilters(); -}); -applyFilters(); - -// zoom/pan -$('[data-zoom]').on('click', function() { - if ($(this).attr('data-zoom') === 'true') { - $('[data-zoom]').attr('data-zoom', false) - .html(''); - $('[data-resetzoompos]').hide(); - instance.pause(); - canvasClickSelect(); - } else { - $('[data-zoom]').attr('data-zoom', true) - .html(''); - $('[data-resetzoompos]').show(); - instance.resume(); - } -}); -// reset zoom position -$('[data-resetzoompos]').click(function() { - $('[data-canvas]').css('transform-origin', '') - .css('transform', ''); - instance.restore(); -}); - -// init the player -function updateCode() { - // clear the variables - jsStr = ''; - - // apply the javascript - $('textarea.js').each(function() { - jsStr += $(this).val() + '\n'; - }); - -// $code = 'var mainTL = new TimelineMax({repeat: -1, onUpdate: function() {\n time.textContent = parseFloat(mainTL.progress()).toFixed(2)}})\n' + jsStr + 'var fps = '+ $('[data-fps]').val() +';\nvar duration = mainTL.duration();\nvar frames = Math.ceil(duration / 1 * fps);\nmainTL.pause('+ time.textContent +').timeScale('+ timescale.value +');\n$("[data-timeduration]").text(parseFloat(mainTL.duration()).toFixed(2))'; - - if ($('[data-repeat]').attr('data-repeat') === 'true') { - $code = 'var mainTL = new TimelineMax({repeat: -1, onUpdate: function() {\n time.textContent = parseFloat(mainTL.progress()).toFixed(2)}})\n' + jsStr + 'var fps = '+ $('[data-fps]').val() +';\nvar duration = mainTL.duration();\nvar frames = Math.ceil(duration / 1 * fps);\nmainTL.pause('+ time.textContent +').timeScale('+ timescale.value +');\n$("[data-timeduration]").text(parseFloat(mainTL.duration()).toFixed(2))'; - } else { - $code = 'var mainTL = new TimelineMax({onUpdate: function() {\n time.textContent = parseFloat(mainTL.progress()).toFixed(2)}, onComplete: function() {$("[data-play]").trigger("click")}})\n' + jsStr + 'var fps = '+ $('[data-fps]').val() +';\nvar duration = mainTL.duration();\nvar frames = Math.ceil(duration / 1 * fps);\nmainTL.pause('+ time.textContent +').timeScale('+ timescale.value +');\n$("[data-timeduration]").text(parseFloat(mainTL.duration()).toFixed(2))'; - } - - // run the code - $('[data-canvas]').empty().html(origSVG); - applyFilters(); - $('[data-canvas]').append(''); - updatePlayer(); - - detectInt = parseFloat(time.textContent).toFixed(2); - totalInt = parseFloat($('[data-timeduration]').text()).toFixed(2); - getPerc = (detectInt * 100) / totalInt; - getPerc = Math.round(getPerc); - getDecimal = parseFloat(getPerc) / 100; - mainTL.progress(parseFloat(getDecimal).toFixed(2)); - return false; -} -$('#timescale').on('change', function() { - if ($('[data-play]').attr('data-play') === 'true') { - // is paused - updateCode(); - } else { - // is playing - $('[data-play]').trigger('click'); - updateCode(); - $('[data-play]').trigger('click'); - } -}); - -function updatePlayer() { - $(".playhead").removeAttr('style'); - - var $sequenceTime = $("#time"), - sequenceTrackLength, - sequenceDragger, - draggable; - - mainTL.eventCallback("onUpdate", updateDragger) - sequenceTrackLength = $('.seek-bar').width(); - sequenceDragger = $(".playhead"); - draggable = Draggable.create(sequenceDragger, { - type:"x", -// edgeResistance: 1, -// overshootTolerance: 0, - bounds:{minX:0, maxX:sequenceTrackLength}, - onDrag: function() { - mainTL.progress(this.x / sequenceTrackLength).pause(); - } - })[0]; - - function updateDragger() { - TweenMax.set(sequenceDragger, {x:sequenceTrackLength * mainTL.progress()}) - $sequenceTime.html(mainTL.time().toFixed(2)) - - detectInt = parseFloat(time.textContent).toFixed(2); - totalInt = parseFloat($('[data-timeduration]').text()).toFixed(2); - getPerc = (detectInt * 100) / totalInt; - getPerc = Math.round(getPerc); - getDecimal = parseFloat(getPerc) / 100; - - $('.progress-bar').css('width', getPerc + '%'); - } -} - -// timeline buttons -$('[data-play]').on('click', function() { - if ($(this).attr('data-play') === 'true') { - // pause state - $('[data-play]').attr('data-play', false) - .html(''); - -// // stop symbol -// .html(''); - $('[data-render]').show(); - - if(mainTL.progress() < 1) { - mainTL.play(); - } else { - mainTL.restart(); - $('.playhead').attr('style', 'left: 0%;'); - } - - } else { - // play state - $('[data-play]').attr('data-play', true) - .html(''); - $('[data-render]').hide(); - mainTL.pause(); - } -}); -$('[data-playit=firstframe]').click(function() { - time.textContent = '0.00'; -// mainTL.seek(0); - mainTL.progress(0); -// $('.progress-bar').css('width', '0%'); -}); -$('[data-playit=nextframe]').click(function() { - // detect if is already last frame - if ($('[data-timeduration]').text() === time.textContent) { - $('[data-playit=firstframe]').trigger('click'); - return false; - } - - if (parseFloat(time.textContent).toFixed(2) >= 0 || time.textContent < parseFloat(mainTL.progress()).toFixed(2)) { -// time.textContent = parseFloat(0.01 + parseFloat(mainTL.progress())).toFixed(2); - time.textContent = parseFloat(0.01 + parseFloat(time.textContent)).toFixed(2); -// mainTL.seek(parseFloat(time.textContent)); - - detectInt = parseFloat(time.textContent).toFixed(2); - totalInt = parseFloat($('[data-timeduration]').text()).toFixed(2); - getPerc = (detectInt * 100) / totalInt; - getPerc = Math.round(getPerc); - getDecimal = parseFloat(getPerc) / 100; - mainTL.progress(parseFloat(getDecimal).toFixed(2)); -// $('.progress-bar').css('width', getPerc + '%'); - } -}); -$('[data-playit=prevframe]').click(function() { - // detect if is already first frame - if (time.textContent === '0.00') { - $('[data-playit=lastframe]').trigger('click'); - return false; - } - - if (parseFloat(time.textContent).toFixed(2) > 0 || time.textContent > parseFloat(mainTL.progress()).toFixed(2)) { -// time.textContent = parseFloat(parseFloat(mainTL.progress()) - 0.01).toFixed(2); - time.textContent = parseFloat(parseFloat(time.textContent - 0.01)).toFixed(2); -// mainTL.seek(parseFloat(time.textContent)); - - detectInt = parseFloat(time.textContent).toFixed(2); - totalInt = parseFloat($('[data-timeduration]').text()).toFixed(2); - getPerc = (detectInt * 100) / totalInt; - getPerc = Math.round(getPerc); - getDecimal = parseFloat(getPerc) / 100; - mainTL.progress(parseFloat(getDecimal).toFixed(2)); -// $('.progress-bar').css('width', getPerc + '%'); - } -}); -$('[data-playit=lastframe]').click(function() { - time.textContent = $('[data-timeduration]').text(); -// mainTL.seek(time.textContent); - mainTL.progress(1); -// $('.progress-bar').css('width', '100%'); -}); -$('[data-repeat]').on('click', function() { - if ($(this).attr('data-repeat') === 'true') { - // no loop - $('[data-repeat]').attr('data-repeat', false); - $('textarea.js').trigger('change'); - } else { - // repeat/loop - $('[data-repeat]').attr('data-repeat', true); - $('textarea.js').trigger('change'); - } -}); -$('[data-delit]').click(function() { - swal({ - title: 'Proceed with deleting tween?', - text: "Are you sure? All your data will be lost!", - type: 'question', - showCancelButton: true - }).then((result) => { - if (result.value) { - // remove the div - $('.selectors [data-keyselector="'+ elms.value +'"]').remove(); - - // lastly remove the select option - $('#elms option:selected').remove(); - $('#elms').trigger('change'); - } else { - return false; - } - }) -}); -$('[data-editname]').click(function() { - swal({ - title: 'Change tween name?', - input: 'text', - inputPlaceholder: "something", - showCancelButton: true, - confirmButtonText: 'Save', - showLoaderOnConfirm: true - }).then((result) => { - if (result.value) { - $this = $('#elms option:selected').text(); - $('#elms option').each(function() { - if ($(this).text() != result.value) { - $('#elms option:selected').text(result.value); - } else { - alertify.error('Error: That name already exists!'); - $('#elms option:selected').text($this); - return false; - } - }); - } else { - swal( - 'Oops!', - console.error().toString(), - 'error' - ); - } - }); -}); - -// enable/disable snippet presets -$('.props > div > div > input[type=checkbox]').on('change', function() { - if (this.checked) { - $(this).parent().find('input').removeAttr('disabled'); - $(this).parent().find('select').removeAttr('disabled'); - } else { - $(this).parent().find('input:not(input[type=checkbox])').attr('disabled', true); - $(this).parent().find('select').attr('disabled', true); - } -}); - -// change input/textarea font size -$('[data-fontsize]').on('keyup change', function() { - $('input, textarea, .CodeMirror').css('font-size', this.value + 'px'); -}); - -// init animations -function getCode() { - // clear the variables - jsStr = ''; - - // clear and reset the canvas - $('[data-canvas]').empty().html(origSVG); - applyFilters(); - - // apply the javascript - $('textarea.js').each(function() { - jsStr += $(this).val() + '\n'; - }); - -// $code = 'var mainTL = new TimelineMax({repeat: -1})\n' + jsStr + 'var fps = '+ $('[data-fps]').val() +';\nvar duration = mainTL.duration();\nvar frames = Math.ceil(duration / 1 * fps);\nmainTL.play(0).timeScale('+ timescale.value +');\n'; -// $code = 'var mainTL = new TimelineMax('+ ($('[data-repeat]').attr('data-repeat') === 'true') ? "{repeat: -1}" : "" +')\n' + jsStr + 'var fps = '+ $('[data-fps]').val() +';\nvar duration = mainTL.duration();\nvar frames = Math.ceil(duration / 1 * fps);\nmainTL.play(0).timeScale('+ timescale.value +');\n'; - - if ($('[data-repeat]').attr('data-repeat') === 'true') { - $code = 'var mainTL = new TimelineMax({repeat: -1})\n' + jsStr + 'var fps = '+ $('[data-fps]').val() +';\nvar duration = mainTL.duration();\nvar frames = Math.ceil(duration / 1 * fps);\nmainTL.play(0).timeScale('+ timescale.value +');\n'; - } else { - $code = 'var mainTL = new TimelineMax()\n' + jsStr + 'var fps = '+ $('[data-fps]').val() +';\nvar duration = mainTL.duration();\nvar frames = Math.ceil(duration / 1 * fps);\nmainTL.play(0).timeScale('+ timescale.value +');\n'; - } -} -function render() { -// alertify.log("coming soon..."); -// return false; - - if (!$("[data-canvas]").html()) { - alertify.error("Abort Operation: No svg detected!"); - return false; - } - - // if animation is already playing - if ($('[data-play=false]').is(':visible')) { - $('[data-play=false]').trigger('click') - } - - getCode(); - if (jsStr.toString().split(' ').join('').toLowerCase().includes('repeat:-1')) { - alertify.error("Error: Indefinite repeat found!"); - alertify.error("Do NOT use repeat: -1"); - alertify.error("Use a specific number!!"); - $('.playback').show(); - $('[data-render]').hide(); - return false; - } - - if ($('[data-render]')[0].textContent.toLowerCase() === 'render') { - // hide settings - $('[data-call=settings] img').css({ - width: 0, - padding: 0, - overflow: 'hidden' - }); - - $('[data-midbtns]').hide(); - $('[data-export]').show(); - $('[data-render]').text('RENDERING ANIMATION').css('color', '#e71fd8'); - - // close keys - $('[data-close=keys]').trigger('click'); - - $('[data-canvas]').empty().html(origSVG); - applyFilters(); - $('[data-canvas]').append(''); - setTimeout(function() { - var fps = $("[data-fps]").val(); - var duration = mainTL.duration(); -// var duration = tl.totoalDuration(); -// var duration = tl.totalDuration(); - var frames = Math.ceil(duration / 1 * fps); - var current = 0; - - // canvas - var svg = document.querySelector("[data-canvas] svg"); - var canvas = document.createElement("canvas"); - var ctx = canvas.getContext("2d"); - - canvas.width = $("[data-project=width]").val(); - canvas.height = $("[data-project=height]").val(); - var jsonStr = []; - - function processImage() { - mainTL.progress(current++ / frames); - - var xml = new XMLSerializer().serializeToString(svg); - var blob = window.btoa(xml); - var img = new Image(); - img.src = "data:image/svg+xml;base64," + blob; - - img.crossOrigin = "Anonymous"; - img.onload = function() { - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.drawImage(this, 0, 0); - var imgType = canvas.toDataURL("image/png"); - var image = new Image(); - image.src = imgType; - jsonStr.push(imgType); - - // export gif animation - document.querySelector("[data-export=gif]").onclick = function() { - $("body").append('
    Creating GIF
    '); - - gifshot.createGIF({ - images: jsonStr, - gifWidth: canvas.width, - gifHeight: canvas.height, - interval: fps / 1000, // seconds - progressCallback: function(captureProgress) { console.log('progress: ', captureProgress); }, - completeCallback: function() { console.log('completed!!!'); }, - numWorkers: 2, - },function(obj) { - if(!obj.error) { - var a = document.createElement("a"); - a.href = obj.image; - a.target = "_blank"; - - if (a.download === undefined) { - // do stuff - } else { - var projectname = $("[data-projectname]")[0].value.toLowerCase().replace(/ /g, "-") - if (!$("[data-projectname]")[0].value.toLowerCase().replace(/ /g, "-")) { - projectname = $("[data-projectname]")[0].value = "_svgMotion"; - } - - if (bowser.msie && bowser.version <= 6) { - // hello ie - } else if (bowser.firefox) { - // hello firefox - a.download = projectname + ".gif"; - } else if (bowser.chrome) { - // hello chrome - a.download = projectname + ".gif"; - } else if (bowser.safari) { - // hello safari - } else if(bowser.iphone || bowser.android) { - // hello mobile - } - } - - a.click(); - - $("[data-show=preloader]").remove(); - } - } - ); - }; - - // export image sequence - document.querySelector("[data-export=images]").onclick = function() { - var zip = new JSZip(); - - for (var i = 0; i < jsonStr.length; i++) { - zip.file("frame-"+[i]+".png", jsonStr[i].split('base64,')[1],{base64: true}); - } - - var content = zip.generate({type:"blob"}); - var projectname = $("[data-projectname]")[0].value.toLowerCase().replace(/ /g, "-") - if (!$("[data-projectname]")[0].value.toLowerCase().replace(/ /g, "-")) { - projectname = $("[data-projectname]")[0].value = "_svgMotion"; - } - saveAs(content, projectname + "-sequence.zip"); - }; - }; - - if (current <= frames) { - processImage(); - } else { - mainTL.play(0).timeScale(1.0); - } - } - processImage(); - }, 2); - } else { - // reset icons - $('[data-export]').hide(); - $('[data-midbtns]').show(); - - // stop animation - $('.playback').show(); - // play state - // if animation is already playing - if ($('[data-play=false]').is(':visible')) { - $('[data-play=false]').trigger('click') - } - updateCode(); - - // reset icon - $('[data-render]').text('RENDER').attr('style', ''); - - // show settings - $('[data-call=settings] img').removeAttr('style'); - - $('[data-render]').hide(); - } -} -$('[data-render]').click(function() { - render(); -}); - -// export files -function getProjectJSON() { - projectJSON = { - "version": version, - "settings": [{ - "name" : $('[data-projectname]')[0].textContent, - "width" : $('[data-project=width]').val(), - "height" : $('[data-project=height]').val(), - "framerate": $('[data-fps]').val(), - "fontsize" : $('[data-fontsize]').val(), - "notepad" : $('[data-notepad]').val() - }], - "filters": [{ - "blurfilter" : blurfilter.value, - "huefilter" : huefilter.value, - "brightnessfilter": brightnessfilter.value, - "contrastfilter" : contrastfilter.value, - "saturatefilter" : saturatefilter.value, - "grayscalefilter" : grayscalefilter.value, - "sepiafilter" : sepiafilter.value, - "invertfilter" : invertfilter.value - }], - "originalSVG": origSVG.toString(), - "elmkeys": $("#elms").html(), - "keys" : $("[data-keyscode]").html() - }; -}; -function saveCode(filename) { - JSZipUtils.getBinaryContent("libraries/gsap/gsap-public.zip", function(err, data) { - if(err) { - throw err // or handle err - } - - var zip = new JSZip(); - - // Put all application files in subfolder for shell script - var zipFolder = zip.folder("libraries"); - zipFolder.load(data); - - // html - // run the code - $('[data-canvas]').empty().html(origSVG); - applyFilters(); - - zip.file("index.html", '\n\n \n '+ filename +': An svgMotion Animation\n \n \n \n \n \n \n
    \n '+ $('.svgmotion').html() +'\n
    \n\n \n \n \n'); - - // javascript - $code = ''; - $('textarea.js').each(function() { - $code += this.value + '\n'; - }); - - if ($('[data-repeat]').attr('data-repeat') === 'true') { - $code = '/*\n This animation was created using svgMotion v'+ version.toString() +'\n Create yours today at https://michaelsboost.com/svgMotion\n*/\n\nvar mainTL = new TimelineMax({\n repeat: -1\n})\n\n' + $code + '\nvar fps = '+ $('[data-fps]').val() +';\nvar duration = mainTL.duration();\nvar frames = Math.ceil(duration / 1 * fps);\nmainTL.play(0).timeScale('+ timescale.value +');' - } else { - $code = '/*\n This animation was created using svgMotion v'+ version.toString() +'\n Create yours today at https://michaelsboost.com/svgMotion\n*/\n\nvar mainTL = new TimelineMax()\n\n' + $code + '\nvar fps = '+ $('[data-fps]').val() +';\nvar duration = mainTL.duration();\nvar frames = Math.ceil(duration / 1 * fps);\nmainTL.play(0).timeScale('+ timescale.value +');' - } - - zip.file("js/animation.js", $code); - var content = zip.generate({type:"blob"}); - saveAs(content, filename + ".zip"); - $('textarea.js').trigger('change'); - }); -} -function exportSVGFrame() { - var projectname = $("[data-projectname]")[0].value.toLowerCase().replace(/ /g, "-") + "-frame-" + time.textContent; - if (!$("[data-projectname]")[0].value.toLowerCase().replace(/ /g, "-")) { - projectname = $("[data-projectname]")[0].value = "-frame-" + time.textContent; - } - blob = new Blob([ '\n' + $(".canvas").html() ], {type: "text/html"}); - saveAs(blob, projectname + ".svg"); -}; -function exportPNGFrame() { - var projectname = $("[data-projectname]")[0].value.toLowerCase().replace(/ /g, "-") + "-frame-" + time.textContent; - if (!$("[data-projectname]")[0].value.toLowerCase().replace(/ /g, "-")) { - projectname = $("[data-projectname]")[0].value = "-frame-" + time.textContent; - } - saveAsPNG(projectname); -}; -function exportJSON() { - getProjectJSON(); - var projectname = $('[data-projectname]')[0].value.toLowerCase().replace(/ /g, "-") + '_svgMotion'; - if (!$('[data-projectname]')[0].value.toLowerCase().replace(/ /g, "-")) { - projectname = $('[data-projectname]')[0].value = "_svgMotion"; - } - var blob = new Blob([JSON.stringify(projectJSON)], {type: "application/json;charset=utf-8"}); - saveAs(blob, projectname + ".json"); -}; -$('[data-project=export]').on('click', function() { - exportJSON(); -}); -$('[data-exportframe=svg]').on('click', function() { - $(".canvas style").remove(); - $(".canvas script").remove(); - exportSVGFrame(); -// updatePreview(); -}); -$('[data-exportframe=png]').on('click', function() { - exportPNGFrame(); -// updatePreview(); -}); -$('[data-exportzip]').on('click', function() { - // if animation is playing stop it - $('[data-play=false]').trigger('click'); - - var projectname = $("[data-projectname]")[0].value.toLowerCase().replace(/ /g, "-"); - if (!$("[data-projectname]")[0].value.toLowerCase().replace(/ /g, "-")) { - projectname = $("[data-projectname]")[0].value = "_svgMotion"; - } else { - projectname = projectname + '_svgMotion'; - } - saveCode(projectname); -}); - -// hide tools options onload -$('[data-toolsmenu]').hide(); -$('[data-toolsmenu] [data-toolsoption]').hide(); - -// hide dialogs onload -$('[data-dialogs] [data-dialog]').hide(); -$('[data-tools=zoom]').trigger('click'); - -function initDemo() { - // set the canvas size - $('[data-project=width]').val(1280); - $('[data-project=height]').val(800); - $('[data-canvas]').css('width', $('[data-project=width]').val() + 'px'); - $('[data-canvas]').css('height', $('[data-project=height]').val() + 'px'); - - // clear and reset the canvas - $('[data-canvas]').empty().html(origSVG); - - // reset setting inputs - $('[data-projectname]').val('Character Walking').trigger('change'); - $('[data-notepad]').val('This demo demonstrates frame by frame animation utilized with tween-based animations.'); - - // init filters - blurfilter.value = 0; - huefilter.value = -6; - brightnessfilter.value = 0.76; - contrastfilter.value = 1.8; - saturatefilter.value = 1; - grayscalefilter.value = 0; - sepiafilter.value = 30; - invertfilter.value = 0; - applyFilters(); - - $('[data-call=layers]').trigger('click'); - $('[data-selectorlist] span').filter(function() { - if (this.textContent === 'g > g:nth-child(4)') { - $(this).trigger('click'); - } else { - return false; - } - }); - // frame by frame animation string adds " > g" - $('[data-close=layers]').trigger('click'); - - // lower font-size - $('[data-fontsize]').val(12).trigger('change'); -} - -// bot -initDemo(); -$('[data-call=keys]').trigger('click'); - diff --git a/dev/js/browsersupport.js b/dev/js/browsersupport.js deleted file mode 100644 index 82de26d..0000000 --- a/dev/js/browsersupport.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - Version: 1.000-dev - svgMotion, copyright (c) by Michael Schwartz - Distributed under an MIT license: https://github.com/michaelsboost/svgMotion/blob/gh-pages/LICENSE - - This is svgMotion (https://michaelsboost.github.io/svgMotion/), A vector animation tool -*/ - -// Detect browser support onload -function unsupportedBrowser() { - alertify.error("Error: You are using an unsupported browser!"); - setTimeout(function() { - alertify.log('We recommend using the most recent version of Google Chrome'); - }, 2000); -} -if (bowser.msie && bowser.version <= 6) { - // hello ie - unsupportedBrowser(); -} else if (bowser.firefox) { - // hello firefox - unsupportedBrowser(); -} else if (bowser.chrome) { - // hello chrome -} else if (bowser.safari) { - // hello safari - unsupportedBrowser(); -} else if(bowser.iphone || bowser.android) { - // hello mobile - unsupportedBrowser(); -} \ No newline at end of file diff --git a/dev/js/getPath.js b/dev/js/getPath.js deleted file mode 100644 index e909caf..0000000 --- a/dev/js/getPath.js +++ /dev/null @@ -1,34 +0,0 @@ -jQuery.fn.extend({ - getPath: function() { - var pathes = []; - - this.each(function(index, element) { - var path, $node = jQuery(element); - - while ($node.length) { - var realNode = $node.get(0), name = realNode.localName; - if (!name) { break; } - - name = name.toLowerCase(); - var parent = $node.parent(); - var sameTagSiblings = parent.children(name); - - if (sameTagSiblings.length > 1) - { - var allSiblings = parent.children(); - var index = allSiblings.index(realNode) + 1; - if (index > 0) { - name += ':nth-child(' + index + ')'; - } - } - - path = name + (path ? ' > ' + path : ''); - $node = parent; - } - - pathes.push(path); - }); - - return pathes.join(','); - } -}); \ No newline at end of file diff --git a/dev/libraries/alertifyjs/alertify.core.css b/dev/libraries/alertifyjs/alertify.core.css deleted file mode 100644 index 12d82dd..0000000 --- a/dev/libraries/alertifyjs/alertify.core.css +++ /dev/null @@ -1,137 +0,0 @@ -.alertify, -.alertify-show, -.alertify-log { - -webkit-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); - -moz-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); - -ms-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); - -o-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); - transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); /* easeOutBack */ -} -.alertify-hide { - -webkit-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); - -moz-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); - -ms-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); - -o-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); - transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); /* easeInBack */ -} -.alertify-log-hide { - -webkit-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); - -moz-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); - -ms-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); - -o-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); - transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); /* easeInBack */ -} -.alertify-cover { - position: fixed; z-index: 99999; - top: 0; right: 0; bottom: 0; left: 0; - background-color:white; - filter:alpha(opacity=0); - opacity:0; -} - .alertify-cover-hidden { - display: none; - } -.alertify { - position: fixed; z-index: 99999; - top: 50px; left: 50%; - width: 550px; - margin-left: -275px; - opacity: 1; -} - .alertify-hidden { - -webkit-transform: translate(0,-150px); - -moz-transform: translate(0,-150px); - -ms-transform: translate(0,-150px); - -o-transform: translate(0,-150px); - transform: translate(0,-150px); - opacity: 0; - display: none; - } - /* overwrite display: none; for everything except IE6-8 */ - :root *> .alertify-hidden { - display: block; - visibility: hidden; - } -.alertify-logs { - position: fixed; - z-index: 5000; - bottom: 10px; - right: 10px; - width: 300px; -} -.alertify-logs-hidden { - display: none; -} - .alertify-log { - display: block; - margin-top: 10px; - position: relative; - right: -300px; - opacity: 0; - } - .alertify-log-show { - right: 0; - opacity: 1; - } - .alertify-log-hide { - -webkit-transform: translate(300px, 0); - -moz-transform: translate(300px, 0); - -ms-transform: translate(300px, 0); - -o-transform: translate(300px, 0); - transform: translate(300px, 0); - opacity: 0; - } - .alertify-dialog { - padding: 25px; - } - .alertify-resetFocus { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; - } - .alertify-inner { - text-align: center; - } - .alertify-text { - margin-bottom: 15px; - width: 100%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - font-size: 100%; - } - .alertify-buttons { - } - .alertify-button, - .alertify-button:hover, - .alertify-button:active, - .alertify-button:visited { - background: none; - text-decoration: none; - border: none; - /* line-height and font-size for input button */ - line-height: 1.5; - font-size: 100%; - display: inline-block; - cursor: pointer; - margin-left: 5px; - } - -@media only screen and (max-width: 680px) { - .alertify, - .alertify-logs { - width: 90%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .alertify { - left: 5%; - margin: 0; - } -} diff --git a/dev/libraries/alertifyjs/alertify.default.css b/dev/libraries/alertifyjs/alertify.default.css deleted file mode 100644 index 213c632..0000000 --- a/dev/libraries/alertifyjs/alertify.default.css +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Default Look and Feel - */ -.alertify, -.alertify-log { - font-family: sans-serif; -} -.alertify { - background: #FFF; - border: 10px solid #333; /* browsers that don't support rgba */ - border: 10px solid rgba(0,0,0,.7); - border-radius: 8px; - box-shadow: 0 3px 3px rgba(0,0,0,.3); - -webkit-background-clip: padding; /* Safari 4? Chrome 6? */ - -moz-background-clip: padding; /* Firefox 3.6 */ - background-clip: padding-box; /* Firefox 4, Safari 5, Opera 10, IE 9 */ -} - .alertify-text { - border: 1px solid #CCC; - padding: 10px; - border-radius: 4px; - } - .alertify-button { - border-radius: 4px; - color: #FFF; - font-weight: bold; - padding: 6px 15px; - text-decoration: none; - text-shadow: 1px 1px 0 rgba(0,0,0,.5); - box-shadow: inset 0 1px 0 0 rgba(255,255,255,.5); - background-image: -webkit-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0)); - background-image: -moz-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0)); - background-image: -ms-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0)); - background-image: -o-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0)); - background-image: linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0)); - } - .alertify-button:hover, - .alertify-button:focus { - outline: none; - background-image: -webkit-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0)); - background-image: -moz-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0)); - background-image: -ms-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0)); - background-image: -o-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0)); - background-image: linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0)); - } - .alertify-button:focus { - box-shadow: 0 0 15px #2B72D5; - } - .alertify-button:active { - position: relative; - box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); - } - .alertify-button-cancel, - .alertify-button-cancel:hover, - .alertify-button-cancel:focus { - background-color: #FE1A00; - border: 1px solid #D83526; - } - .alertify-button-ok, - .alertify-button-ok:hover, - .alertify-button-ok:focus { - background-color: #5CB811; - border: 1px solid #3B7808; - } - -.alertify-log { - background: #1F1F1F; - background: rgba(0,0,0,.9); - padding: 15px; - border-radius: 4px; - color: #FFF; - text-shadow: -1px -1px 0 rgba(0,0,0,.5); -} - .alertify-log-error { - background: #FE1A00; - background: rgba(254,26,0,.9); - } - .alertify-log-success { - background: #5CB811; - background: rgba(92,184,17,.9); - } \ No newline at end of file diff --git a/dev/libraries/alertifyjs/alertify.js b/dev/libraries/alertifyjs/alertify.js deleted file mode 100644 index 373d32d..0000000 --- a/dev/libraries/alertifyjs/alertify.js +++ /dev/null @@ -1,636 +0,0 @@ -/** - * alertify - * An unobtrusive customizable JavaScript notification system - * - * @author Fabien Doiron - * @copyright Fabien Doiron 2013 - * @license MIT - * @link http://fabien-d.github.com/alertify.js/ - * @module alertify - * @version 0.3.11 - */ -(function (global, undefined) { - "use strict"; - - var document = global.document, - Alertify; - - Alertify = function () { - - var _alertify = {}, - dialogs = {}, - isopen = false, - keys = { ENTER: 13, ESC: 27, SPACE: 32 }, - queue = [], - $, btnCancel, btnOK, btnReset, btnResetBack, btnFocus, elCallee, elCover, elDialog, elLog, form, input, getTransitionEvent; - - /** - * Markup pieces - * @type {Object} - */ - dialogs = { - buttons : { - holder : "", - submit : "", - ok : "", - cancel : "" - }, - input : "
    ", - message : "

    {{message}}

    ", - log : "
    {{message}}
    " - }; - - /** - * Return the proper transitionend event - * @return {String} Transition type string - */ - getTransitionEvent = function () { - var t, - type, - supported = false, - el = document.createElement("fakeelement"), - transitions = { - "WebkitTransition" : "webkitTransitionEnd", - "MozTransition" : "transitionend", - "OTransition" : "otransitionend", - "transition" : "transitionend" - }; - - for (t in transitions) { - if (el.style[t] !== undefined) { - type = transitions[t]; - supported = true; - break; - } - } - - return { - type : type, - supported : supported - }; - }; - - /** - * Shorthand for document.getElementById() - * - * @param {String} id A specific element ID - * @return {Object} HTML element - */ - $ = function (id) { - return document.getElementById(id); - }; - - /** - * Alertify private object - * @type {Object} - */ - _alertify = { - - /** - * Labels object - * @type {Object} - */ - labels : { - ok : "OK", - cancel : "Cancel" - }, - - /** - * Delay number - * @type {Number} - */ - delay : 5000, - - /** - * Whether buttons are reversed (default is secondary/primary) - * @type {Boolean} - */ - buttonReverse : false, - - /** - * Which button should be focused by default - * @type {String} "ok" (default), "cancel", or "none" - */ - buttonFocus : "ok", - - /** - * Set the transition event on load - * @type {[type]} - */ - transition : undefined, - - /** - * Set the proper button click events - * - * @param {Function} fn [Optional] Callback function - * - * @return {undefined} - */ - addListeners : function (fn) { - var hasOK = (typeof btnOK !== "undefined"), - hasCancel = (typeof btnCancel !== "undefined"), - hasInput = (typeof input !== "undefined"), - val = "", - self = this, - ok, cancel, common, key, reset; - - // ok event handler - ok = function (event) { - if (typeof event.preventDefault !== "undefined") event.preventDefault(); - common(event); - if (typeof input !== "undefined") val = input.value; - if (typeof fn === "function") { - if (typeof input !== "undefined") { - fn(true, val); - } - else fn(true); - } - return false; - }; - - // cancel event handler - cancel = function (event) { - if (typeof event.preventDefault !== "undefined") event.preventDefault(); - common(event); - if (typeof fn === "function") fn(false); - return false; - }; - - // common event handler (keyup, ok and cancel) - common = function (event) { - self.hide(); - self.unbind(document.body, "keyup", key); - self.unbind(btnReset, "focus", reset); - if (hasOK) self.unbind(btnOK, "click", ok); - if (hasCancel) self.unbind(btnCancel, "click", cancel); - }; - - // keyup handler - key = function (event) { - var keyCode = event.keyCode; - if ((keyCode === keys.SPACE && !hasInput) || (hasInput && keyCode === keys.ENTER)) ok(event); - if (keyCode === keys.ESC && hasCancel) cancel(event); - }; - - // reset focus to first item in the dialog - reset = function (event) { - if (hasInput) input.focus(); - else if (!hasCancel || self.buttonReverse) btnOK.focus(); - else btnCancel.focus(); - }; - - // handle reset focus link - // this ensures that the keyboard focus does not - // ever leave the dialog box until an action has - // been taken - this.bind(btnReset, "focus", reset); - this.bind(btnResetBack, "focus", reset); - // handle OK click - if (hasOK) this.bind(btnOK, "click", ok); - // handle Cancel click - if (hasCancel) this.bind(btnCancel, "click", cancel); - // listen for keys, Cancel => ESC - this.bind(document.body, "keyup", key); - if (!this.transition.supported) { - this.setFocus(); - } - }, - - /** - * Bind events to elements - * - * @param {Object} el HTML Object - * @param {Event} event Event to attach to element - * @param {Function} fn Callback function - * - * @return {undefined} - */ - bind : function (el, event, fn) { - if (typeof el.addEventListener === "function") { - el.addEventListener(event, fn, false); - } else if (el.attachEvent) { - el.attachEvent("on" + event, fn); - } - }, - - /** - * Use alertify as the global error handler (using window.onerror) - * - * @return {boolean} success - */ - handleErrors : function () { - if (typeof global.onerror !== "undefined") { - var self = this; - global.onerror = function (msg, url, line) { - self.error("[" + msg + " on line " + line + " of " + url + "]", 0); - }; - return true; - } else { - return false; - } - }, - - /** - * Append button HTML strings - * - * @param {String} secondary The secondary button HTML string - * @param {String} primary The primary button HTML string - * - * @return {String} The appended button HTML strings - */ - appendButtons : function (secondary, primary) { - return this.buttonReverse ? primary + secondary : secondary + primary; - }, - - /** - * Build the proper message box - * - * @param {Object} item Current object in the queue - * - * @return {String} An HTML string of the message box - */ - build : function (item) { - var html = "", - type = item.type, - message = item.message, - css = item.cssClass || ""; - - html += "
    "; - html += "Reset Focus"; - - if (_alertify.buttonFocus === "none") html += ""; - - // doens't require an actual form - if (type === "prompt") html += "
    "; - - html += "
    "; - html += dialogs.message.replace("{{message}}", message); - - if (type === "prompt") html += dialogs.input; - - html += dialogs.buttons.holder; - html += "
    "; - - if (type === "prompt") html += "
    "; - - html += "Reset Focus"; - html += "
    "; - - switch (type) { - case "confirm": - html = html.replace("{{buttons}}", this.appendButtons(dialogs.buttons.cancel, dialogs.buttons.ok)); - html = html.replace("{{ok}}", this.labels.ok).replace("{{cancel}}", this.labels.cancel); - break; - case "prompt": - html = html.replace("{{buttons}}", this.appendButtons(dialogs.buttons.cancel, dialogs.buttons.submit)); - html = html.replace("{{ok}}", this.labels.ok).replace("{{cancel}}", this.labels.cancel); - break; - case "alert": - html = html.replace("{{buttons}}", dialogs.buttons.ok); - html = html.replace("{{ok}}", this.labels.ok); - break; - default: - break; - } - - elDialog.className = "alertify alertify-" + type + " " + css; - elCover.className = "alertify-cover"; - return html; - }, - - /** - * Close the log messages - * - * @param {Object} elem HTML Element of log message to close - * @param {Number} wait [optional] Time (in ms) to wait before automatically hiding the message, if 0 never hide - * - * @return {undefined} - */ - close : function (elem, wait) { - // Unary Plus: +"2" === 2 - var timer = (wait && !isNaN(wait)) ? +wait : this.delay, - self = this, - hideElement, transitionDone; - - // set click event on log messages - this.bind(elem, "click", function () { - hideElement(elem); - }); - // Hide the dialog box after transition - // This ensure it doens't block any element from being clicked - transitionDone = function (event) { - event.stopPropagation(); - // unbind event so function only gets called once - self.unbind(this, self.transition.type, transitionDone); - // remove log message - elLog.removeChild(this); - if (!elLog.hasChildNodes()) elLog.className += " alertify-logs-hidden"; - }; - // this sets the hide class to transition out - // or removes the child if css transitions aren't supported - hideElement = function (el) { - // ensure element exists - if (typeof el !== "undefined" && el.parentNode === elLog) { - // whether CSS transition exists - if (self.transition.supported) { - self.bind(el, self.transition.type, transitionDone); - el.className += " alertify-log-hide"; - } else { - elLog.removeChild(el); - if (!elLog.hasChildNodes()) elLog.className += " alertify-logs-hidden"; - } - } - }; - // never close (until click) if wait is set to 0 - if (wait === 0) return; - // set timeout to auto close the log message - setTimeout(function () { hideElement(elem); }, timer); - }, - - /** - * Create a dialog box - * - * @param {String} message The message passed from the callee - * @param {String} type Type of dialog to create - * @param {Function} fn [Optional] Callback function - * @param {String} placeholder [Optional] Default value for prompt input field - * @param {String} cssClass [Optional] Class(es) to append to dialog box - * - * @return {Object} - */ - dialog : function (message, type, fn, placeholder, cssClass) { - // set the current active element - // this allows the keyboard focus to be resetted - // after the dialog box is closed - elCallee = document.activeElement; - // check to ensure the alertify dialog element - // has been successfully created - var check = function () { - if ((elLog && elLog.scrollTop !== null) && (elCover && elCover.scrollTop !== null)) return; - else check(); - }; - // error catching - if (typeof message !== "string") throw new Error("message must be a string"); - if (typeof type !== "string") throw new Error("type must be a string"); - if (typeof fn !== "undefined" && typeof fn !== "function") throw new Error("fn must be a function"); - // initialize alertify if it hasn't already been done - this.init(); - check(); - - queue.push({ type: type, message: message, callback: fn, placeholder: placeholder, cssClass: cssClass }); - if (!isopen) this.setup(); - - return this; - }, - - /** - * Extend the log method to create custom methods - * - * @param {String} type Custom method name - * - * @return {Function} - */ - extend : function (type) { - if (typeof type !== "string") throw new Error("extend method must have exactly one paramter"); - return function (message, wait) { - this.log(message, type, wait); - return this; - }; - }, - - /** - * Hide the dialog and rest to defaults - * - * @return {undefined} - */ - hide : function () { - var transitionDone, - self = this; - // remove reference from queue - queue.splice(0,1); - // if items remaining in the queue - if (queue.length > 0) this.setup(true); - else { - isopen = false; - // Hide the dialog box after transition - // This ensure it doens't block any element from being clicked - transitionDone = function (event) { - event.stopPropagation(); - // unbind event so function only gets called once - self.unbind(elDialog, self.transition.type, transitionDone); - }; - // whether CSS transition exists - if (this.transition.supported) { - this.bind(elDialog, this.transition.type, transitionDone); - elDialog.className = "alertify alertify-hide alertify-hidden"; - } else { - elDialog.className = "alertify alertify-hide alertify-hidden alertify-isHidden"; - } - elCover.className = "alertify-cover alertify-cover-hidden"; - // set focus to the last element or body - // after the dialog is closed - elCallee.focus(); - } - }, - - /** - * Initialize Alertify - * Create the 2 main elements - * - * @return {undefined} - */ - init : function () { - // ensure legacy browsers support html5 tags - document.createElement("nav"); - document.createElement("article"); - document.createElement("section"); - // cover - if ($("alertify-cover") == null) { - elCover = document.createElement("div"); - elCover.setAttribute("id", "alertify-cover"); - elCover.className = "alertify-cover alertify-cover-hidden"; - document.body.appendChild(elCover); - } - // main element - if ($("alertify") == null) { - isopen = false; - queue = []; - elDialog = document.createElement("section"); - elDialog.setAttribute("id", "alertify"); - elDialog.className = "alertify alertify-hidden"; - document.body.appendChild(elDialog); - } - // log element - if ($("alertify-logs") == null) { - elLog = document.createElement("section"); - elLog.setAttribute("id", "alertify-logs"); - elLog.className = "alertify-logs alertify-logs-hidden"; - document.body.appendChild(elLog); - } - // set tabindex attribute on body element - // this allows script to give it focus - // after the dialog is closed - document.body.setAttribute("tabindex", "0"); - // set transition type - this.transition = getTransitionEvent(); - }, - - /** - * Show a new log message box - * - * @param {String} message The message passed from the callee - * @param {String} type [Optional] Optional type of log message - * @param {Number} wait [Optional] Time (in ms) to wait before auto-hiding the log - * - * @return {Object} - */ - log : function (message, type, wait) { - // check to ensure the alertify dialog element - // has been successfully created - var check = function () { - if (elLog && elLog.scrollTop !== null) return; - else check(); - }; - // initialize alertify if it hasn't already been done - this.init(); - check(); - - elLog.className = "alertify-logs"; - this.notify(message, type, wait); - return this; - }, - - /** - * Add new log message - * If a type is passed, a class name "alertify-log-{type}" will get added. - * This allows for custom look and feel for various types of notifications. - * - * @param {String} message The message passed from the callee - * @param {String} type [Optional] Type of log message - * @param {Number} wait [Optional] Time (in ms) to wait before auto-hiding - * - * @return {undefined} - */ - notify : function (message, type, wait) { - var log = document.createElement("article"); - log.className = "alertify-log" + ((typeof type === "string" && type !== "") ? " alertify-log-" + type : ""); - log.innerHTML = message; - // append child - elLog.appendChild(log); - // triggers the CSS animation - setTimeout(function() { log.className = log.className + " alertify-log-show"; }, 50); - this.close(log, wait); - }, - - /** - * Set properties - * - * @param {Object} args Passing parameters - * - * @return {undefined} - */ - set : function (args) { - var k; - // error catching - if (typeof args !== "object" && args instanceof Array) throw new Error("args must be an object"); - // set parameters - for (k in args) { - if (args.hasOwnProperty(k)) { - this[k] = args[k]; - } - } - }, - - /** - * Common place to set focus to proper element - * - * @return {undefined} - */ - setFocus : function () { - if (input) { - input.focus(); - input.select(); - } - else btnFocus.focus(); - }, - - /** - * Initiate all the required pieces for the dialog box - * - * @return {undefined} - */ - setup : function (fromQueue) { - var item = queue[0], - self = this, - transitionDone; - - // dialog is open - isopen = true; - // Set button focus after transition - transitionDone = function (event) { - event.stopPropagation(); - self.setFocus(); - // unbind event so function only gets called once - self.unbind(elDialog, self.transition.type, transitionDone); - }; - // whether CSS transition exists - if (this.transition.supported && !fromQueue) { - this.bind(elDialog, this.transition.type, transitionDone); - } - // build the proper dialog HTML - elDialog.innerHTML = this.build(item); - // assign all the common elements - btnReset = $("alertify-resetFocus"); - btnResetBack = $("alertify-resetFocusBack"); - btnOK = $("alertify-ok") || undefined; - btnCancel = $("alertify-cancel") || undefined; - btnFocus = (_alertify.buttonFocus === "cancel") ? btnCancel : ((_alertify.buttonFocus === "none") ? $("alertify-noneFocus") : btnOK), - input = $("alertify-text") || undefined; - form = $("alertify-form") || undefined; - // add placeholder value to the input field - if (typeof item.placeholder === "string" && item.placeholder !== "") input.value = item.placeholder; - if (fromQueue) this.setFocus(); - this.addListeners(item.callback); - }, - - /** - * Unbind events to elements - * - * @param {Object} el HTML Object - * @param {Event} event Event to detach to element - * @param {Function} fn Callback function - * - * @return {undefined} - */ - unbind : function (el, event, fn) { - if (typeof el.removeEventListener === "function") { - el.removeEventListener(event, fn, false); - } else if (el.detachEvent) { - el.detachEvent("on" + event, fn); - } - } - }; - - return { - alert : function (message, fn, cssClass) { _alertify.dialog(message, "alert", fn, "", cssClass); return this; }, - confirm : function (message, fn, cssClass) { _alertify.dialog(message, "confirm", fn, "", cssClass); return this; }, - extend : _alertify.extend, - init : _alertify.init, - log : function (message, type, wait) { _alertify.log(message, type, wait); return this; }, - prompt : function (message, fn, placeholder, cssClass) { _alertify.dialog(message, "prompt", fn, placeholder, cssClass); return this; }, - success : function (message, wait) { _alertify.log(message, "success", wait); return this; }, - error : function (message, wait) { _alertify.log(message, "error", wait); return this; }, - set : function (args) { _alertify.set(args); }, - labels : _alertify.labels, - debug : _alertify.handleErrors - }; - }; - - // AMD and window support - if (typeof define === "function") { - define([], function () { return new Alertify(); }); - } else if (typeof global.alertify === "undefined") { - global.alertify = new Alertify(); - } - -}(this)); diff --git a/dev/libraries/bowser/bowser.min.js b/dev/libraries/bowser/bowser.min.js deleted file mode 100644 index 5c5d373..0000000 --- a/dev/libraries/bowser/bowser.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bowser - a browser detector - * https://github.com/ded/bowser - * MIT License | (c) Dustin Diaz 2015 - */ -!function(e,t,n){typeof module!="undefined"&&module.exports?module.exports=n():typeof define=="function"&&define.amd?define(t,n):e[t]=n()}(this,"bowser",function(){function t(t){function n(e){var n=t.match(e);return n&&n.length>1&&n[1]||""}function r(e){var n=t.match(e);return n&&n.length>1&&n[2]||""}function C(e){switch(e){case"NT":return"NT";case"XP":return"XP";case"NT 5.0":return"2000";case"NT 5.1":return"XP";case"NT 5.2":return"2003";case"NT 6.0":return"Vista";case"NT 6.1":return"7";case"NT 6.2":return"8";case"NT 6.3":return"8.1";case"NT 10.0":return"10";default:return undefined}}var i=n(/(ipod|iphone|ipad)/i).toLowerCase(),o=/like android/i.test(t),u=!o&&/android/i.test(t),a=/nexus\s*[0-6]\s*/i.test(t),f=!a&&/nexus\s*[0-9]+/i.test(t),l=/CrOS/.test(t),c=/silk/i.test(t),h=/sailfish/i.test(t),p=/tizen/i.test(t),d=/(web|hpw)(o|0)s/i.test(t),v=/windows phone/i.test(t),m=/SamsungBrowser/i.test(t),g=!v&&/windows/i.test(t),y=!i&&!c&&/macintosh/i.test(t),b=!u&&!h&&!p&&!d&&/linux/i.test(t),w=r(/edg([ea]|ios)\/(\d+(\.\d+)?)/i),E=n(/version\/(\d+(\.\d+)?)/i),S=/tablet/i.test(t)&&!/tablet pc/i.test(t),x=!S&&/[^-]mobi/i.test(t),T=/xbox/i.test(t),N;/opera/i.test(t)?N={name:"Opera",opera:e,version:E||n(/(?:opera|opr|opios)[\s\/](\d+(\.\d+)?)/i)}:/opr\/|opios/i.test(t)?N={name:"Opera",opera:e,version:n(/(?:opr|opios)[\s\/](\d+(\.\d+)?)/i)||E}:/SamsungBrowser/i.test(t)?N={name:"Samsung Internet for Android",samsungBrowser:e,version:E||n(/(?:SamsungBrowser)[\s\/](\d+(\.\d+)?)/i)}:/Whale/i.test(t)?N={name:"NAVER Whale browser",whale:e,version:n(/(?:whale)[\s\/](\d+(?:\.\d+)+)/i)}:/MZBrowser/i.test(t)?N={name:"MZ Browser",mzbrowser:e,version:n(/(?:MZBrowser)[\s\/](\d+(?:\.\d+)+)/i)}:/coast/i.test(t)?N={name:"Opera Coast",coast:e,version:E||n(/(?:coast)[\s\/](\d+(\.\d+)?)/i)}:/focus/i.test(t)?N={name:"Focus",focus:e,version:n(/(?:focus)[\s\/](\d+(?:\.\d+)+)/i)}:/yabrowser/i.test(t)?N={name:"Yandex Browser",yandexbrowser:e,version:E||n(/(?:yabrowser)[\s\/](\d+(\.\d+)?)/i)}:/ucbrowser/i.test(t)?N={name:"UC Browser",ucbrowser:e,version:n(/(?:ucbrowser)[\s\/](\d+(?:\.\d+)+)/i)}:/mxios/i.test(t)?N={name:"Maxthon",maxthon:e,version:n(/(?:mxios)[\s\/](\d+(?:\.\d+)+)/i)}:/epiphany/i.test(t)?N={name:"Epiphany",epiphany:e,version:n(/(?:epiphany)[\s\/](\d+(?:\.\d+)+)/i)}:/puffin/i.test(t)?N={name:"Puffin",puffin:e,version:n(/(?:puffin)[\s\/](\d+(?:\.\d+)?)/i)}:/sleipnir/i.test(t)?N={name:"Sleipnir",sleipnir:e,version:n(/(?:sleipnir)[\s\/](\d+(?:\.\d+)+)/i)}:/k-meleon/i.test(t)?N={name:"K-Meleon",kMeleon:e,version:n(/(?:k-meleon)[\s\/](\d+(?:\.\d+)+)/i)}:v?(N={name:"Windows Phone",osname:"Windows Phone",windowsphone:e},w?(N.msedge=e,N.version=w):(N.msie=e,N.version=n(/iemobile\/(\d+(\.\d+)?)/i))):/msie|trident/i.test(t)?N={name:"Internet Explorer",msie:e,version:n(/(?:msie |rv:)(\d+(\.\d+)?)/i)}:l?N={name:"Chrome",osname:"Chrome OS",chromeos:e,chromeBook:e,chrome:e,version:n(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i)}:/edg([ea]|ios)/i.test(t)?N={name:"Microsoft Edge",msedge:e,version:w}:/vivaldi/i.test(t)?N={name:"Vivaldi",vivaldi:e,version:n(/vivaldi\/(\d+(\.\d+)?)/i)||E}:h?N={name:"Sailfish",osname:"Sailfish OS",sailfish:e,version:n(/sailfish\s?browser\/(\d+(\.\d+)?)/i)}:/seamonkey\//i.test(t)?N={name:"SeaMonkey",seamonkey:e,version:n(/seamonkey\/(\d+(\.\d+)?)/i)}:/firefox|iceweasel|fxios/i.test(t)?(N={name:"Firefox",firefox:e,version:n(/(?:firefox|iceweasel|fxios)[ \/](\d+(\.\d+)?)/i)},/\((mobile|tablet);[^\)]*rv:[\d\.]+\)/i.test(t)&&(N.firefoxos=e,N.osname="Firefox OS")):c?N={name:"Amazon Silk",silk:e,version:n(/silk\/(\d+(\.\d+)?)/i)}:/phantom/i.test(t)?N={name:"PhantomJS",phantom:e,version:n(/phantomjs\/(\d+(\.\d+)?)/i)}:/slimerjs/i.test(t)?N={name:"SlimerJS",slimer:e,version:n(/slimerjs\/(\d+(\.\d+)?)/i)}:/blackberry|\bbb\d+/i.test(t)||/rim\stablet/i.test(t)?N={name:"BlackBerry",osname:"BlackBerry OS",blackberry:e,version:E||n(/blackberry[\d]+\/(\d+(\.\d+)?)/i)}:d?(N={name:"WebOS",osname:"WebOS",webos:e,version:E||n(/w(?:eb)?osbrowser\/(\d+(\.\d+)?)/i)},/touchpad\//i.test(t)&&(N.touchpad=e)):/bada/i.test(t)?N={name:"Bada",osname:"Bada",bada:e,version:n(/dolfin\/(\d+(\.\d+)?)/i)}:p?N={name:"Tizen",osname:"Tizen",tizen:e,version:n(/(?:tizen\s?)?browser\/(\d+(\.\d+)?)/i)||E}:/qupzilla/i.test(t)?N={name:"QupZilla",qupzilla:e,version:n(/(?:qupzilla)[\s\/](\d+(?:\.\d+)+)/i)||E}:/chromium/i.test(t)?N={name:"Chromium",chromium:e,version:n(/(?:chromium)[\s\/](\d+(?:\.\d+)?)/i)||E}:/chrome|crios|crmo/i.test(t)?N={name:"Chrome",chrome:e,version:n(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i)}:u?N={name:"Android",version:E}:/safari|applewebkit/i.test(t)?(N={name:"Safari",safari:e},E&&(N.version=E)):i?(N={name:i=="iphone"?"iPhone":i=="ipad"?"iPad":"iPod"},E&&(N.version=E)):/googlebot/i.test(t)?N={name:"Googlebot",googlebot:e,version:n(/googlebot\/(\d+(\.\d+))/i)||E}:N={name:n(/^(.*)\/(.*) /),version:r(/^(.*)\/(.*) /)},!N.msedge&&/(apple)?webkit/i.test(t)?(/(apple)?webkit\/537\.36/i.test(t)?(N.name=N.name||"Blink",N.blink=e):(N.name=N.name||"Webkit",N.webkit=e),!N.version&&E&&(N.version=E)):!N.opera&&/gecko\//i.test(t)&&(N.name=N.name||"Gecko",N.gecko=e,N.version=N.version||n(/gecko\/(\d+(\.\d+)?)/i)),!N.windowsphone&&(u||N.silk)?(N.android=e,N.osname="Android"):!N.windowsphone&&i?(N[i]=e,N.ios=e,N.osname="iOS"):y?(N.mac=e,N.osname="macOS"):T?(N.xbox=e,N.osname="Xbox"):g?(N.windows=e,N.osname="Windows"):b&&(N.linux=e,N.osname="Linux");var k="";N.windows?k=C(n(/Windows ((NT|XP)( \d\d?.\d)?)/i)):N.windowsphone?k=n(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i):N.mac?(k=n(/Mac OS X (\d+([_\.\s]\d+)*)/i),k=k.replace(/[_\s]/g,".")):i?(k=n(/os (\d+([_\s]\d+)*) like mac os x/i),k=k.replace(/[_\s]/g,".")):u?k=n(/android[ \/-](\d+(\.\d+)*)/i):N.webos?k=n(/(?:web|hpw)os\/(\d+(\.\d+)*)/i):N.blackberry?k=n(/rim\stablet\sos\s(\d+(\.\d+)*)/i):N.bada?k=n(/bada\/(\d+(\.\d+)*)/i):N.tizen&&(k=n(/tizen[\/\s](\d+(\.\d+)*)/i)),k&&(N.osversion=k);var L=!N.windows&&k.split(".")[0];if(S||f||i=="ipad"||u&&(L==3||L>=4&&!x)||N.silk)N.tablet=e;else if(x||i=="iphone"||i=="ipod"||u||a||N.blackberry||N.webos||N.bada)N.mobile=e;return N.msedge||N.msie&&N.version>=10||N.yandexbrowser&&N.version>=15||N.vivaldi&&N.version>=1||N.chrome&&N.version>=20||N.samsungBrowser&&N.version>=4||N.whale&&s([N.version,"1.0"])===1||N.mzbrowser&&s([N.version,"6.0"])===1||N.focus&&s([N.version,"1.0"])===1||N.firefox&&N.version>=20||N.safari&&N.version>=6||N.opera&&N.version>=10||N.ios&&N.osversion&&N.osversion.split(".")[0]>=6||N.blackberry&&N.version>=10.1||N.chromium&&N.version>=20?N.a=e:N.msie&&N.version<10||N.chrome&&N.version<20||N.firefox&&N.version<20||N.safari&&N.version<6||N.opera&&N.version<10||N.ios&&N.osversion&&N.osversion.split(".")[0]<6||N.chromium&&N.version<20?N.c=e:N.x=e,N}function r(e){return e.split(".").length}function i(e,t){var n=[],r;if(Array.prototype.map)return Array.prototype.map.call(e,t);for(r=0;r=0){if(n[0][t]>n[1][t])return 1;if(n[0][t]!==n[1][t])return-1;if(t===0)return 0}}function o(e,r,i){var o=n;typeof r=="string"&&(i=r,r=void 0),r===void 0&&(r=!1),i&&(o=t(i));var u=""+o.version;for(var a in e)if(e.hasOwnProperty(a)&&o[a]){if(typeof e[a]!="string")throw new Error("Browser version in the minVersion map should be a string: "+a+": "+String(e));return s([u,e[a]])<0}return r}function u(e,t,n){return!o(e,t,n)}var e=!0,n=t(typeof navigator!="undefined"?navigator.userAgent||"":"");return n.test=function(e){for(var t=0;t= delay ? callback.call() : handle.value = requestAnimFrame(loop); - }; - - handle.value = requestAnimFrame(loop); - - return handle; - }, - Blob: window.Blob || window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder, - btoa: function () { - var btoa = window.btoa || function (input) { - var output = ''; - var i = 0; - var l = input.length; - var key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - var chr1 = void 0; - var chr2 = void 0; - var chr3 = void 0; - var enc1 = void 0; - var enc2 = void 0; - var enc3 = void 0; - var enc4 = void 0; - - while (i < l) { - chr1 = input.charCodeAt(i++); - chr2 = input.charCodeAt(i++); - chr3 = input.charCodeAt(i++); - enc1 = chr1 >> 2; - enc2 = (chr1 & 3) << 4 | chr2 >> 4; - enc3 = (chr2 & 15) << 2 | chr3 >> 6; - enc4 = chr3 & 63; - - if (isNaN(chr2)) { - enc3 = enc4 = 64; - } else if (isNaN(chr3)) { - enc4 = 64; - } - - output = output + key.charAt(enc1) + key.charAt(enc2) + key.charAt(enc3) + key.charAt(enc4); - } - - return output; - }; - - return btoa ? btoa.bind(window) : utils.noop; - }(), - isObject: function isObject(obj) { - return obj && Object.prototype.toString.call(obj) === '[object Object]'; - }, - isEmptyObject: function isEmptyObject(obj) { - return utils.isObject(obj) && !Object.keys(obj).length; - }, - isArray: function isArray(arr) { - return arr && Array.isArray(arr); - }, - isFunction: function isFunction(func) { - return func && typeof func === 'function'; - }, - isElement: function isElement(elem) { - return elem && elem.nodeType === 1; - }, - isString: function isString(value) { - return typeof value === 'string' || Object.prototype.toString.call(value) === '[object String]'; - }, - isSupported: { - canvas: function canvas() { - var el = document.createElement('canvas'); - - return el && el.getContext && el.getContext('2d'); - }, - webworkers: function webworkers() { - return window.Worker; - }, - blob: function blob() { - return utils.Blob; - }, - Uint8Array: function Uint8Array() { - return window.Uint8Array; - }, - Uint32Array: function Uint32Array() { - return window.Uint32Array; - }, - videoCodecs: function () { - var testEl = document.createElement('video'); - var supportObj = { - 'mp4': false, - 'h264': false, - 'ogv': false, - 'ogg': false, - 'webm': false - }; - - try { - if (testEl && testEl.canPlayType) { - // Check for MPEG-4 support - supportObj.mp4 = testEl.canPlayType('video/mp4; codecs="mp4v.20.8"') !== ''; - - // Check for h264 support - supportObj.h264 = (testEl.canPlayType('video/mp4; codecs="avc1.42E01E"') || testEl.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) !== ''; - - // Check for Ogv support - supportObj.ogv = testEl.canPlayType('video/ogg; codecs="theora"') !== ''; - - // Check for Ogg support - supportObj.ogg = testEl.canPlayType('video/ogg; codecs="theora"') !== ''; - - // Check for Webm support - supportObj.webm = testEl.canPlayType('video/webm; codecs="vp8, vorbis"') !== -1; - } - } catch (e) {} - - return supportObj; - }() - }, - noop: function noop() {}, - each: function each(collection, callback) { - var x = void 0; - var len = void 0; - - if (utils.isArray(collection)) { - x = -1; - len = collection.length; - - while (++x < len) { - if (callback(x, collection[x]) === false) { - break; - } - } - } else if (utils.isObject(collection)) { - for (x in collection) { - if (collection.hasOwnProperty(x)) { - if (callback(x, collection[x]) === false) { - break; - } - } - } - } - }, - mergeOptions: function mergeOptions(defaultOptions, userOptions) { - if (!utils.isObject(defaultOptions) || !utils.isObject(userOptions) || !Object.keys) { - return; - } - - var newObj = {}; - - utils.each(defaultOptions, function (key, val) { - newObj[key] = defaultOptions[key]; - }); - - utils.each(userOptions, function (key, val) { - var currentUserOption = userOptions[key]; - - if (!utils.isObject(currentUserOption)) { - newObj[key] = currentUserOption; - } else { - if (!defaultOptions[key]) { - newObj[key] = currentUserOption; - } else { - newObj[key] = utils.mergeOptions(defaultOptions[key], currentUserOption); - } - } - }); - - return newObj; - }, - setCSSAttr: function setCSSAttr(elem, attr, val) { - if (!utils.isElement(elem)) { - return; - } - - if (utils.isString(attr) && utils.isString(val)) { - elem.style[attr] = val; - } else if (utils.isObject(attr)) { - utils.each(attr, function (key, val) { - elem.style[key] = val; - }); - } - }, - removeElement: function removeElement(node) { - if (!utils.isElement(node)) { - return; - } - if (node.parentNode) { - node.parentNode.removeChild(node); - } - }, - createWebWorker: function createWebWorker(content) { - if (!utils.isString(content)) { - return {}; - } - - try { - var blob = new utils.Blob([content], { - 'type': 'text/javascript' - }); - var objectUrl = utils.URL.createObjectURL(blob); - var worker = new Worker(objectUrl); - - return { - 'objectUrl': objectUrl, - 'worker': worker - }; - } catch (e) { - return '' + e; - } - }, - getExtension: function getExtension(src) { - return src.substr(src.lastIndexOf('.') + 1, src.length); - }, - getFontSize: function getFontSize() { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - if (!document.body || options.resizeFont === false) { - return options.fontSize; - } - - var text = options.text; - var containerWidth = options.gifWidth; - var fontSize = parseInt(options.fontSize, 10); - var minFontSize = parseInt(options.minFontSize, 10); - var div = document.createElement('div'); - var span = document.createElement('span'); - - div.setAttribute('width', containerWidth); - div.appendChild(span); - - span.innerHTML = text; - span.style.fontSize = fontSize + 'px'; - span.style.textIndent = '-9999px'; - span.style.visibility = 'hidden'; - - document.body.appendChild(span); - - while (span.offsetWidth > containerWidth && fontSize >= minFontSize) { - span.style.fontSize = --fontSize + 'px'; - } - - document.body.removeChild(span); - - return fontSize + 'px'; - }, - webWorkerError: false -}; - - - -var utils$2 = Object.freeze({ - default: utils -}); - -/* - error.js - ======== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -var error = { - validate: function validate(skipObj) { - skipObj = utils.isObject(skipObj) ? skipObj : {}; - - var errorObj = {}; - - utils.each(error.validators, function (indece, currentValidator) { - var errorCode = currentValidator.errorCode; - - if (!skipObj[errorCode] && !currentValidator.condition) { - errorObj = currentValidator; - errorObj.error = true; - - return false; - } - }); - - delete errorObj.condition; - - return errorObj; - }, - isValid: function isValid(skipObj) { - var errorObj = error.validate(skipObj); - var isValid = errorObj.error !== true ? true : false; - - return isValid; - }, - validators: [{ - condition: utils.isFunction(utils.getUserMedia), - errorCode: 'getUserMedia', - errorMsg: 'The getUserMedia API is not supported in your browser' - }, { - condition: utils.isSupported.canvas(), - errorCode: 'canvas', - errorMsg: 'Canvas elements are not supported in your browser' - }, { - condition: utils.isSupported.webworkers(), - errorCode: 'webworkers', - errorMsg: 'The Web Workers API is not supported in your browser' - }, { - condition: utils.isFunction(utils.URL), - errorCode: 'window.URL', - errorMsg: 'The window.URL API is not supported in your browser' - }, { - condition: utils.isSupported.blob(), - errorCode: 'window.Blob', - errorMsg: 'The window.Blob File API is not supported in your browser' - }, { - condition: utils.isSupported.Uint8Array(), - errorCode: 'window.Uint8Array', - errorMsg: 'The window.Uint8Array function constructor is not supported in your browser' - }, { - condition: utils.isSupported.Uint32Array(), - errorCode: 'window.Uint32Array', - errorMsg: 'The window.Uint32Array function constructor is not supported in your browser' - }], - messages: { - videoCodecs: { - errorCode: 'videocodec', - errorMsg: 'The video codec you are trying to use is not supported in your browser' - } - } -}; - - - -var error$2 = Object.freeze({ - default: error -}); - -/* - defaultOptions.js - ================= -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Helpers -var noop = function noop() {}; - -var defaultOptions = { - sampleInterval: 10, - numWorkers: 2, - filter: '', - gifWidth: 200, - gifHeight: 200, - interval: 0.1, - numFrames: 10, - frameDuration: 1, - keepCameraOn: false, - images: [], - video: null, - webcamVideoElement: null, - cameraStream: null, - text: '', - fontWeight: 'normal', - fontSize: '16px', - minFontSize: '10px', - resizeFont: false, - fontFamily: 'sans-serif', - fontColor: '#ffffff', - textAlign: 'center', - textBaseline: 'bottom', - textXCoordinate: null, - textYCoordinate: null, - progressCallback: noop, - completeCallback: noop, - saveRenderingContexts: false, - savedRenderingContexts: [], - showFrameText: true, - crossOrigin: 'Anonymous', - waterMark: null, - waterMarkHeight: null, - waterMarkWidth: null, - waterMarkXCoordinate: 1, - waterMarkYCoordinate: 1 -}; - - - -var defaultOptions$2 = Object.freeze({ - default: defaultOptions -}); - -/* - isSupported.js - ============== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -function isSupported() { - return error.isValid(); -} - -/* - isWebCamGIFSupported.js - ======================= -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -function isWebCamGIFSupported() { - return error.isValid(); -} - -/* - isSupported.js - ============== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -function isSupported$1() { - var options = { - getUserMedia: true - }; - - return error.isValid(options); -} - -/* - isExistingVideoGIFSupported.js - ============================== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -function isExistingVideoGIFSupported(codecs) { - var hasValidCodec = false; - - if (utils.isArray(codecs) && codecs.length) { - utils.each(codecs, function (indece, currentCodec) { - if (utils.isSupported.videoCodecs[currentCodec]) { - hasValidCodec = true; - } - }); - - if (!hasValidCodec) { - return false; - } - } else if (utils.isString(codecs) && codecs.length) { - if (!utils.isSupported.videoCodecs[codecs]) { - return false; - } - } - - return error.isValid({ - 'getUserMedia': true - }); -} - -/* - NeuQuant.js - =========== -*/ - -/* - * NeuQuant Neural-Net Quantization Algorithm - * ------------------------------------------ - * - * Copyright (c) 1994 Anthony Dekker - * - * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See - * "Kohonen neural networks for optimal colour quantization" in "Network: - * Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of - * the algorithm. - * - * Any party obtaining a copy of these files from the author, directly or - * indirectly, is granted, free of charge, a full and unrestricted irrevocable, - * world-wide, paid up, royalty-free, nonexclusive right and license to deal in - * this software and documentation files (the "Software"), including without - * limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons who - * receive copies from any such party to do so, with the only requirement being - * that this copyright notice remain intact. - */ - -/* - * This class handles Neural-Net quantization algorithm - * @author Kevin Weiner (original Java version - kweiner@fmsware.com) - * @author Thibault Imbert (AS3 version - bytearray.org) - * @version 0.1 AS3 implementation - * @version 0.2 JS->AS3 "translation" by antimatter15 - * @version 0.3 JS clean up + using modern JS idioms by sole - http://soledadpenades.com - * Also implement fix in color conversion described at http://stackoverflow.com/questions/16371712/neuquant-js-javascript-color-quantization-hidden-bug-in-js-conversion - */ - -function NeuQuant() { - var netsize = 256; // number of colours used - - // four primes near 500 - assume no image has a length so large - // that it is divisible by all four primes - var prime1 = 499; - var prime2 = 491; - var prime3 = 487; - var prime4 = 503; - - // minimum size for input image - var minpicturebytes = 3 * prime4; - - // Network Definitions - - var maxnetpos = netsize - 1; - var netbiasshift = 4; // bias for colour values - var ncycles = 100; // no. of learning cycles - - // defs for freq and bias - var intbiasshift = 16; // bias for fractions - var intbias = 1 << intbiasshift; - var gammashift = 10; // gamma = 1024 - var gamma = 1 << gammashift; - var betashift = 10; - var beta = intbias >> betashift; // beta = 1/1024 - var betagamma = intbias << gammashift - betashift; - - // defs for decreasing radius factor - // For 256 colors, radius starts at 32.0 biased by 6 bits - // and decreases by a factor of 1/30 each cycle - var initrad = netsize >> 3; - var radiusbiasshift = 6; - var radiusbias = 1 << radiusbiasshift; - var initradius = initrad * radiusbias; - var radiusdec = 30; - - // defs for decreasing alpha factor - // Alpha starts at 1.0 biased by 10 bits - var alphabiasshift = 10; - var initalpha = 1 << alphabiasshift; - var alphadec; - - // radbias and alpharadbias used for radpower calculation - var radbiasshift = 8; - var radbias = 1 << radbiasshift; - var alpharadbshift = alphabiasshift + radbiasshift; - var alpharadbias = 1 << alpharadbshift; - - // Input image - var thepicture; - // Height * Width * 3 - var lengthcount; - // Sampling factor 1..30 - var samplefac; - - // The network itself - var network; - var netindex = []; - - // for network lookup - really 256 - var bias = []; - - // bias and freq arrays for learning - var freq = []; - var radpower = []; - - function NeuQuantConstructor(thepic, len, sample) { - - var i; - var p; - - thepicture = thepic; - lengthcount = len; - samplefac = sample; - - network = new Array(netsize); - - for (i = 0; i < netsize; i++) { - network[i] = new Array(4); - p = network[i]; - p[0] = p[1] = p[2] = (i << netbiasshift + 8) / netsize | 0; - freq[i] = intbias / netsize | 0; // 1 / netsize - bias[i] = 0; - } - } - - function colorMap() { - var map = []; - var index = new Array(netsize); - for (var i = 0; i < netsize; i++) { - index[network[i][3]] = i; - }var k = 0; - for (var l = 0; l < netsize; l++) { - var j = index[l]; - map[k++] = network[j][0]; - map[k++] = network[j][1]; - map[k++] = network[j][2]; - } - return map; - } - - // Insertion sort of network and building of netindex[0..255] - // (to do after unbias) - function inxbuild() { - var i; - var j; - var smallpos; - var smallval; - var p; - var q; - var previouscol; - var startpos; - - previouscol = 0; - startpos = 0; - - for (i = 0; i < netsize; i++) { - - p = network[i]; - smallpos = i; - smallval = p[1]; // index on g - // find smallest in i..netsize-1 - for (j = i + 1; j < netsize; j++) { - - q = network[j]; - - if (q[1] < smallval) { - // index on g - smallpos = j; - smallval = q[1]; // index on g - } - } - - q = network[smallpos]; - - // swap p (i) and q (smallpos) entries - if (i != smallpos) { - j = q[0]; - q[0] = p[0]; - p[0] = j; - j = q[1]; - q[1] = p[1]; - p[1] = j; - j = q[2]; - q[2] = p[2]; - p[2] = j; - j = q[3]; - q[3] = p[3]; - p[3] = j; - } - - // smallval entry is now in position i - if (smallval != previouscol) { - - netindex[previouscol] = startpos + i >> 1; - - for (j = previouscol + 1; j < smallval; j++) { - netindex[j] = i; - } - - previouscol = smallval; - startpos = i; - } - } - - netindex[previouscol] = startpos + maxnetpos >> 1; - for (j = previouscol + 1; j < 256; j++) { - netindex[j] = maxnetpos; // really 256 - } - } - - // Main Learning Loop - - function learn() { - var i; - var j; - var b; - var g; - var r; - var radius; - var rad; - var alpha; - var step; - var delta; - var samplepixels; - var p; - var pix; - var lim; - - if (lengthcount < minpicturebytes) { - samplefac = 1; - } - - alphadec = 30 + (samplefac - 1) / 3; - p = thepicture; - pix = 0; - lim = lengthcount; - samplepixels = lengthcount / (3 * samplefac); - delta = samplepixels / ncycles | 0; - alpha = initalpha; - radius = initradius; - - rad = radius >> radiusbiasshift; - if (rad <= 1) { - rad = 0; - } - - for (i = 0; i < rad; i++) { - radpower[i] = alpha * ((rad * rad - i * i) * radbias / (rad * rad)); - } - - if (lengthcount < minpicturebytes) { - step = 3; - } else if (lengthcount % prime1 !== 0) { - step = 3 * prime1; - } else { - - if (lengthcount % prime2 !== 0) { - step = 3 * prime2; - } else { - if (lengthcount % prime3 !== 0) { - step = 3 * prime3; - } else { - step = 3 * prime4; - } - } - } - - i = 0; - - while (i < samplepixels) { - - b = (p[pix + 0] & 0xff) << netbiasshift; - g = (p[pix + 1] & 0xff) << netbiasshift; - r = (p[pix + 2] & 0xff) << netbiasshift; - j = contest(b, g, r); - - altersingle(alpha, j, b, g, r); - - if (rad !== 0) { - // Alter neighbours - alterneigh(rad, j, b, g, r); - } - - pix += step; - - if (pix >= lim) { - pix -= lengthcount; - } - - i++; - - if (delta === 0) { - delta = 1; - } - - if (i % delta === 0) { - alpha -= alpha / alphadec; - radius -= radius / radiusdec; - rad = radius >> radiusbiasshift; - - if (rad <= 1) { - rad = 0; - } - - for (j = 0; j < rad; j++) { - radpower[j] = alpha * ((rad * rad - j * j) * radbias / (rad * rad)); - } - } - } - } - - // Search for BGR values 0..255 (after net is unbiased) and return colour index - function map(b, g, r) { - var i; - var j; - var dist; - var a; - var bestd; - var p; - var best; - - // Biggest possible distance is 256 * 3 - bestd = 1000; - best = -1; - i = netindex[g]; // index on g - j = i - 1; // start at netindex[g] and work outwards - - while (i < netsize || j >= 0) { - - if (i < netsize) { - - p = network[i]; - - dist = p[1] - g; // inx key - - if (dist >= bestd) { - i = netsize; // stop iter - } else { - - i++; - - if (dist < 0) { - dist = -dist; - } - - a = p[0] - b; - - if (a < 0) { - a = -a; - } - - dist += a; - - if (dist < bestd) { - a = p[2] - r; - - if (a < 0) { - a = -a; - } - - dist += a; - - if (dist < bestd) { - bestd = dist; - best = p[3]; - } - } - } - } - - if (j >= 0) { - - p = network[j]; - - dist = g - p[1]; // inx key - reverse dif - - if (dist >= bestd) { - j = -1; // stop iter - } else { - - j--; - if (dist < 0) { - dist = -dist; - } - a = p[0] - b; - if (a < 0) { - a = -a; - } - dist += a; - - if (dist < bestd) { - a = p[2] - r; - if (a < 0) { - a = -a; - } - dist += a; - if (dist < bestd) { - bestd = dist; - best = p[3]; - } - } - } - } - } - - return best; - } - - function process() { - learn(); - unbiasnet(); - inxbuild(); - return colorMap(); - } - - // Unbias network to give byte values 0..255 and record position i - // to prepare for sort - function unbiasnet() { - var i; - var j; - - for (i = 0; i < netsize; i++) { - network[i][0] >>= netbiasshift; - network[i][1] >>= netbiasshift; - network[i][2] >>= netbiasshift; - network[i][3] = i; // record colour no - } - } - - // Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) - // in radpower[|i-j|] - function alterneigh(rad, i, b, g, r) { - - var j; - var k; - var lo; - var hi; - var a; - var m; - - var p; - - lo = i - rad; - if (lo < -1) { - lo = -1; - } - - hi = i + rad; - - if (hi > netsize) { - hi = netsize; - } - - j = i + 1; - k = i - 1; - m = 1; - - while (j < hi || k > lo) { - - a = radpower[m++]; - - if (j < hi) { - - p = network[j++]; - - try { - - p[0] -= a * (p[0] - b) / alpharadbias | 0; - p[1] -= a * (p[1] - g) / alpharadbias | 0; - p[2] -= a * (p[2] - r) / alpharadbias | 0; - } catch (e) {} - } - - if (k > lo) { - - p = network[k--]; - - try { - - p[0] -= a * (p[0] - b) / alpharadbias | 0; - p[1] -= a * (p[1] - g) / alpharadbias | 0; - p[2] -= a * (p[2] - r) / alpharadbias | 0; - } catch (e) {} - } - } - } - - // Move neuron i towards biased (b,g,r) by factor alpha - function altersingle(alpha, i, b, g, r) { - - // alter hit neuron - var n = network[i]; - var alphaMult = alpha / initalpha; - n[0] -= alphaMult * (n[0] - b) | 0; - n[1] -= alphaMult * (n[1] - g) | 0; - n[2] -= alphaMult * (n[2] - r) | 0; - } - - // Search for biased BGR values - function contest(b, g, r) { - - // finds closest neuron (min dist) and updates freq - // finds best neuron (min dist-bias) and returns position - // for frequently chosen neurons, freq[i] is high and bias[i] is negative - // bias[i] = gamma*((1/netsize)-freq[i]) - - var i; - var dist; - var a; - var biasdist; - var betafreq; - var bestpos; - var bestbiaspos; - var bestd; - var bestbiasd; - var n; - - bestd = ~(1 << 31); - bestbiasd = bestd; - bestpos = -1; - bestbiaspos = bestpos; - - for (i = 0; i < netsize; i++) { - - n = network[i]; - dist = n[0] - b; - - if (dist < 0) { - dist = -dist; - } - - a = n[1] - g; - - if (a < 0) { - a = -a; - } - - dist += a; - - a = n[2] - r; - - if (a < 0) { - a = -a; - } - - dist += a; - - if (dist < bestd) { - bestd = dist; - bestpos = i; - } - - biasdist = dist - (bias[i] >> intbiasshift - netbiasshift); - - if (biasdist < bestbiasd) { - bestbiasd = biasdist; - bestbiaspos = i; - } - - betafreq = freq[i] >> betashift; - freq[i] -= betafreq; - bias[i] += betafreq << gammashift; - } - - freq[bestpos] += beta; - bias[bestpos] -= betagamma; - return bestbiaspos; - } - - NeuQuantConstructor.apply(this, arguments); - - var exports = {}; - exports.map = map; - exports.process = process; - - return exports; -} - -/* - processFrameWorker.js - ===================== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -function workerCode() { - var self = this; - - try { - self.onmessage = function (ev) { - var data = ev.data || {}; - var response; - - if (data.gifshot) { - response = workerMethods.run(data); - postMessage(response); - } - }; - } catch (e) {} - - var workerMethods = { - dataToRGB: function dataToRGB(data, width, height) { - var length = width * height * 4; - var i = 0; - var rgb = []; - - while (i < length) { - rgb.push(data[i++]); - rgb.push(data[i++]); - rgb.push(data[i++]); - i++; // for the alpha channel which we don't care about - } - - return rgb; - }, - componentizedPaletteToArray: function componentizedPaletteToArray(paletteRGB) { - paletteRGB = paletteRGB || []; - - var paletteArray = []; - - for (var i = 0; i < paletteRGB.length; i += 3) { - var r = paletteRGB[i]; - var g = paletteRGB[i + 1]; - var b = paletteRGB[i + 2]; - - paletteArray.push(r << 16 | g << 8 | b); - } - - return paletteArray; - }, - // This is the "traditional" Animated_GIF style of going from RGBA to indexed color frames - 'processFrameWithQuantizer': function processFrameWithQuantizer(imageData, width, height, sampleInterval) { - var rgbComponents = this.dataToRGB(imageData, width, height); - var nq = new NeuQuant(rgbComponents, rgbComponents.length, sampleInterval); - var paletteRGB = nq.process(); - var paletteArray = new Uint32Array(this.componentizedPaletteToArray(paletteRGB)); - var numberPixels = width * height; - var indexedPixels = new Uint8Array(numberPixels); - var k = 0; - - for (var i = 0; i < numberPixels; i++) { - var r = rgbComponents[k++]; - var g = rgbComponents[k++]; - var b = rgbComponents[k++]; - - indexedPixels[i] = nq.map(r, g, b); - } - - return { - pixels: indexedPixels, - palette: paletteArray - }; - }, - 'run': function run(frame) { - frame = frame || {}; - - var _frame = frame, - height = _frame.height, - palette = _frame.palette, - sampleInterval = _frame.sampleInterval, - width = _frame.width; - - var imageData = frame.data; - - return this.processFrameWithQuantizer(imageData, width, height, sampleInterval); - } - }; - - return workerMethods; -} - -/* - gifWriter.js - ============ -*/ - -// (c) Dean McNamee , 2013. -// -// https://github.com/deanm/omggif -// -// 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. -// -// omggif is a JavaScript implementation of a GIF 89a encoder and decoder, -// including animation and compression. It does not rely on any specific -// underlying system, so should run in the browser, Node, or Plask. - -function gifWriter(buf, width, height, gopts) { - var p = 0; - - gopts = gopts === undefined ? {} : gopts; - var loop_count = gopts.loop === undefined ? null : gopts.loop; - var global_palette = gopts.palette === undefined ? null : gopts.palette; - - if (width <= 0 || height <= 0 || width > 65535 || height > 65535) throw "Width/Height invalid."; - - function check_palette_and_num_colors(palette) { - var num_colors = palette.length; - - if (num_colors < 2 || num_colors > 256 || num_colors & num_colors - 1) throw "Invalid code/color length, must be power of 2 and 2 .. 256."; - return num_colors; - } - - // - Header. - buf[p++] = 0x47; - buf[p++] = 0x49; - buf[p++] = 0x46; // GIF - buf[p++] = 0x38; - buf[p++] = 0x39; - buf[p++] = 0x61; // 89a - - // Handling of Global Color Table (palette) and background index. - var gp_num_colors_pow2 = 0; - var background = 0; - - // - Logical Screen Descriptor. - // NOTE(deanm): w/h apparently ignored by implementations, but set anyway. - buf[p++] = width & 0xff; - buf[p++] = width >> 8 & 0xff; - buf[p++] = height & 0xff; - buf[p++] = height >> 8 & 0xff; - // NOTE: Indicates 0-bpp original color resolution (unused?). - buf[p++] = (global_palette !== null ? 0x80 : 0) | // Global Color Table Flag. - gp_num_colors_pow2; // NOTE: No sort flag (unused?). - buf[p++] = background; // Background Color Index. - buf[p++] = 0; // Pixel aspect ratio (unused?). - - if (loop_count !== null) { - // Netscape block for looping. - if (loop_count < 0 || loop_count > 65535) throw "Loop count invalid."; - - // Extension code, label, and length. - buf[p++] = 0x21; - buf[p++] = 0xff; - buf[p++] = 0x0b; - // NETSCAPE2.0 - buf[p++] = 0x4e; - buf[p++] = 0x45; - buf[p++] = 0x54; - buf[p++] = 0x53; - buf[p++] = 0x43; - buf[p++] = 0x41; - buf[p++] = 0x50; - buf[p++] = 0x45; - buf[p++] = 0x32; - buf[p++] = 0x2e; - buf[p++] = 0x30; - // Sub-block - buf[p++] = 0x03; - buf[p++] = 0x01; - buf[p++] = loop_count & 0xff; - buf[p++] = loop_count >> 8 & 0xff; - buf[p++] = 0x00; // Terminator. - } - - var ended = false; - - this.addFrame = function (x, y, w, h, indexed_pixels, opts) { - if (ended === true) { - --p; - ended = false; - } // Un-end. - - opts = opts === undefined ? {} : opts; - - // TODO(deanm): Bounds check x, y. Do they need to be within the virtual - // canvas width/height, I imagine? - if (x < 0 || y < 0 || x > 65535 || y > 65535) throw "x/y invalid."; - - if (w <= 0 || h <= 0 || w > 65535 || h > 65535) throw "Width/Height invalid."; - - if (indexed_pixels.length < w * h) throw "Not enough pixels for the frame size."; - - var using_local_palette = true; - var palette = opts.palette; - if (palette === undefined || palette === null) { - using_local_palette = false; - palette = global_palette; - } - - if (palette === undefined || palette === null) throw "Must supply either a local or global palette."; - - var num_colors = check_palette_and_num_colors(palette); - - // Compute the min_code_size (power of 2), destroying num_colors. - var min_code_size = 0; - while (num_colors >>= 1) { - ++min_code_size; - }num_colors = 1 << min_code_size; // Now we can easily get it back. - - var delay = opts.delay === undefined ? 0 : opts.delay; - - // From the spec: - // 0 - No disposal specified. The decoder is - // not required to take any action. - // 1 - Do not dispose. The graphic is to be left - // in place. - // 2 - Restore to background color. The area used by the - // graphic must be restored to the background color. - // 3 - Restore to previous. The decoder is required to - // restore the area overwritten by the graphic with - // what was there prior to rendering the graphic. - // 4-7 - To be defined. - // NOTE(deanm): Dispose background doesn't really work, apparently most - // browsers ignore the background palette index and clear to transparency. - var disposal = opts.disposal === undefined ? 0 : opts.disposal; - if (disposal < 0 || disposal > 3) // 4-7 is reserved. - throw "Disposal out of range."; - - var use_transparency = false; - var transparent_index = 0; - if (opts.transparent !== undefined && opts.transparent !== null) { - use_transparency = true; - transparent_index = opts.transparent; - if (transparent_index < 0 || transparent_index >= num_colors) throw "Transparent color index."; - } - - if (disposal !== 0 || use_transparency || delay !== 0) { - // - Graphics Control Extension - buf[p++] = 0x21; - buf[p++] = 0xf9; // Extension / Label. - buf[p++] = 4; // Byte size. - - buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0); - buf[p++] = delay & 0xff; - buf[p++] = delay >> 8 & 0xff; - buf[p++] = transparent_index; // Transparent color index. - buf[p++] = 0; // Block Terminator. - } - - // - Image Descriptor - buf[p++] = 0x2c; // Image Seperator. - buf[p++] = x & 0xff; - buf[p++] = x >> 8 & 0xff; // Left. - buf[p++] = y & 0xff; - buf[p++] = y >> 8 & 0xff; // Top. - buf[p++] = w & 0xff; - buf[p++] = w >> 8 & 0xff; - buf[p++] = h & 0xff; - buf[p++] = h >> 8 & 0xff; - // NOTE: No sort flag (unused?). - // TODO(deanm): Support interlace. - buf[p++] = using_local_palette === true ? 0x80 | min_code_size - 1 : 0; - - // - Local Color Table - if (using_local_palette === true) { - for (var i = 0, il = palette.length; i < il; ++i) { - var rgb = palette[i]; - buf[p++] = rgb >> 16 & 0xff; - buf[p++] = rgb >> 8 & 0xff; - buf[p++] = rgb & 0xff; - } - } - - p = GifWriterOutputLZWCodeStream(buf, p, min_code_size < 2 ? 2 : min_code_size, indexed_pixels); - }; - - this.end = function () { - if (ended === false) { - buf[p++] = 0x3b; // Trailer. - ended = true; - } - return p; - }; - - // Main compression routine, palette indexes -> LZW code stream. - // |index_stream| must have at least one entry. - function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) { - buf[p++] = min_code_size; - var cur_subblock = p++; // Pointing at the length field. - - var clear_code = 1 << min_code_size; - var code_mask = clear_code - 1; - var eoi_code = clear_code + 1; - var next_code = eoi_code + 1; - - var cur_code_size = min_code_size + 1; // Number of bits per code. - var cur_shift = 0; - // We have at most 12-bit codes, so we should have to hold a max of 19 - // bits here (and then we would write out). - var cur = 0; - - function emit_bytes_to_buffer(bit_block_size) { - while (cur_shift >= bit_block_size) { - buf[p++] = cur & 0xff; - cur >>= 8; - cur_shift -= 8; - if (p === cur_subblock + 256) { - // Finished a subblock. - buf[cur_subblock] = 255; - cur_subblock = p++; - } - } - } - - function emit_code(c) { - cur |= c << cur_shift; - cur_shift += cur_code_size; - emit_bytes_to_buffer(8); - } - - // I am not an expert on the topic, and I don't want to write a thesis. - // However, it is good to outline here the basic algorithm and the few data - // structures and optimizations here that make this implementation fast. - // The basic idea behind LZW is to build a table of previously seen runs - // addressed by a short id (herein called output code). All data is - // referenced by a code, which represents one or more values from the - // original input stream. All input bytes can be referenced as the same - // value as an output code. So if you didn't want any compression, you - // could more or less just output the original bytes as codes (there are - // some details to this, but it is the idea). In order to achieve - // compression, values greater then the input range (codes can be up to - // 12-bit while input only 8-bit) represent a sequence of previously seen - // inputs. The decompressor is able to build the same mapping while - // decoding, so there is always a shared common knowledge between the - // encoding and decoder, which is also important for "timing" aspects like - // how to handle variable bit width code encoding. - // - // One obvious but very important consequence of the table system is there - // is always a unique id (at most 12-bits) to map the runs. 'A' might be - // 4, then 'AA' might be 10, 'AAA' 11, 'AAAA' 12, etc. This relationship - // can be used for an effecient lookup strategy for the code mapping. We - // need to know if a run has been seen before, and be able to map that run - // to the output code. Since we start with known unique ids (input bytes), - // and then from those build more unique ids (table entries), we can - // continue this chain (almost like a linked list) to always have small - // integer values that represent the current byte chains in the encoder. - // This means instead of tracking the input bytes (AAAABCD) to know our - // current state, we can track the table entry for AAAABC (it is guaranteed - // to exist by the nature of the algorithm) and the next character D. - // Therefor the tuple of (table_entry, byte) is guaranteed to also be - // unique. This allows us to create a simple lookup key for mapping input - // sequences to codes (table indices) without having to store or search - // any of the code sequences. So if 'AAAA' has a table entry of 12, the - // tuple of ('AAAA', K) for any input byte K will be unique, and can be our - // key. This leads to a integer value at most 20-bits, which can always - // fit in an SMI value and be used as a fast sparse array / object key. - - // Output code for the current contents of the index buffer. - var ib_code = index_stream[0] & code_mask; // Load first input index. - var code_table = {}; // Key'd on our 20-bit "tuple". - - emit_code(clear_code); // Spec says first code should be a clear code. - - // First index already loaded, process the rest of the stream. - for (var i = 1, il = index_stream.length; i < il; ++i) { - var k = index_stream[i] & code_mask; - var cur_key = ib_code << 8 | k; // (prev, k) unique tuple. - var cur_code = code_table[cur_key]; // buffer + k. - - // Check if we have to create a new code table entry. - if (cur_code === undefined) { - // We don't have buffer + k. - // Emit index buffer (without k). - // This is an inline version of emit_code, because this is the core - // writing routine of the compressor (and V8 cannot inline emit_code - // because it is a closure here in a different context). Additionally - // we can call emit_byte_to_buffer less often, because we can have - // 30-bits (from our 31-bit signed SMI), and we know our codes will only - // be 12-bits, so can safely have 18-bits there without overflow. - // emit_code(ib_code); - cur |= ib_code << cur_shift; - cur_shift += cur_code_size; - while (cur_shift >= 8) { - buf[p++] = cur & 0xff; - cur >>= 8; - cur_shift -= 8; - if (p === cur_subblock + 256) { - // Finished a subblock. - buf[cur_subblock] = 255; - cur_subblock = p++; - } - } - - if (next_code === 4096) { - // Table full, need a clear. - emit_code(clear_code); - next_code = eoi_code + 1; - cur_code_size = min_code_size + 1; - code_table = {}; - } else { - // Table not full, insert a new entry. - // Increase our variable bit code sizes if necessary. This is a bit - // tricky as it is based on "timing" between the encoding and - // decoder. From the encoders perspective this should happen after - // we've already emitted the index buffer and are about to create the - // first table entry that would overflow our current code bit size. - if (next_code >= 1 << cur_code_size) ++cur_code_size; - code_table[cur_key] = next_code++; // Insert into code table. - } - - ib_code = k; // Index buffer to single input k. - } else { - ib_code = cur_code; // Index buffer to sequence in code table. - } - } - - emit_code(ib_code); // There will still be something in the index buffer. - emit_code(eoi_code); // End Of Information. - - // Flush / finalize the sub-blocks stream to the buffer. - emit_bytes_to_buffer(1); - - // Finish the sub-blocks, writing out any unfinished lengths and - // terminating with a sub-block of length 0. If we have already started - // but not yet used a sub-block it can just become the terminator. - if (cur_subblock + 1 === p) { - // Started but unused. - buf[cur_subblock] = 0; - } else { - // Started and used, write length and additional terminator block. - buf[cur_subblock] = p - cur_subblock - 1; - buf[p++] = 0; - } - return p; - } -} - -/* - animatedGIF.js - ============== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -// Helpers -var noop$2 = function noop() {}; - -var AnimatedGIF = function AnimatedGIF(options) { - this.canvas = null; - this.ctx = null; - this.repeat = 0; - this.frames = []; - this.numRenderedFrames = 0; - this.onRenderCompleteCallback = noop$2; - this.onRenderProgressCallback = noop$2; - this.workers = []; - this.availableWorkers = []; - this.generatingGIF = false; - this.options = options; - - // Constructs and initializes the the web workers appropriately - this.initializeWebWorkers(options); -}; - -AnimatedGIF.prototype = { - 'workerMethods': workerCode(), - 'initializeWebWorkers': function initializeWebWorkers(options) { - var self = this; - var processFrameWorkerCode = NeuQuant.toString() + '(' + workerCode.toString() + '());'; - var webWorkerObj = void 0; - var objectUrl = void 0; - var webWorker = void 0; - var numWorkers = void 0; - var x = -1; - var workerError = ''; - - numWorkers = options.numWorkers; - - while (++x < numWorkers) { - webWorkerObj = utils.createWebWorker(processFrameWorkerCode); - - if (utils.isObject(webWorkerObj)) { - objectUrl = webWorkerObj.objectUrl; - webWorker = webWorkerObj.worker; - - self.workers.push({ - worker: webWorker, - objectUrl: objectUrl - }); - - self.availableWorkers.push(webWorker); - } else { - workerError = webWorkerObj; - utils.webWorkerError = !!webWorkerObj; - } - } - - this.workerError = workerError; - this.canvas = document.createElement('canvas'); - this.canvas.width = options.gifWidth; - this.canvas.height = options.gifHeight; - this.ctx = this.canvas.getContext('2d'); - this.frames = []; - }, - // Return a worker for processing a frame - getWorker: function getWorker() { - return this.availableWorkers.pop(); - }, - // Restores a worker to the pool - freeWorker: function freeWorker(worker) { - this.availableWorkers.push(worker); - }, - byteMap: function () { - var byteMap = []; - - for (var i = 0; i < 256; i++) { - byteMap[i] = String.fromCharCode(i); - } - - return byteMap; - }(), - bufferToString: function bufferToString(buffer) { - var numberValues = buffer.length; - var str = ''; - var x = -1; - - while (++x < numberValues) { - str += this.byteMap[buffer[x]]; - } - - return str; - }, - onFrameFinished: function onFrameFinished(progressCallback) { - // The GIF is not written until we're done with all the frames - // because they might not be processed in the same order - var self = this; - var frames = self.frames; - var options = self.options; - var hasExistingImages = !!(options.images || []).length; - var allDone = frames.every(function (frame) { - return !frame.beingProcessed && frame.done; - }); - - self.numRenderedFrames++; - - if (hasExistingImages) { - progressCallback(self.numRenderedFrames / frames.length); - } - - self.onRenderProgressCallback(self.numRenderedFrames * 0.75 / frames.length); - - if (allDone) { - if (!self.generatingGIF) { - self.generateGIF(frames, self.onRenderCompleteCallback); - } - } else { - utils.requestTimeout(function () { - self.processNextFrame(); - }, 1); - } - }, - processFrame: function processFrame(position) { - var AnimatedGifContext = this; - var options = this.options; - var _options = this.options, - progressCallback = _options.progressCallback, - sampleInterval = _options.sampleInterval; - - var frames = this.frames; - var frame = void 0; - var worker = void 0; - var done = function done() { - var ev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - var data = ev.data; - - // Delete original data, and free memory - delete frame.data; - - frame.pixels = Array.prototype.slice.call(data.pixels); - frame.palette = Array.prototype.slice.call(data.palette); - frame.done = true; - frame.beingProcessed = false; - - AnimatedGifContext.freeWorker(worker); - - AnimatedGifContext.onFrameFinished(progressCallback); - }; - - frame = frames[position]; - - if (frame.beingProcessed || frame.done) { - this.onFrameFinished(); - - return; - } - - frame.sampleInterval = sampleInterval; - frame.beingProcessed = true; - frame.gifshot = true; - - worker = this.getWorker(); - - if (worker) { - // Process the frame in a web worker - worker.onmessage = done; - worker.postMessage(frame); - } else { - // Process the frame in the current thread - done({ - 'data': AnimatedGifContext.workerMethods.run(frame) - }); - } - }, - startRendering: function startRendering(completeCallback) { - this.onRenderCompleteCallback = completeCallback; - - for (var i = 0; i < this.options.numWorkers && i < this.frames.length; i++) { - this.processFrame(i); - } - }, - processNextFrame: function processNextFrame() { - var position = -1; - - for (var i = 0; i < this.frames.length; i++) { - var frame = this.frames[i]; - - if (!frame.done && !frame.beingProcessed) { - position = i; - break; - } - } - - if (position >= 0) { - this.processFrame(position); - } - }, - // Takes the already processed data in frames and feeds it to a new - // GifWriter instance in order to get the binary GIF file - generateGIF: function generateGIF(frames, callback) { - // TODO: Weird: using a simple JS array instead of a typed array, - // the files are WAY smaller o_o. Patches/explanations welcome! - var buffer = []; // new Uint8Array(width * height * frames.length * 5); - var gifOptions = { - loop: this.repeat - }; - var options = this.options; - var interval = options.interval; - - var frameDuration = options.frameDuration; - var existingImages = options.images; - var hasExistingImages = !!existingImages.length; - var height = options.gifHeight; - var width = options.gifWidth; - var gifWriter$$1 = new gifWriter(buffer, width, height, gifOptions); - var onRenderProgressCallback = this.onRenderProgressCallback; - var delay = hasExistingImages ? interval * 100 : 0; - var bufferToString = void 0; - var gif = void 0; - - this.generatingGIF = true; - - utils.each(frames, function (iterator, frame) { - var framePalette = frame.palette; - - onRenderProgressCallback(0.75 + 0.25 * frame.position * 1.0 / frames.length); - - for (var i = 0; i < frameDuration; i++) { - gifWriter$$1.addFrame(0, 0, width, height, frame.pixels, { - palette: framePalette, - delay: delay - }); - } - }); - - gifWriter$$1.end(); - - onRenderProgressCallback(1.0); - - this.frames = []; - - this.generatingGIF = false; - - if (utils.isFunction(callback)) { - bufferToString = this.bufferToString(buffer); - gif = 'data:image/gif;base64,' + utils.btoa(bufferToString); - - callback(gif); - } - }, - // From GIF: 0 = loop forever, null = not looping, n > 0 = loop n times and stop - setRepeat: function setRepeat(r) { - this.repeat = r; - }, - addFrame: function addFrame(element, gifshotOptions, frameText) { - gifshotOptions = utils.isObject(gifshotOptions) ? gifshotOptions : {}; - - var self = this; - var ctx = self.ctx; - var options = self.options; - var width = options.gifWidth; - var height = options.gifHeight; - var fontSize = utils.getFontSize(gifshotOptions); - var _gifshotOptions = gifshotOptions, - filter = _gifshotOptions.filter, - fontColor = _gifshotOptions.fontColor, - fontFamily = _gifshotOptions.fontFamily, - fontWeight = _gifshotOptions.fontWeight, - gifHeight = _gifshotOptions.gifHeight, - gifWidth = _gifshotOptions.gifWidth, - text = _gifshotOptions.text, - textAlign = _gifshotOptions.textAlign, - textBaseline = _gifshotOptions.textBaseline, - waterMark = _gifshotOptions.waterMark, - waterMarkHeight = _gifshotOptions.waterMarkHeight, - waterMarkWidth = _gifshotOptions.waterMarkWidth, - waterMarkXCoordinate = _gifshotOptions.waterMarkXCoordinate, - waterMarkYCoordinate = _gifshotOptions.waterMarkYCoordinate; - - var textXCoordinate = gifshotOptions.textXCoordinate ? gifshotOptions.textXCoordinate : textAlign === 'left' ? 1 : textAlign === 'right' ? width : width / 2; - var textYCoordinate = gifshotOptions.textYCoordinate ? gifshotOptions.textYCoordinate : textBaseline === 'top' ? 1 : textBaseline === 'center' ? height / 2 : height; - var font = fontWeight + ' ' + fontSize + ' ' + fontFamily; - var textToUse = frameText && gifshotOptions.showFrameText ? frameText : text; - var imageData = void 0; - - try { - ctx.filter = filter; - - ctx.drawImage(element, 0, 0, width, height); - - if (textToUse) { - ctx.font = font; - ctx.fillStyle = fontColor; - ctx.textAlign = textAlign; - ctx.textBaseline = textBaseline; - ctx.fillText(textToUse, textXCoordinate, textYCoordinate); - } - if (waterMark) { - ctx.drawImage(waterMark, waterMarkXCoordinate, waterMarkYCoordinate, waterMarkWidth, waterMarkHeight); - } - imageData = ctx.getImageData(0, 0, width, height); - - self.addFrameImageData(imageData); - } catch (e) { - return '' + e; - } - }, - addFrameImageData: function addFrameImageData() { - var imageData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - var frames = this.frames; - var imageDataArray = imageData.data; - - this.frames.push({ - 'data': imageDataArray, - 'width': imageData.width, - 'height': imageData.height, - 'palette': null, - 'dithering': null, - 'done': false, - 'beingProcessed': false, - 'position': frames.length - }); - }, - onRenderProgress: function onRenderProgress(callback) { - this.onRenderProgressCallback = callback; - }, - isRendering: function isRendering() { - return this.generatingGIF; - }, - getBase64GIF: function getBase64GIF(completeCallback) { - var self = this; - var onRenderComplete = function onRenderComplete(gif) { - self.destroyWorkers(); - - utils.requestTimeout(function () { - completeCallback(gif); - }, 0); - }; - - self.startRendering(onRenderComplete); - }, - destroyWorkers: function destroyWorkers() { - if (this.workerError) { - return; - } - - var workers = this.workers; - - // Explicitly ask web workers to die so they are explicitly GC'ed - utils.each(workers, function (iterator, workerObj) { - var worker = workerObj.worker; - var objectUrl = workerObj.objectUrl; - - worker.terminate(); - utils.URL.revokeObjectURL(objectUrl); - }); - } -}; - -/* - getBase64GIF.js - =============== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -function getBase64GIF(animatedGifInstance, callback) { - // This is asynchronous, rendered with WebWorkers - animatedGifInstance.getBase64GIF(function (image) { - callback({ - error: false, - errorCode: '', - errorMsg: '', - image: image - }); - }); -} - -/* - existingImages.js - ================= -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -function existingImages() { - var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - var self = this; - var callback = obj.callback, - images = obj.images, - options = obj.options; - - var imagesLength = obj.imagesLength; - var skipObj = { - 'getUserMedia': true, - 'window.URL': true - }; - var errorObj = error.validate(skipObj); - var loadedImages = []; - var loadedImagesLength = 0; - var tempImage = void 0; - var ag = void 0; - - if (errorObj.error) { - return callback(errorObj); - } - - // change workerPath to point to where Animated_GIF.worker.js is - ag = new AnimatedGIF(options); - - utils.each(images, function (index, image) { - var currentImage = image; - - if (image.src) { - currentImage = currentImage.src; - } - if (utils.isElement(currentImage)) { - if (options.crossOrigin) { - currentImage.crossOrigin = options.crossOrigin; - } - - loadedImages[index] = currentImage; - loadedImagesLength += 1; - - if (loadedImagesLength === imagesLength) { - addLoadedImagesToGif(); - } - } else if (utils.isString(currentImage)) { - tempImage = new Image(); - - if (options.crossOrigin) { - tempImage.crossOrigin = options.crossOrigin; - } - - (function (tempImage) { - if (image.text) { - tempImage.text = image.text; - } - - tempImage.onerror = function (e) { - var obj = void 0; - - --imagesLength; // skips over images that error out - - if (imagesLength === 0) { - obj = {}; - obj.error = 'None of the requested images was capable of being retrieved'; - - return callback(obj); - } - }; - - tempImage.onload = function (e) { - if (image.text) { - loadedImages[index] = { - img: tempImage, - text: tempImage.text - }; - } else { - loadedImages[index] = tempImage; - } - - loadedImagesLength += 1; - - if (loadedImagesLength === imagesLength) { - addLoadedImagesToGif(); - } - - utils.removeElement(tempImage); - }; - - tempImage.src = currentImage; - })(tempImage); - - utils.setCSSAttr(tempImage, { - position: 'fixed', - opacity: '0' - }); - - document.body.appendChild(tempImage); - } - }); - - function addLoadedImagesToGif() { - utils.each(loadedImages, function (index, loadedImage) { - if (loadedImage) { - if (loadedImage.text) { - ag.addFrame(loadedImage.img, options, loadedImage.text); - } else { - ag.addFrame(loadedImage, options); - } - } - }); - - getBase64GIF(ag, callback); - } -} - -/* - screenShot.js - ============= -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -// Helpers -var noop$3 = function noop() {}; - -var screenShot = { - getGIF: function getGIF() { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - var callback = arguments[1]; - - callback = utils.isFunction(callback) ? callback : noop$3; - - var canvas = document.createElement('canvas'); - var context = void 0; - var existingImages = options.images; - var hasExistingImages = !!existingImages.length; - var cameraStream = options.cameraStream, - crop = options.crop, - filter = options.filter, - fontColor = options.fontColor, - fontFamily = options.fontFamily, - fontWeight = options.fontWeight, - keepCameraOn = options.keepCameraOn, - numWorkers = options.numWorkers, - progressCallback = options.progressCallback, - saveRenderingContexts = options.saveRenderingContexts, - savedRenderingContexts = options.savedRenderingContexts, - text = options.text, - textAlign = options.textAlign, - textBaseline = options.textBaseline, - videoElement = options.videoElement, - videoHeight = options.videoHeight, - videoWidth = options.videoWidth, - webcamVideoElement = options.webcamVideoElement, - waterMark = options.waterMark, - waterMarkHeight = options.waterMarkHeight, - waterMarkWidth = options.waterMarkWidth, - waterMarkXCoordinate = options.waterMarkXCoordinate, - waterMarkYCoordinate = options.waterMarkYCoordinate; - - var gifWidth = Number(options.gifWidth); - var gifHeight = Number(options.gifHeight); - var interval = Number(options.interval); - var sampleInterval = Number(options.sampleInterval); - var waitBetweenFrames = hasExistingImages ? 0 : interval * 1000; - var renderingContextsToSave = []; - var numFrames = savedRenderingContexts.length ? savedRenderingContexts.length : options.numFrames; - var pendingFrames = numFrames; - var ag = new AnimatedGIF(options); - var fontSize = utils.getFontSize(options); - var textXCoordinate = options.textXCoordinate ? options.textXCoordinate : textAlign === 'left' ? 1 : textAlign === 'right' ? gifWidth : gifWidth / 2; - var textYCoordinate = options.textYCoordinate ? options.textYCoordinate : textBaseline === 'top' ? 1 : textBaseline === 'center' ? gifHeight / 2 : gifHeight; - var font = fontWeight + ' ' + fontSize + ' ' + fontFamily; - var sourceX = crop ? Math.floor(crop.scaledWidth / 2) : 0; - var sourceWidth = crop ? videoWidth - crop.scaledWidth : 0; - var sourceY = crop ? Math.floor(crop.scaledHeight / 2) : 0; - var sourceHeight = crop ? videoHeight - crop.scaledHeight : 0; - var captureFrames = function captureSingleFrame() { - var framesLeft = pendingFrames - 1; - - if (savedRenderingContexts.length) { - context.putImageData(savedRenderingContexts[numFrames - pendingFrames], 0, 0); - - finishCapture(); - } else { - drawVideo(); - } - - function drawVideo() { - try { - // Makes sure the canvas video heights/widths are in bounds - if (sourceWidth > videoWidth) { - sourceWidth = videoWidth; - } - - if (sourceHeight > videoHeight) { - sourceHeight = videoHeight; - } - - if (sourceX < 0) { - sourceX = 0; - } - - if (sourceY < 0) { - sourceY = 0; - } - - context.filter = filter; - - context.drawImage(videoElement, sourceX, sourceY, sourceWidth, sourceHeight, 0, 0, gifWidth, gifHeight); - - finishCapture(); - } catch (e) { - // There is a Firefox bug that sometimes throws NS_ERROR_NOT_AVAILABLE and - // and IndexSizeError errors when drawing a video element to the canvas - if (e.name === 'NS_ERROR_NOT_AVAILABLE') { - // Wait 100ms before trying again - utils.requestTimeout(drawVideo, 100); - } else { - throw e; - } - } - } - - function finishCapture() { - var imageData = void 0; - - if (saveRenderingContexts) { - renderingContextsToSave.push(context.getImageData(0, 0, gifWidth, gifHeight)); - } - if (waterMark) { - context.drawImage(waterMark, waterMarkXCoordinate, waterMarkYCoordinate, waterMarkWidth, waterMarkHeight); - } - // If there is text to display, make sure to display it on the canvas after the image is drawn - if (text) { - context.font = font; - context.fillStyle = fontColor; - context.textAlign = textAlign; - context.textBaseline = textBaseline; - context.fillText(text, textXCoordinate, textYCoordinate); - } - - imageData = context.getImageData(0, 0, gifWidth, gifHeight); - - ag.addFrameImageData(imageData); - - pendingFrames = framesLeft; - - // Call back with an r value indicating how far along we are in capture - progressCallback((numFrames - pendingFrames) / numFrames); - - if (framesLeft > 0) { - // test - utils.requestTimeout(captureSingleFrame, waitBetweenFrames); - } - - if (!pendingFrames) { - ag.getBase64GIF(function (image) { - callback({ - 'error': false, - 'errorCode': '', - 'errorMsg': '', - 'image': image, - 'cameraStream': cameraStream, - 'videoElement': videoElement, - 'webcamVideoElement': webcamVideoElement, - 'savedRenderingContexts': renderingContextsToSave, - 'keepCameraOn': keepCameraOn - }); - }); - } - } - }; - - numFrames = numFrames !== undefined ? numFrames : 10; - interval = interval !== undefined ? interval : 0.1; // In seconds - - canvas.width = gifWidth; - canvas.height = gifHeight; - context = canvas.getContext('2d'); - - (function capture() { - if (!savedRenderingContexts.length && videoElement.currentTime === 0) { - utils.requestTimeout(capture, 100); - - return; - } - - captureFrames(); - })(); - }, - getCropDimensions: function getCropDimensions() { - var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - var width = obj.videoWidth; - var height = obj.videoHeight; - var gifWidth = obj.gifWidth; - var gifHeight = obj.gifHeight; - var result = { - width: 0, - height: 0, - scaledWidth: 0, - scaledHeight: 0 - }; - - if (width > height) { - result.width = Math.round(width * (gifHeight / height)) - gifWidth; - result.scaledWidth = Math.round(result.width * (height / gifHeight)); - } else { - result.height = Math.round(height * (gifWidth / width)) - gifHeight; - result.scaledHeight = Math.round(result.height * (width / gifWidth)); - } - - return result; - } -}; - -/* - videoStream.js - ============== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -var videoStream = { - loadedData: false, - defaultVideoDimensions: { - width: 640, - height: 480 - }, - findVideoSize: function findVideoSizeMethod(obj) { - findVideoSizeMethod.attempts = findVideoSizeMethod.attempts || 0; - - var cameraStream = obj.cameraStream, - completedCallback = obj.completedCallback, - videoElement = obj.videoElement; - - - if (!videoElement) { - return; - } - - if (videoElement.videoWidth > 0 && videoElement.videoHeight > 0) { - videoElement.removeEventListener('loadeddata', videoStream.findVideoSize); - - completedCallback({ - videoElement: videoElement, - cameraStream: cameraStream, - videoWidth: videoElement.videoWidth, - videoHeight: videoElement.videoHeight - }); - } else { - if (findVideoSizeMethod.attempts < 10) { - findVideoSizeMethod.attempts += 1; - - utils.requestTimeout(function () { - videoStream.findVideoSize(obj); - }, 400); - } else { - completedCallback({ - videoElement: videoElement, - cameraStream: cameraStream, - videoWidth: videoStream.defaultVideoDimensions.width, - videoHeight: videoStream.defaultVideoDimensions.height - }); - } - } - }, - onStreamingTimeout: function onStreamingTimeout(callback) { - if (utils.isFunction(callback)) { - callback({ - error: true, - errorCode: 'getUserMedia', - errorMsg: 'There was an issue with the getUserMedia API - Timed out while trying to start streaming', - image: null, - cameraStream: {} - }); - } - }, - stream: function stream(obj) { - var existingVideo = utils.isArray(obj.existingVideo) ? obj.existingVideo[0] : obj.existingVideo; - var cameraStream = obj.cameraStream, - completedCallback = obj.completedCallback, - streamedCallback = obj.streamedCallback, - videoElement = obj.videoElement; - - - if (utils.isFunction(streamedCallback)) { - streamedCallback(); - } - - if (existingVideo) { - if (utils.isString(existingVideo)) { - videoElement.src = existingVideo; - videoElement.innerHTML = ''; - } else if (existingVideo instanceof Blob) { - try { - videoElement.src = utils.URL.createObjectURL(existingVideo); - } catch (e) {} - - videoElement.innerHTML = ''; - } - } else if (videoElement.mozSrcObject) { - videoElement.mozSrcObject = cameraStream; - } else if (utils.URL) { - try { - videoElement.srcObject = cameraStream; - videoElement.src = utils.URL.createObjectURL(cameraStream); - } catch (e) { - videoElement.srcObject = cameraStream; - } - } - - videoElement.play(); - - utils.requestTimeout(function checkLoadedData() { - checkLoadedData.count = checkLoadedData.count || 0; - - if (videoStream.loadedData === true) { - videoStream.findVideoSize({ - videoElement: videoElement, - cameraStream: cameraStream, - completedCallback: completedCallback - }); - - videoStream.loadedData = false; - } else { - checkLoadedData.count += 1; - - if (checkLoadedData.count > 10) { - videoStream.findVideoSize({ - videoElement: videoElement, - cameraStream: cameraStream, - completedCallback: completedCallback - }); - } else { - checkLoadedData(); - } - } - }, 0); - }, - startStreaming: function startStreaming(obj) { - var errorCallback = utils.isFunction(obj.error) ? obj.error : utils.noop; - var streamedCallback = utils.isFunction(obj.streamed) ? obj.streamed : utils.noop; - var completedCallback = utils.isFunction(obj.completed) ? obj.completed : utils.noop; - var crossOrigin = obj.crossOrigin, - existingVideo = obj.existingVideo, - lastCameraStream = obj.lastCameraStream, - options = obj.options, - webcamVideoElement = obj.webcamVideoElement; - - var videoElement = utils.isElement(existingVideo) ? existingVideo : webcamVideoElement ? webcamVideoElement : document.createElement('video'); - var cameraStream = void 0; - - if (crossOrigin) { - videoElement.crossOrigin = options.crossOrigin; - } - - videoElement.autoplay = true; - videoElement.loop = true; - videoElement.muted = true; - videoElement.addEventListener('loadeddata', function (event) { - videoStream.loadedData = true; - if (options.offset) { - videoElement.currentTime = options.offset; - } - }); - - if (existingVideo) { - videoStream.stream({ - videoElement: videoElement, - existingVideo: existingVideo, - completedCallback: completedCallback - }); - } else if (lastCameraStream) { - videoStream.stream({ - videoElement: videoElement, - cameraStream: lastCameraStream, - streamedCallback: streamedCallback, - completedCallback: completedCallback - }); - } else { - utils.getUserMedia({ - video: true - }, function (stream) { - videoStream.stream({ - videoElement: videoElement, - cameraStream: stream, - streamedCallback: streamedCallback, - completedCallback: completedCallback - }); - }, errorCallback); - } - }, - startVideoStreaming: function startVideoStreaming(callback) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - var timeoutLength = options.timeout !== undefined ? options.timeout : 0; - var originalCallback = options.callback; - var webcamVideoElement = options.webcamVideoElement; - var noGetUserMediaSupportTimeout = void 0; - - // Some browsers apparently have support for video streaming because of the - // presence of the getUserMedia function, but then do not answer our - // calls for streaming. - // So we'll set up this timeout and if nothing happens after a while, we'll - // conclude that there's no actual getUserMedia support. - if (timeoutLength > 0) { - noGetUserMediaSupportTimeout = utils.requestTimeout(function () { - videoStream.onStreamingTimeout(originalCallback); - }, 10000); - } - - videoStream.startStreaming({ - error: function error() { - originalCallback({ - error: true, - errorCode: 'getUserMedia', - errorMsg: 'There was an issue with the getUserMedia API - the user probably denied permission', - image: null, - cameraStream: {} - }); - }, - streamed: function streamed() { - // The streaming started somehow, so we can assume there is getUserMedia support - clearTimeout(noGetUserMediaSupportTimeout); - }, - completed: function completed() { - var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - var cameraStream = obj.cameraStream, - videoElement = obj.videoElement, - videoHeight = obj.videoHeight, - videoWidth = obj.videoWidth; - - - callback({ - cameraStream: cameraStream, - videoElement: videoElement, - videoHeight: videoHeight, - videoWidth: videoWidth - }); - }, - lastCameraStream: options.lastCameraStream, - webcamVideoElement: webcamVideoElement, - crossOrigin: options.crossOrigin, - options: options - }); - }, - stopVideoStreaming: function stopVideoStreaming(obj) { - obj = utils.isObject(obj) ? obj : {}; - - var _obj = obj, - keepCameraOn = _obj.keepCameraOn, - videoElement = _obj.videoElement, - webcamVideoElement = _obj.webcamVideoElement; - - var cameraStream = obj.cameraStream || {}; - var cameraStreamTracks = cameraStream.getTracks ? cameraStream.getTracks() || [] : []; - var hasCameraStreamTracks = !!cameraStreamTracks.length; - var firstCameraStreamTrack = cameraStreamTracks[0]; - - if (!keepCameraOn && hasCameraStreamTracks) { - if (utils.isFunction(firstCameraStreamTrack.stop)) { - // Stops the camera stream - firstCameraStreamTrack.stop(); - } - } - - if (utils.isElement(videoElement) && !webcamVideoElement) { - // Pauses the video, revokes the object URL (freeing up memory), and remove the video element - videoElement.pause(); - - // Destroys the object url - if (utils.isFunction(utils.URL.revokeObjectURL) && !utils.webWorkerError) { - if (videoElement.src) { - utils.URL.revokeObjectURL(videoElement.src); - } - } - - // Removes the video element from the DOM - utils.removeElement(videoElement); - } - } -}; - -/* - stopVideoStreaming.js - ===================== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -function stopVideoStreaming(options) { - options = utils.isObject(options) ? options : {}; - - videoStream.stopVideoStreaming(options); -} - -/* - createAndGetGIF.js - ================== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -function createAndGetGIF(obj, callback) { - var options = obj.options || {}; - - var images = options.images, - video = options.video; - - var gifWidth = Number(options.gifWidth); - var gifHeight = Number(options.gifHeight); - var numFrames = Number(options.numFrames); - var cameraStream = obj.cameraStream, - videoElement = obj.videoElement, - videoWidth = obj.videoWidth, - videoHeight = obj.videoHeight; - - var cropDimensions = screenShot.getCropDimensions({ - videoWidth: videoWidth, - videoHeight: videoHeight, - gifHeight: gifHeight, - gifWidth: gifWidth - }); - var completeCallback = callback; - - options.crop = cropDimensions; - options.videoElement = videoElement; - options.videoWidth = videoWidth; - options.videoHeight = videoHeight; - options.cameraStream = cameraStream; - - if (!utils.isElement(videoElement)) { - return; - } - - videoElement.width = gifWidth + cropDimensions.width; - videoElement.height = gifHeight + cropDimensions.height; - - if (!options.webcamVideoElement) { - utils.setCSSAttr(videoElement, { - position: 'fixed', - opacity: '0' - }); - - document.body.appendChild(videoElement); - } - - // Firefox doesn't seem to obey autoplay if the element is not in the DOM when the content - // is loaded, so we must manually trigger play after adding it, or the video will be frozen - videoElement.play(); - - screenShot.getGIF(options, function (obj) { - if ((!images || !images.length) && (!video || !video.length)) { - stopVideoStreaming(obj); - } - - completeCallback(obj); - }); -} - -/* - existingVideo.js - ================ -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -function existingVideo() { - var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - var callback = obj.callback, - existingVideo = obj.existingVideo, - options = obj.options; - - var skipObj = { - getUserMedia: true, - 'window.URL': true - }; - var errorObj = error.validate(skipObj); - var loadedImages = 0; - var videoType = void 0; - var videoSrc = void 0; - var tempImage = void 0; - var ag = void 0; - - if (errorObj.error) { - return callback(errorObj); - } - - if (utils.isElement(existingVideo) && existingVideo.src) { - videoSrc = existingVideo.src; - videoType = utils.getExtension(videoSrc); - - if (!utils.isSupported.videoCodecs[videoType]) { - return callback(error.messages.videoCodecs); - } - } else if (utils.isArray(existingVideo)) { - utils.each(existingVideo, function (iterator, videoSrc) { - if (videoSrc instanceof Blob) { - videoType = videoSrc.type.substr(videoSrc.type.lastIndexOf('/') + 1, videoSrc.length); - } else { - videoType = videoSrc.substr(videoSrc.lastIndexOf('.') + 1, videoSrc.length); - } - - if (utils.isSupported.videoCodecs[videoType]) { - existingVideo = videoSrc; - - return false; - } - }); - } - - videoStream.startStreaming({ - completed: function completed(obj) { - obj.options = options || {}; - - createAndGetGIF(obj, callback); - }, - existingVideo: existingVideo, - crossOrigin: options.crossOrigin, - options: options - }); -} - -/* - existingWebcam.js - ================= -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -function existingWebcam() { - var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - var callback = obj.callback, - lastCameraStream = obj.lastCameraStream, - options = obj.options, - webcamVideoElement = obj.webcamVideoElement; - - - if (!isWebCamGIFSupported()) { - return callback(error.validate()); - } - - if (options.savedRenderingContexts.length) { - screenShot.getGIF(options, function (obj) { - callback(obj); - }); - - return; - } - - videoStream.startVideoStreaming(function () { - var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - obj.options = options || {}; - - createAndGetGIF(obj, callback); - }, { - lastCameraStream: lastCameraStream, - callback: callback, - webcamVideoElement: webcamVideoElement, - crossOrigin: options.crossOrigin - }); -} - -/* - createGIF.js - ============ -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -function createGIF(userOptions, callback) { - callback = utils.isFunction(userOptions) ? userOptions : callback; - userOptions = utils.isObject(userOptions) ? userOptions : {}; - - if (!utils.isFunction(callback)) { - return; - } - - var options = utils.mergeOptions(defaultOptions, userOptions) || {}; - var lastCameraStream = userOptions.cameraStream; - var images = options.images; - var imagesLength = images ? images.length : 0; - var video = options.video; - var webcamVideoElement = options.webcamVideoElement; - - options = utils.mergeOptions(options, { - 'gifWidth': Math.floor(options.gifWidth), - 'gifHeight': Math.floor(options.gifHeight) - }); - - // If the user would like to create a GIF from an existing image(s) - if (imagesLength) { - existingImages({ - 'images': images, - 'imagesLength': imagesLength, - 'callback': callback, - 'options': options - }); - } else if (video) { - // If the user would like to create a GIF from an existing HTML5 video - existingVideo({ - 'existingVideo': video, - callback: callback, - options: options - }); - } else { - // If the user would like to create a GIF from a webcam stream - existingWebcam({ - lastCameraStream: lastCameraStream, - callback: callback, - webcamVideoElement: webcamVideoElement, - options: options - }); - } -} - -/* - takeSnapShot.js - =============== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -function takeSnapShot(userOptions, callback) { - callback = utils.isFunction(userOptions) ? userOptions : callback; - userOptions = utils.isObject(userOptions) ? userOptions : {}; - - if (!utils.isFunction(callback)) { - return; - } - - var mergedOptions = utils.mergeOptions(defaultOptions, userOptions); - var options = utils.mergeOptions(mergedOptions, { - 'interval': .1, - 'numFrames': 1, - 'gifWidth': Math.floor(mergedOptions.gifWidth), - 'gifHeight': Math.floor(mergedOptions.gifHeight) - }); - - createGIF(options, callback); -} - -/* - API.js - ====== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. -*/ - -// Dependencies -var API = { - 'utils': utils$2, - 'error': error$2, - 'defaultOptions': defaultOptions$2, - 'createGIF': createGIF, - 'takeSnapShot': takeSnapShot, - 'stopVideoStreaming': stopVideoStreaming, - 'isSupported': isSupported, - 'isWebCamGIFSupported': isWebCamGIFSupported, - 'isExistingVideoGIFSupported': isExistingVideoGIFSupported, - 'isExistingImagesGIFSupported': isSupported$1, - 'VERSION': '0.4.5' -}; - -/* - index.js - ======== -*/ - -/* Copyright 2017 Yahoo Inc. - * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. - */ - -// Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, and plain browser loading -if (typeof define === 'function' && define.amd) { - define([], function () { - return API; - }); -} else if (typeof exports !== 'undefined') { - module.exports = API; -} else { - window.gifshot = API; -} -}(typeof window !== "undefined" ? window : {}, typeof document !== "undefined" ? document : { createElement: function() {} }, typeof window !== "undefined" ? window.navigator : {})); diff --git a/dev/libraries/gifshot/gifshot.min.js b/dev/libraries/gifshot/gifshot.min.js deleted file mode 100644 index b8e2d44..0000000 --- a/dev/libraries/gifshot/gifshot.min.js +++ /dev/null @@ -1,8 +0,0 @@ -/*Copyrights for code authored by Yahoo Inc. is licensed under the following terms: -MIT License -Copyright 2017 Yahoo Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -!function(e,t,r,i){"use strict";function n(){return C.isValid()}function o(){return C.isValid()}function a(){var e={getUserMedia:!0};return C.isValid(e)}function s(e){var t=!1;if(w.isArray(e)&&e.length){if(w.each(e,function(e,r){w.isSupported.videoCodecs[r]&&(t=!0)}),!t)return!1}else if(w.isString(e)&&e.length&&!w.isSupported.videoCodecs[e])return!1;return C.isValid({getUserMedia:!0})}function d(){function e(e,t,r){var i,n;for(u=e,m=t,g=r,f=new Array(h),i=0;h>i;i++)f[i]=new Array(4),n=f[i],n[0]=n[1]=n[2]=(i<r;r++)t[f[r][3]]=r;for(var i=0,n=0;h>n;n++){var o=t[n];e[i++]=f[o][0],e[i++]=f[o][1],e[i++]=f[o][2]}return e}function r(){var e,t,r,i,n,o,a,s;for(a=0,s=0,e=0;h>e;e++){for(n=f[e],r=e,i=n[1],t=e+1;h>t;t++)o=f[t],o[1]>1,t=a+1;i>t;t++)P[t]=e;a=i,s=e}}for(P[a]=s+C>>1,t=a+1;256>t;t++)P[t]=C}function i(){var e,t,r,i,n,o,a,f,h,C,x,F,W,O;for(y>m&&(g=1),l=30+(g-1)/3,F=u,W=0,O=m,x=m/(3*g),C=x/S|0,f=V,o=T,a=o>>U,1>=a&&(a=0),e=0;a>e;e++)N[e]=f*((a*a-e*e)*z/(a*a));for(h=y>m?3:m%p!==0?3*p:m%v!==0?3*v:m%b!==0?3*b:3*w,e=0;x>e;)if(r=(255&F[W+0])<=O&&(W-=m),e++,0===C&&(C=1),e%C===0)for(f-=f/l,o-=o/I,a=o>>U,1>=a&&(a=0),t=0;a>t;t++)N[t]=f*((a*a-t*t)*z/(a*a))}function n(e,t,r){var i,n,o,a,s,d,c;for(s=1e3,c=-1,i=P[t],n=i-1;h>i||n>=0;)h>i&&(d=f[i],o=d[1]-t,o>=s?i=h:(i++,0>o&&(o=-o),a=d[0]-e,0>a&&(a=-a),o+=a,s>o&&(a=d[2]-r,0>a&&(a=-a),o+=a,s>o&&(s=o,c=d[3])))),n>=0&&(d=f[n],o=t-d[1],o>=s?n=-1:(n--,0>o&&(o=-o),a=d[0]-e,0>a&&(a=-a),o+=a,s>o&&(a=d[2]-r,0>a&&(a=-a),o+=a,s>o&&(s=o,c=d[3]))));return c}function o(){return i(),a(),r(),t()}function a(){var e;for(e=0;h>e;e++)f[e][0]>>=k,f[e][1]>>=k,f[e][2]>>=k,f[e][3]=e}function s(e,t,r,i,n){var o,a,s,d,c,l,u;for(s=t-e,-1>s&&(s=-1),d=t+e,d>h&&(d=h),o=t+1,a=t-1,l=1;d>o||a>s;){if(c=N[l++],d>o){u=f[o++];try{u[0]-=c*(u[0]-r)/B|0,u[1]-=c*(u[1]-i)/B|0,u[2]-=c*(u[2]-n)/B|0}catch(m){}}if(a>s){u=f[a--];try{u[0]-=c*(u[0]-r)/B|0,u[1]-=c*(u[1]-i)/B|0,u[2]-=c*(u[2]-n)/B|0}catch(m){}}}}function d(e,t,r,i,n){var o=f[t],a=e/V;o[0]-=a*(o[0]-r)|0,o[1]-=a*(o[1]-i)|0,o[2]-=a*(o[2]-n)|0}function c(e,t,r){var i,n,o,a,s,d,c,l,u,m;for(l=~(1<<31),u=l,d=-1,c=d,i=0;h>i;i++)m=f[i],n=m[0]-e,0>n&&(n=-n),o=m[1]-t,0>o&&(o=-o),n+=o,o=m[2]-r,0>o&&(o=-o),n+=o,l>n&&(l=n,d=i),a=n-(G[i]>>x-k),u>a&&(u=a,c=i),s=D[i]>>O,D[i]-=s,G[i]+=s<>O,M=F<>3,U=6,R=1<n;)o.push(e[n++]),o.push(e[n++]),o.push(e[n++]),n++;return o},componentizedPaletteToArray:function(e){e=e||[];for(var t=[],r=0;rm;m++){var g=n[u++],f=n[u++],h=n[u++];l[m]=o.map(g,f,h)}return{pixels:l,palette:s}},run:function(e){e=e||{};var t=e,r=t.height,i=(t.palette,t.sampleInterval),n=t.width,o=e.data;return this.processFrameWithQuantizer(o,n,r,i)}};return r}function l(e,t,r,n){function o(e){var t=e.length;if(2>t||t>256||t&t-1)throw"Invalid code/color length, must be power of 2 and 2 .. 256.";return t}function a(e,t,r,n){function o(r){for(;g>=r;)e[t++]=255&f,f>>=8,g-=8,t===s+256&&(e[s]=255,s=t++)}function a(e){f|=e<v;++v){var w=n[v]&c,y=h<<8|w,C=p[y];if(C===i){for(f|=h<=8;)e[t++]=255&f,f>>=8,g-=8,t===s+256&&(e[s]=255,s=t++);4096===u?(a(d),u=l+1,m=r+1,p={}):(u>=1<=t||0>=r||t>65535||r>65535)throw"Width/Height invalid.";e[s++]=71,e[s++]=73,e[s++]=70,e[s++]=56,e[s++]=57,e[s++]=97;var l=0,u=0;if(e[s++]=255&t,e[s++]=t>>8&255,e[s++]=255&r,e[s++]=r>>8&255,e[s++]=(null!==c?128:0)|l,e[s++]=u,e[s++]=0,null!==d){if(0>d||d>65535)throw"Loop count invalid.";e[s++]=33,e[s++]=255,e[s++]=11,e[s++]=78,e[s++]=69,e[s++]=84,e[s++]=83,e[s++]=67,e[s++]=65,e[s++]=80,e[s++]=69,e[s++]=50,e[s++]=46,e[s++]=48,e[s++]=3,e[s++]=1,e[s++]=255&d,e[s++]=d>>8&255,e[s++]=0}var m=!1;this.addFrame=function(t,r,n,d,l,u){if(m===!0&&(--s,m=!1),u=u===i?{}:u,0>t||0>r||t>65535||r>65535)throw"x/y invalid.";if(0>=n||0>=d||n>65535||d>65535)throw"Width/Height invalid.";if(l.length>=1;)++p;h=1<b||b>3)throw"Disposal out of range.";var w=!1,y=0;if(u.transparent!==i&&null!==u.transparent&&(w=!0,y=u.transparent,0>y||y>=h))throw"Transparent color index.";if((0!==b||w||0!==v)&&(e[s++]=33,e[s++]=249,e[s++]=4,e[s++]=b<<2|(w===!0?1:0),e[s++]=255&v,e[s++]=v>>8&255,e[s++]=y,e[s++]=0),e[s++]=44,e[s++]=255&t,e[s++]=t>>8&255,e[s++]=255&r,e[s++]=r>>8&255,e[s++]=255&n,e[s++]=n>>8&255,e[s++]=255&d,e[s++]=d>>8&255,e[s++]=g===!0?128|p-1:0,g===!0)for(var C=0,k=f.length;k>C;++C){var S=f[C];e[s++]=S>>16&255,e[s++]=S>>8&255,e[s++]=255&S}s=a(e,s,2>p?2:p,l)},this.end=function(){return m===!1&&(e[s++]=59,m=!0),s}}function u(e,t){e.getBase64GIF(function(e){t({error:!1,errorCode:"",errorMsg:"",image:e})})}function m(){function e(){w.each(l,function(e,t){t&&(t.text?f.addFrame(t.img,a,t.text):f.addFrame(t,a))}),u(f,n)}var r=arguments.length>0&&arguments[0]!==i?arguments[0]:{},n=r.callback,o=r.images,a=r.options,s=r.imagesLength,d={getUserMedia:!0,"window.URL":!0},c=C.validate(d),l=[],m=0,g=void 0,f=void 0;return c.error?n(c):(f=new O(a),w.each(o,function(r,i){var o=i;i.src&&(o=o.src),w.isElement(o)?(a.crossOrigin&&(o.crossOrigin=a.crossOrigin),l[r]=o,m+=1,m===s&&e()):w.isString(o)&&(g=new Image,a.crossOrigin&&(g.crossOrigin=a.crossOrigin),function(t){i.text&&(t.text=i.text),t.onerror=function(){var e=void 0;return--s,0===s?(e={},e.error="None of the requested images was capable of being retrieved",n(e)):void 0},t.onload=function(){l[r]=i.text?{img:t,text:t.text}:t,m+=1,m===s&&e(),w.removeElement(t)},t.src=o}(g),w.setCSSAttr(g,{position:"fixed",opacity:"0"}),t.body.appendChild(g))}),void 0)}function g(e){e=w.isObject(e)?e:{},A.stopVideoStreaming(e)}function f(e,r){var i=e.options||{},n=i.images,o=i.video,a=Number(i.gifWidth),s=Number(i.gifHeight),d=(Number(i.numFrames),e.cameraStream),c=e.videoElement,l=e.videoWidth,u=e.videoHeight,m=M.getCropDimensions({videoWidth:l,videoHeight:u,gifHeight:s,gifWidth:a}),f=r;i.crop=m,i.videoElement=c,i.videoWidth=l,i.videoHeight=u,i.cameraStream=d,w.isElement(c)&&(c.width=a+m.width,c.height=s+m.height,i.webcamVideoElement||(w.setCSSAttr(c,{position:"fixed",opacity:"0"}),t.body.appendChild(c)),c.play(),M.getGIF(i,function(e){n&&n.length||o&&o.length||g(e),f(e)}))}function h(){var e=arguments.length>0&&arguments[0]!==i?arguments[0]:{},t=e.callback,r=e.existingVideo,n=e.options,o={getUserMedia:!0,"window.URL":!0},a=C.validate(o),s=void 0,d=void 0;if(a.error)return t(a);if(w.isElement(r)&&r.src){if(d=r.src,s=w.getExtension(d),!w.isSupported.videoCodecs[s])return t(C.messages.videoCodecs)}else w.isArray(r)&&w.each(r,function(e,t){return s=t instanceof Blob?t.type.substr(t.type.lastIndexOf("/")+1,t.length):t.substr(t.lastIndexOf(".")+1,t.length),w.isSupported.videoCodecs[s]?(r=t,!1):void 0});A.startStreaming({completed:function(e){e.options=n||{},f(e,t)},existingVideo:r,crossOrigin:n.crossOrigin,options:n})}function p(){var e=arguments.length>0&&arguments[0]!==i?arguments[0]:{},t=e.callback,r=e.lastCameraStream,n=e.options,a=e.webcamVideoElement;return o()?n.savedRenderingContexts.length?(M.getGIF(n,function(e){t(e)}),void 0):(A.startVideoStreaming(function(){var e=arguments.length>0&&arguments[0]!==i?arguments[0]:{};e.options=n||{},f(e,t)},{lastCameraStream:r,callback:t,webcamVideoElement:a,crossOrigin:n.crossOrigin}),void 0):t(C.validate())}function v(e,t){if(t=w.isFunction(e)?e:t,e=w.isObject(e)?e:{},w.isFunction(t)){var r=w.mergeOptions(x,e)||{},i=e.cameraStream,n=r.images,o=n?n.length:0,a=r.video,s=r.webcamVideoElement;r=w.mergeOptions(r,{gifWidth:Math.floor(r.gifWidth),gifHeight:Math.floor(r.gifHeight)}),o?m({images:n,imagesLength:o,callback:t,options:r}):a?h({existingVideo:a,callback:t,options:r}):p({lastCameraStream:i,callback:t,webcamVideoElement:s,options:r})}}function b(e,t){if(t=w.isFunction(e)?e:t,e=w.isObject(e)?e:{},w.isFunction(t)){var r=w.mergeOptions(x,e),i=w.mergeOptions(r,{interval:.1,numFrames:1,gifWidth:Math.floor(r.gifWidth),gifHeight:Math.floor(r.gifHeight)});v(i,t)}}var w={URL:e.URL||e.webkitURL||e.mozURL||e.msURL,getUserMedia:function(){var e=r.getUserMedia||r.webkitGetUserMedia||r.mozGetUserMedia||r.msGetUserMedia;return e?e.bind(r):e}(),requestAnimFrame:e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame||e.msRequestAnimationFrame,requestTimeout:function(e,t){if(e=e||w.noop,t=t||0,!w.requestAnimFrame)return setTimeout(e,t);var r=(new Date).getTime(),i=new Object,n=w.requestAnimFrame,o=function a(){var o=(new Date).getTime(),s=o-r;s>=t?e.call():i.value=n(a)};return i.value=n(o),i},Blob:e.Blob||e.BlobBuilder||e.WebKitBlobBuilder||e.MozBlobBuilder||e.MSBlobBuilder,btoa:function(){var t=e.btoa||function(e){for(var t="",r=0,i=e.length,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",o=void 0,a=void 0,s=void 0,d=void 0,c=void 0,l=void 0,u=void 0;i>r;)o=e.charCodeAt(r++),a=e.charCodeAt(r++),s=e.charCodeAt(r++),d=o>>2,c=(3&o)<<4|a>>4,l=(15&a)<<2|s>>6,u=63&s,isNaN(a)?l=u=64:isNaN(s)&&(u=64),t=t+n.charAt(d)+n.charAt(c)+n.charAt(l)+n.charAt(u);return t};return t?t.bind(e):w.noop}(),isObject:function(e){return e&&"[object Object]"===Object.prototype.toString.call(e)},isEmptyObject:function(e){return w.isObject(e)&&!Object.keys(e).length},isArray:function(e){return e&&Array.isArray(e)},isFunction:function(e){return e&&"function"==typeof e},isElement:function(e){return e&&1===e.nodeType},isString:function(e){return"string"==typeof e||"[object String]"===Object.prototype.toString.call(e)},isSupported:{canvas:function(){var e=t.createElement("canvas");return e&&e.getContext&&e.getContext("2d")},webworkers:function(){return e.Worker},blob:function(){return w.Blob},Uint8Array:function(){return e.Uint8Array},Uint32Array:function(){return e.Uint32Array},videoCodecs:function(){var e=t.createElement("video"),r={mp4:!1,h264:!1,ogv:!1,ogg:!1,webm:!1};try{e&&e.canPlayType&&(r.mp4=""!==e.canPlayType('video/mp4; codecs="mp4v.20.8"'),r.h264=""!==(e.canPlayType('video/mp4; codecs="avc1.42E01E"')||e.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')),r.ogv=""!==e.canPlayType('video/ogg; codecs="theora"'),r.ogg=""!==e.canPlayType('video/ogg; codecs="theora"'),r.webm=-1!==e.canPlayType('video/webm; codecs="vp8, vorbis"'))}catch(i){}return r}()},noop:function(){},each:function(e,t){var r=void 0,i=void 0;if(w.isArray(e))for(r=-1,i=e.length;++r0&&arguments[0]!==i?arguments[0]:{};if(!t.body||e.resizeFont===!1)return e.fontSize;var r=e.text,n=e.gifWidth,o=parseInt(e.fontSize,10),a=parseInt(e.minFontSize,10),s=t.createElement("div"),d=t.createElement("span");for(s.setAttribute("width",n),s.appendChild(d),d.innerHTML=r,d.style.fontSize=o+"px",d.style.textIndent="-9999px",d.style.visibility="hidden",t.body.appendChild(d);d.offsetWidth>n&&o>=a;)d.style.fontSize=--o+"px";return t.body.removeChild(d),o+"px"},webWorkerError:!1},y=Object.freeze({"default":w}),C={validate:function(e){e=w.isObject(e)?e:{};var t={};return w.each(C.validators,function(r,i){var n=i.errorCode;return e[n]||i.condition?void 0:(t=i,t.error=!0,!1)}),delete t.condition,t},isValid:function R(e){var t=C.validate(e),R=t.error!==!0?!0:!1;return R},validators:[{condition:w.isFunction(w.getUserMedia),errorCode:"getUserMedia",errorMsg:"The getUserMedia API is not supported in your browser"},{condition:w.isSupported.canvas(),errorCode:"canvas",errorMsg:"Canvas elements are not supported in your browser"},{condition:w.isSupported.webworkers(),errorCode:"webworkers",errorMsg:"The Web Workers API is not supported in your browser"},{condition:w.isFunction(w.URL),errorCode:"window.URL",errorMsg:"The window.URL API is not supported in your browser"},{condition:w.isSupported.blob(),errorCode:"window.Blob",errorMsg:"The window.Blob File API is not supported in your browser"},{condition:w.isSupported.Uint8Array(),errorCode:"window.Uint8Array",errorMsg:"The window.Uint8Array function constructor is not supported in your browser"},{condition:w.isSupported.Uint32Array(),errorCode:"window.Uint32Array",errorMsg:"The window.Uint32Array function constructor is not supported in your browser"}],messages:{videoCodecs:{errorCode:"videocodec",errorMsg:"The video codec you are trying to use is not supported in your browser"}}},k=Object.freeze({"default":C}),S=function(){},x={sampleInterval:10,numWorkers:2,filter:"",gifWidth:200,gifHeight:200,interval:.1,numFrames:10,frameDuration:1,keepCameraOn:!1,images:[],video:null,webcamVideoElement:null,cameraStream:null,text:"",fontWeight:"normal",fontSize:"16px",minFontSize:"10px",resizeFont:!1,fontFamily:"sans-serif",fontColor:"#ffffff",textAlign:"center",textBaseline:"bottom",textXCoordinate:null,textYCoordinate:null,progressCallback:S,completeCallback:S,saveRenderingContexts:!1,savedRenderingContexts:[],showFrameText:!0,crossOrigin:"Anonymous",waterMark:null,waterMarkHeight:null,waterMarkWidth:null,waterMarkXCoordinate:1,waterMarkYCoordinate:1},F=Object.freeze({"default":x}),W=function(){},O=function(e){this.canvas=null,this.ctx=null,this.repeat=0,this.frames=[],this.numRenderedFrames=0,this.onRenderCompleteCallback=W,this.onRenderProgressCallback=W,this.workers=[],this.availableWorkers=[],this.generatingGIF=!1,this.options=e,this.initializeWebWorkers(e)};O.prototype={workerMethods:c(),initializeWebWorkers:function(e){var r=this,i=d.toString()+"("+c.toString()+"());",n=void 0,o=void 0,a=void 0,s=void 0,l=-1,u="";for(s=e.numWorkers;++lt;t++)e[t]=String.fromCharCode(t);return e}(),bufferToString:function(e){for(var t=e.length,r="",i=-1;++i0&&arguments[0]!==i?arguments[0]:{},r=e.data;delete s.data,s.pixels=Array.prototype.slice.call(r.pixels),s.palette=Array.prototype.slice.call(r.palette),s.done=!0,s.beingProcessed=!1,t.freeWorker(d),t.onFrameFinished(n)};return s=a[e],s.beingProcessed||s.done?(this.onFrameFinished(),void 0):(s.sampleInterval=o,s.beingProcessed=!0,s.gifshot=!0,d=this.getWorker(),d?(d.onmessage=c,d.postMessage(s)):c({data:t.workerMethods.run(s)}),void 0)},startRendering:function(e){this.onRenderCompleteCallback=e;for(var t=0;t=0&&this.processFrame(e)},generateGIF:function(e,t){var r=[],i={loop:this.repeat},n=this.options,o=n.interval,a=n.frameDuration,s=n.images,d=!!s.length,c=n.gifHeight,u=n.gifWidth,m=new l(r,u,c,i),g=this.onRenderProgressCallback,f=d?100*o:0,h=void 0,p=void 0;this.generatingGIF=!0,w.each(e,function(t,r){var i=r.palette;g(.75+.25*r.position*1/e.length);for(var n=0;a>n;n++)m.addFrame(0,0,u,c,r.pixels,{palette:i,delay:f})}),m.end(),g(1),this.frames=[],this.generatingGIF=!1,w.isFunction(t)&&(h=this.bufferToString(r),p="data:image/gif;base64,"+w.btoa(h),t(p))},setRepeat:function(e){this.repeat=e},addFrame:function(e,t,r){t=w.isObject(t)?t:{};var i=this,n=i.ctx,o=i.options,a=o.gifWidth,s=o.gifHeight,d=w.getFontSize(t),c=t,l=c.filter,u=c.fontColor,m=c.fontFamily,g=c.fontWeight,f=(c.gifHeight,c.gifWidth,c.text),h=c.textAlign,p=c.textBaseline,v=c.waterMark,b=c.waterMarkHeight,y=c.waterMarkWidth,C=c.waterMarkXCoordinate,k=c.waterMarkYCoordinate,S=t.textXCoordinate?t.textXCoordinate:"left"===h?1:"right"===h?a:a/2,x=t.textYCoordinate?t.textYCoordinate:"top"===p?1:"center"===p?s/2:s,F=g+" "+d+" "+m,W=r&&t.showFrameText?r:f,O=void 0;try{n.filter=l,n.drawImage(e,0,0,a,s),W&&(n.font=F,n.fillStyle=u,n.textAlign=h,n.textBaseline=p,n.fillText(W,S,x)),v&&n.drawImage(v,C,k,y,b),O=n.getImageData(0,0,a,s),i.addFrameImageData(O)}catch(E){return""+E}},addFrameImageData:function(){var e=arguments.length>0&&arguments[0]!==i?arguments[0]:{},t=this.frames,r=e.data;this.frames.push({data:r,width:e.width,height:e.height,palette:null,dithering:null,done:!1,beingProcessed:!1,position:t.length})},onRenderProgress:function(e){this.onRenderProgressCallback=e},isRendering:function(){return this.generatingGIF},getBase64GIF:function(e){var t=this,r=function(r){t.destroyWorkers(),w.requestTimeout(function(){e(r)},0)};t.startRendering(r)},destroyWorkers:function(){if(!this.workerError){var e=this.workers;w.each(e,function(e,t){var r=t.worker,i=t.objectUrl;r.terminate(),w.URL.revokeObjectURL(i)})}}};var E=function(){},M={getGIF:function(){var e=arguments.length>0&&arguments[0]!==i?arguments[0]:{},r=arguments[1];r=w.isFunction(r)?r:E;var n=t.createElement("canvas"),o=void 0,a=e.images,s=!!a.length,d=e.cameraStream,c=e.crop,l=e.filter,u=e.fontColor,m=e.fontFamily,g=e.fontWeight,f=e.keepCameraOn,h=(e.numWorkers,e.progressCallback),p=e.saveRenderingContexts,v=e.savedRenderingContexts,b=e.text,y=e.textAlign,C=e.textBaseline,k=e.videoElement,S=e.videoHeight,x=e.videoWidth,F=e.webcamVideoElement,W=e.waterMark,M=e.waterMarkHeight,A=e.waterMarkWidth,U=e.waterMarkXCoordinate,R=e.waterMarkYCoordinate,T=Number(e.gifWidth),I=Number(e.gifHeight),j=Number(e.interval),V=(Number(e.sampleInterval),s?0:1e3*j),H=[],z=v.length?v.length:e.numFrames,L=z,B=new O(e),P=w.getFontSize(e),G=e.textXCoordinate?e.textXCoordinate:"left"===y?1:"right"===y?T:T/2,D=e.textYCoordinate?e.textYCoordinate:"top"===C?1:"center"===C?I/2:I,N=g+" "+P+" "+m,q=c?Math.floor(c.scaledWidth/2):0,X=c?x-c.scaledWidth:0,Y=c?Math.floor(c.scaledHeight/2):0,Q=c?S-c.scaledHeight:0,_=function K(){function e(){try{X>x&&(X=x),Q>S&&(Q=S),0>q&&(q=0),0>Y&&(Y=0),o.filter=l,o.drawImage(k,q,Y,X,Q,0,0,T,I),t()}catch(r){if("NS_ERROR_NOT_AVAILABLE"!==r.name)throw r;w.requestTimeout(e,100)}}function t(){var e=void 0;p&&H.push(o.getImageData(0,0,T,I)),W&&o.drawImage(W,U,R,A,M),b&&(o.font=N,o.fillStyle=u,o.textAlign=y,o.textBaseline=C,o.fillText(b,G,D)),e=o.getImageData(0,0,T,I),B.addFrameImageData(e),L=i,h((z-L)/z),i>0&&w.requestTimeout(K,V),L||B.getBase64GIF(function(e){r({error:!1,errorCode:"",errorMsg:"",image:e,cameraStream:d,videoElement:k,webcamVideoElement:F,savedRenderingContexts:H,keepCameraOn:f})})}var i=L-1;v.length?(o.putImageData(v[z-L],0,0),t()):e()};z=z!==i?z:10,j=j!==i?j:.1,n.width=T,n.height=I,o=n.getContext("2d"),function J(){return v.length||0!==k.currentTime?(_(),void 0):(w.requestTimeout(J,100),void 0)}()},getCropDimensions:function(){var e=arguments.length>0&&arguments[0]!==i?arguments[0]:{},t=e.videoWidth,r=e.videoHeight,n=e.gifWidth,o=e.gifHeight,a={width:0,height:0,scaledWidth:0,scaledHeight:0};return t>r?(a.width=Math.round(t*(o/r))-n,a.scaledWidth=Math.round(a.width*(r/o))):(a.height=Math.round(r*(n/t))-o,a.scaledHeight=Math.round(a.height*(t/n))),a}},A={loadedData:!1,defaultVideoDimensions:{width:640,height:480},findVideoSize:function T(e){T.attempts=T.attempts||0;var t=e.cameraStream,r=e.completedCallback,i=e.videoElement;i&&(i.videoWidth>0&&i.videoHeight>0?(i.removeEventListener("loadeddata",A.findVideoSize),r({videoElement:i,cameraStream:t,videoWidth:i.videoWidth,videoHeight:i.videoHeight})):T.attempts<10?(T.attempts+=1,w.requestTimeout(function(){A.findVideoSize(e)},400)):r({videoElement:i,cameraStream:t,videoWidth:A.defaultVideoDimensions.width,videoHeight:A.defaultVideoDimensions.height}))},onStreamingTimeout:function(e){w.isFunction(e)&&e({error:!0,errorCode:"getUserMedia",errorMsg:"There was an issue with the getUserMedia API - Timed out while trying to start streaming",image:null,cameraStream:{}})},stream:function(e){var t=w.isArray(e.existingVideo)?e.existingVideo[0]:e.existingVideo,r=e.cameraStream,i=e.completedCallback,n=e.streamedCallback,o=e.videoElement;if(w.isFunction(n)&&n(),t){if(w.isString(t))o.src=t,o.innerHTML='';else if(t instanceof Blob){try{o.src=w.URL.createObjectURL(t)}catch(a){}o.innerHTML=''}}else if(o.mozSrcObject)o.mozSrcObject=r;else if(w.URL)try{o.srcObject=r,o.src=w.URL.createObjectURL(r)}catch(a){o.srcObject=r}o.play(),w.requestTimeout(function s(){s.count=s.count||0,A.loadedData===!0?(A.findVideoSize({videoElement:o,cameraStream:r,completedCallback:i}),A.loadedData=!1):(s.count+=1,s.count>10?A.findVideoSize({videoElement:o,cameraStream:r,completedCallback:i}):s())},0)},startStreaming:function(e){var r=w.isFunction(e.error)?e.error:w.noop,i=w.isFunction(e.streamed)?e.streamed:w.noop,n=w.isFunction(e.completed)?e.completed:w.noop,o=e.crossOrigin,a=e.existingVideo,s=e.lastCameraStream,d=e.options,c=e.webcamVideoElement,l=w.isElement(a)?a:c?c:t.createElement("video");o&&(l.crossOrigin=d.crossOrigin),l.autoplay=!0,l.loop=!0,l.muted=!0,l.addEventListener("loadeddata",function(){A.loadedData=!0,d.offset&&(l.currentTime=d.offset)}),a?A.stream({videoElement:l,existingVideo:a,completedCallback:n}):s?A.stream({videoElement:l,cameraStream:s,streamedCallback:i,completedCallback:n}):w.getUserMedia({video:!0},function(e){A.stream({videoElement:l,cameraStream:e,streamedCallback:i,completedCallback:n})},r)},startVideoStreaming:function(e){var t=arguments.length>1&&arguments[1]!==i?arguments[1]:{},r=t.timeout!==i?t.timeout:0,n=t.callback,o=t.webcamVideoElement,a=void 0;r>0&&(a=w.requestTimeout(function(){A.onStreamingTimeout(n)},1e4)),A.startStreaming({error:function(){n({error:!0,errorCode:"getUserMedia",errorMsg:"There was an issue with the getUserMedia API - the user probably denied permission",image:null,cameraStream:{}})},streamed:function(){clearTimeout(a)},completed:function(){var t=arguments.length>0&&arguments[0]!==i?arguments[0]:{},r=t.cameraStream,n=t.videoElement,o=t.videoHeight,a=t.videoWidth;e({cameraStream:r,videoElement:n,videoHeight:o,videoWidth:a})},lastCameraStream:t.lastCameraStream,webcamVideoElement:o,crossOrigin:t.crossOrigin,options:t})},stopVideoStreaming:function(e){e=w.isObject(e)?e:{};var t=e,r=t.keepCameraOn,i=t.videoElement,n=t.webcamVideoElement,o=e.cameraStream||{},a=o.getTracks?o.getTracks()||[]:[],s=!!a.length,d=a[0];!r&&s&&w.isFunction(d.stop)&&d.stop(),w.isElement(i)&&!n&&(i.pause(),w.isFunction(w.URL.revokeObjectURL)&&!w.webWorkerError&&i.src&&w.URL.revokeObjectURL(i.src),w.removeElement(i))}},U={utils:y,error:k,defaultOptions:F,createGIF:v,takeSnapShot:b,stopVideoStreaming:g,isSupported:n,isWebCamGIFSupported:o,isExistingVideoGIFSupported:s,isExistingImagesGIFSupported:a,VERSION:"0.4.5"};"function"==typeof define&&define.amd?define([],function(){return U}):"undefined"!=typeof exports?module.exports=U:e.gifshot=U}("undefined"!=typeof window?window:{},"undefined"!=typeof document?document:{createElement:function(){}},"undefined"!=typeof window?window.navigator:{}); \ No newline at end of file diff --git a/dev/libraries/gsap/.DS_Store b/dev/libraries/gsap/.DS_Store deleted file mode 100644 index a1e6843..0000000 Binary files a/dev/libraries/gsap/.DS_Store and /dev/null differ diff --git a/dev/libraries/gsap/docs-link.html b/dev/libraries/gsap/docs-link.html deleted file mode 100644 index 9f79b00..0000000 --- a/dev/libraries/gsap/docs-link.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - -GSAP Documentation - - - - diff --git a/dev/libraries/gsap/esm/.DS_Store b/dev/libraries/gsap/esm/.DS_Store deleted file mode 100644 index ce2147e..0000000 Binary files a/dev/libraries/gsap/esm/.DS_Store and /dev/null differ diff --git a/dev/libraries/gsap/esm/CSSPlugin.js b/dev/libraries/gsap/esm/CSSPlugin.js deleted file mode 100644 index 9864207..0000000 --- a/dev/libraries/gsap/esm/CSSPlugin.js +++ /dev/null @@ -1,1417 +0,0 @@ -/*! - * CSSPlugin 3.7.1 - * https://greensock.com - * - * Copyright 2008-2021, GreenSock. All rights reserved. - * Subject to the terms at https://greensock.com/standard-license or for - * Club GreenSock members, the agreement issued with that membership. - * @author: Jack Doyle, jack@greensock.com -*/ - -/* eslint-disable */ -import { gsap, _getProperty, _numExp, _numWithUnitExp, getUnit, _isString, _isUndefined, _renderComplexString, _relExp, _forEachName, _sortPropTweensByPriority, _colorStringFilter, _checkPlugin, _replaceRandom, _plugins, GSCache, PropTween, _config, _ticker, _round, _missingPlugin, _getSetter, _getCache, _colorExp, _setDefaults, _removeLinkedListItem //for the commented-out className feature. -} from "./gsap-core.js"; - -var _win, - _doc, - _docElement, - _pluginInitted, - _tempDiv, - _tempDivStyler, - _recentSetterPlugin, - _windowExists = function _windowExists() { - return typeof window !== "undefined"; -}, - _transformProps = {}, - _RAD2DEG = 180 / Math.PI, - _DEG2RAD = Math.PI / 180, - _atan2 = Math.atan2, - _bigNum = 1e8, - _capsExp = /([A-Z])/g, - _horizontalExp = /(?:left|right|width|margin|padding|x)/i, - _complexExp = /[\s,\(]\S/, - _propertyAliases = { - autoAlpha: "opacity,visibility", - scale: "scaleX,scaleY", - alpha: "opacity" -}, - _renderCSSProp = function _renderCSSProp(ratio, data) { - return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data); -}, - _renderPropWithEnd = function _renderPropWithEnd(ratio, data) { - return data.set(data.t, data.p, ratio === 1 ? data.e : Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data); -}, - _renderCSSPropWithBeginning = function _renderCSSPropWithBeginning(ratio, data) { - return data.set(data.t, data.p, ratio ? Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u : data.b, data); -}, - //if units change, we need a way to render the original unit/value when the tween goes all the way back to the beginning (ratio:0) -_renderRoundedCSSProp = function _renderRoundedCSSProp(ratio, data) { - var value = data.s + data.c * ratio; - data.set(data.t, data.p, ~~(value + (value < 0 ? -.5 : .5)) + data.u, data); -}, - _renderNonTweeningValue = function _renderNonTweeningValue(ratio, data) { - return data.set(data.t, data.p, ratio ? data.e : data.b, data); -}, - _renderNonTweeningValueOnlyAtEnd = function _renderNonTweeningValueOnlyAtEnd(ratio, data) { - return data.set(data.t, data.p, ratio !== 1 ? data.b : data.e, data); -}, - _setterCSSStyle = function _setterCSSStyle(target, property, value) { - return target.style[property] = value; -}, - _setterCSSProp = function _setterCSSProp(target, property, value) { - return target.style.setProperty(property, value); -}, - _setterTransform = function _setterTransform(target, property, value) { - return target._gsap[property] = value; -}, - _setterScale = function _setterScale(target, property, value) { - return target._gsap.scaleX = target._gsap.scaleY = value; -}, - _setterScaleWithRender = function _setterScaleWithRender(target, property, value, data, ratio) { - var cache = target._gsap; - cache.scaleX = cache.scaleY = value; - cache.renderTransform(ratio, cache); -}, - _setterTransformWithRender = function _setterTransformWithRender(target, property, value, data, ratio) { - var cache = target._gsap; - cache[property] = value; - cache.renderTransform(ratio, cache); -}, - _transformProp = "transform", - _transformOriginProp = _transformProp + "Origin", - _supports3D, - _createElement = function _createElement(type, ns) { - var e = _doc.createElementNS ? _doc.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc.createElement(type); //some servers swap in https for http in the namespace which can break things, making "style" inaccessible. - - return e.style ? e : _doc.createElement(type); //some environments won't allow access to the element's style when created with a namespace in which case we default to the standard createElement() to work around the issue. Also note that when GSAP is embedded directly inside an SVG file, createElement() won't allow access to the style object in Firefox (see https://greensock.com/forums/topic/20215-problem-using-tweenmax-in-standalone-self-containing-svg-file-err-cannot-set-property-csstext-of-undefined/). -}, - _getComputedProperty = function _getComputedProperty(target, property, skipPrefixFallback) { - var cs = getComputedStyle(target); - return cs[property] || cs.getPropertyValue(property.replace(_capsExp, "-$1").toLowerCase()) || cs.getPropertyValue(property) || !skipPrefixFallback && _getComputedProperty(target, _checkPropPrefix(property) || property, 1) || ""; //css variables may not need caps swapped out for dashes and lowercase. -}, - _prefixes = "O,Moz,ms,Ms,Webkit".split(","), - _checkPropPrefix = function _checkPropPrefix(property, element, preferPrefix) { - var e = element || _tempDiv, - s = e.style, - i = 5; - - if (property in s && !preferPrefix) { - return property; - } - - property = property.charAt(0).toUpperCase() + property.substr(1); - - while (i-- && !(_prefixes[i] + property in s)) {} - - return i < 0 ? null : (i === 3 ? "ms" : i >= 0 ? _prefixes[i] : "") + property; -}, - _initCore = function _initCore() { - if (_windowExists() && window.document) { - _win = window; - _doc = _win.document; - _docElement = _doc.documentElement; - _tempDiv = _createElement("div") || { - style: {} - }; - _tempDivStyler = _createElement("div"); - _transformProp = _checkPropPrefix(_transformProp); - _transformOriginProp = _transformProp + "Origin"; - _tempDiv.style.cssText = "border-width:0;line-height:0;position:absolute;padding:0"; //make sure to override certain properties that may contaminate measurements, in case the user has overreaching style sheets. - - _supports3D = !!_checkPropPrefix("perspective"); - _pluginInitted = 1; - } -}, - _getBBoxHack = function _getBBoxHack(swapIfPossible) { - //works around issues in some browsers (like Firefox) that don't correctly report getBBox() on SVG elements inside a element and/or . We try creating an SVG, adding it to the documentElement and toss the element in there so that it's definitely part of the rendering tree, then grab the bbox and if it works, we actually swap out the original getBBox() method for our own that does these extra steps whenever getBBox is needed. This helps ensure that performance is optimal (only do all these extra steps when absolutely necessary...most elements don't need it). - var svg = _createElement("svg", this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"), - oldParent = this.parentNode, - oldSibling = this.nextSibling, - oldCSS = this.style.cssText, - bbox; - - _docElement.appendChild(svg); - - svg.appendChild(this); - this.style.display = "block"; - - if (swapIfPossible) { - try { - bbox = this.getBBox(); - this._gsapBBox = this.getBBox; //store the original - - this.getBBox = _getBBoxHack; - } catch (e) {} - } else if (this._gsapBBox) { - bbox = this._gsapBBox(); - } - - if (oldParent) { - if (oldSibling) { - oldParent.insertBefore(this, oldSibling); - } else { - oldParent.appendChild(this); - } - } - - _docElement.removeChild(svg); - - this.style.cssText = oldCSS; - return bbox; -}, - _getAttributeFallbacks = function _getAttributeFallbacks(target, attributesArray) { - var i = attributesArray.length; - - while (i--) { - if (target.hasAttribute(attributesArray[i])) { - return target.getAttribute(attributesArray[i]); - } - } -}, - _getBBox = function _getBBox(target) { - var bounds; - - try { - bounds = target.getBBox(); //Firefox throws errors if you try calling getBBox() on an SVG element that's not rendered (like in a or ). https://bugzilla.mozilla.org/show_bug.cgi?id=612118 - } catch (error) { - bounds = _getBBoxHack.call(target, true); - } - - bounds && (bounds.width || bounds.height) || target.getBBox === _getBBoxHack || (bounds = _getBBoxHack.call(target, true)); //some browsers (like Firefox) misreport the bounds if the element has zero width and height (it just assumes it's at x:0, y:0), thus we need to manually grab the position in that case. - - return bounds && !bounds.width && !bounds.x && !bounds.y ? { - x: +_getAttributeFallbacks(target, ["x", "cx", "x1"]) || 0, - y: +_getAttributeFallbacks(target, ["y", "cy", "y1"]) || 0, - width: 0, - height: 0 - } : bounds; -}, - _isSVG = function _isSVG(e) { - return !!(e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e)); -}, - //reports if the element is an SVG on which getBBox() actually works -_removeProperty = function _removeProperty(target, property) { - if (property) { - var style = target.style; - - if (property in _transformProps && property !== _transformOriginProp) { - property = _transformProp; - } - - if (style.removeProperty) { - if (property.substr(0, 2) === "ms" || property.substr(0, 6) === "webkit") { - //Microsoft and some Webkit browsers don't conform to the standard of capitalizing the first prefix character, so we adjust so that when we prefix the caps with a dash, it's correct (otherwise it'd be "ms-transform" instead of "-ms-transform" for IE9, for example) - property = "-" + property; - } - - style.removeProperty(property.replace(_capsExp, "-$1").toLowerCase()); - } else { - //note: old versions of IE use "removeAttribute()" instead of "removeProperty()" - style.removeAttribute(property); - } - } -}, - _addNonTweeningPT = function _addNonTweeningPT(plugin, target, property, beginning, end, onlySetAtEnd) { - var pt = new PropTween(plugin._pt, target, property, 0, 1, onlySetAtEnd ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue); - plugin._pt = pt; - pt.b = beginning; - pt.e = end; - - plugin._props.push(property); - - return pt; -}, - _nonConvertibleUnits = { - deg: 1, - rad: 1, - turn: 1 -}, - //takes a single value like 20px and converts it to the unit specified, like "%", returning only the numeric amount. -_convertToUnit = function _convertToUnit(target, property, value, unit) { - var curValue = parseFloat(value) || 0, - curUnit = (value + "").trim().substr((curValue + "").length) || "px", - // some browsers leave extra whitespace at the beginning of CSS variables, hence the need to trim() - style = _tempDiv.style, - horizontal = _horizontalExp.test(property), - isRootSVG = target.tagName.toLowerCase() === "svg", - measureProperty = (isRootSVG ? "client" : "offset") + (horizontal ? "Width" : "Height"), - amount = 100, - toPixels = unit === "px", - toPercent = unit === "%", - px, - parent, - cache, - isSVG; - - if (unit === curUnit || !curValue || _nonConvertibleUnits[unit] || _nonConvertibleUnits[curUnit]) { - return curValue; - } - - curUnit !== "px" && !toPixels && (curValue = _convertToUnit(target, property, value, "px")); - isSVG = target.getCTM && _isSVG(target); - - if ((toPercent || curUnit === "%") && (_transformProps[property] || ~property.indexOf("adius"))) { - px = isSVG ? target.getBBox()[horizontal ? "width" : "height"] : target[measureProperty]; - return _round(toPercent ? curValue / px * amount : curValue / 100 * px); - } - - style[horizontal ? "width" : "height"] = amount + (toPixels ? curUnit : unit); - parent = ~property.indexOf("adius") || unit === "em" && target.appendChild && !isRootSVG ? target : target.parentNode; - - if (isSVG) { - parent = (target.ownerSVGElement || {}).parentNode; - } - - if (!parent || parent === _doc || !parent.appendChild) { - parent = _doc.body; - } - - cache = parent._gsap; - - if (cache && toPercent && cache.width && horizontal && cache.time === _ticker.time) { - return _round(curValue / cache.width * amount); - } else { - (toPercent || curUnit === "%") && (style.position = _getComputedProperty(target, "position")); - parent === target && (style.position = "static"); // like for borderRadius, if it's a % we must have it relative to the target itself but that may not have position: relative or position: absolute in which case it'd go up the chain until it finds its offsetParent (bad). position: static protects against that. - - parent.appendChild(_tempDiv); - px = _tempDiv[measureProperty]; - parent.removeChild(_tempDiv); - style.position = "absolute"; - - if (horizontal && toPercent) { - cache = _getCache(parent); - cache.time = _ticker.time; - cache.width = parent[measureProperty]; - } - } - - return _round(toPixels ? px * curValue / amount : px && curValue ? amount / px * curValue : 0); -}, - _get = function _get(target, property, unit, uncache) { - var value; - _pluginInitted || _initCore(); - - if (property in _propertyAliases && property !== "transform") { - property = _propertyAliases[property]; - - if (~property.indexOf(",")) { - property = property.split(",")[0]; - } - } - - if (_transformProps[property] && property !== "transform") { - value = _parseTransform(target, uncache); - value = property !== "transformOrigin" ? value[property] : value.svg ? value.origin : _firstTwoOnly(_getComputedProperty(target, _transformOriginProp)) + " " + value.zOrigin + "px"; - } else { - value = target.style[property]; - - if (!value || value === "auto" || uncache || ~(value + "").indexOf("calc(")) { - value = _specialProps[property] && _specialProps[property](target, property, unit) || _getComputedProperty(target, property) || _getProperty(target, property) || (property === "opacity" ? 1 : 0); // note: some browsers, like Firefox, don't report borderRadius correctly! Instead, it only reports every corner like borderTopLeftRadius - } - } - - return unit && !~(value + "").trim().indexOf(" ") ? _convertToUnit(target, property, value, unit) + unit : value; -}, - _tweenComplexCSSString = function _tweenComplexCSSString(target, prop, start, end) { - //note: we call _tweenComplexCSSString.call(pluginInstance...) to ensure that it's scoped properly. We may call it from within a plugin too, thus "this" would refer to the plugin. - if (!start || start === "none") { - // some browsers like Safari actually PREFER the prefixed property and mis-report the unprefixed value like clipPath (BUG). In other words, even though clipPath exists in the style ("clipPath" in target.style) and it's set in the CSS properly (along with -webkit-clip-path), Safari reports clipPath as "none" whereas WebkitClipPath reports accurately like "ellipse(100% 0% at 50% 0%)", so in this case we must SWITCH to using the prefixed property instead. See https://greensock.com/forums/topic/18310-clippath-doesnt-work-on-ios/ - var p = _checkPropPrefix(prop, target, 1), - s = p && _getComputedProperty(target, p, 1); - - if (s && s !== start) { - prop = p; - start = s; - } else if (prop === "borderColor") { - start = _getComputedProperty(target, "borderTopColor"); // Firefox bug: always reports "borderColor" as "", so we must fall back to borderTopColor. See https://greensock.com/forums/topic/24583-how-to-return-colors-that-i-had-after-reverse/ - } - } - - var pt = new PropTween(this._pt, target.style, prop, 0, 1, _renderComplexString), - index = 0, - matchIndex = 0, - a, - result, - startValues, - startNum, - color, - startValue, - endValue, - endNum, - chunk, - endUnit, - startUnit, - relative, - endValues; - pt.b = start; - pt.e = end; - start += ""; //ensure values are strings - - end += ""; - - if (end === "auto") { - target.style[prop] = end; - end = _getComputedProperty(target, prop) || end; - target.style[prop] = start; - } - - a = [start, end]; - - _colorStringFilter(a); //pass an array with the starting and ending values and let the filter do whatever it needs to the values. If colors are found, it returns true and then we must match where the color shows up order-wise because for things like boxShadow, sometimes the browser provides the computed values with the color FIRST, but the user provides it with the color LAST, so flip them if necessary. Same for drop-shadow(). - - - start = a[0]; - end = a[1]; - startValues = start.match(_numWithUnitExp) || []; - endValues = end.match(_numWithUnitExp) || []; - - if (endValues.length) { - while (result = _numWithUnitExp.exec(end)) { - endValue = result[0]; - chunk = end.substring(index, result.index); - - if (color) { - color = (color + 1) % 5; - } else if (chunk.substr(-5) === "rgba(" || chunk.substr(-5) === "hsla(") { - color = 1; - } - - if (endValue !== (startValue = startValues[matchIndex++] || "")) { - startNum = parseFloat(startValue) || 0; - startUnit = startValue.substr((startNum + "").length); - relative = endValue.charAt(1) === "=" ? +(endValue.charAt(0) + "1") : 0; - - if (relative) { - endValue = endValue.substr(2); - } - - endNum = parseFloat(endValue); - endUnit = endValue.substr((endNum + "").length); - index = _numWithUnitExp.lastIndex - endUnit.length; - - if (!endUnit) { - //if something like "perspective:300" is passed in and we must add a unit to the end - endUnit = endUnit || _config.units[prop] || startUnit; - - if (index === end.length) { - end += endUnit; - pt.e += endUnit; - } - } - - if (startUnit !== endUnit) { - startNum = _convertToUnit(target, prop, startValue, endUnit) || 0; - } //these nested PropTweens are handled in a special way - we'll never actually call a render or setter method on them. We'll just loop through them in the parent complex string PropTween's render method. - - - pt._pt = { - _next: pt._pt, - p: chunk || matchIndex === 1 ? chunk : ",", - //note: SVG spec allows omission of comma/space when a negative sign is wedged between two numbers, like 2.5-5.3 instead of 2.5,-5.3 but when tweening, the negative value may switch to positive, so we insert the comma just in case. - s: startNum, - c: relative ? relative * endNum : endNum - startNum, - m: color && color < 4 || prop === "zIndex" ? Math.round : 0 - }; - } - } - - pt.c = index < end.length ? end.substring(index, end.length) : ""; //we use the "c" of the PropTween to store the final part of the string (after the last number) - } else { - pt.r = prop === "display" && end === "none" ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue; - } - - _relExp.test(end) && (pt.e = 0); //if the end string contains relative values or dynamic random(...) values, delete the end it so that on the final render we don't actually set it to the string with += or -= characters (forces it to use the calculated value). - - this._pt = pt; //start the linked list with this new PropTween. Remember, we call _tweenComplexCSSString.call(pluginInstance...) to ensure that it's scoped properly. We may call it from within another plugin too, thus "this" would refer to the plugin. - - return pt; -}, - _keywordToPercent = { - top: "0%", - bottom: "100%", - left: "0%", - right: "100%", - center: "50%" -}, - _convertKeywordsToPercentages = function _convertKeywordsToPercentages(value) { - var split = value.split(" "), - x = split[0], - y = split[1] || "50%"; - - if (x === "top" || x === "bottom" || y === "left" || y === "right") { - //the user provided them in the wrong order, so flip them - value = x; - x = y; - y = value; - } - - split[0] = _keywordToPercent[x] || x; - split[1] = _keywordToPercent[y] || y; - return split.join(" "); -}, - _renderClearProps = function _renderClearProps(ratio, data) { - if (data.tween && data.tween._time === data.tween._dur) { - var target = data.t, - style = target.style, - props = data.u, - cache = target._gsap, - prop, - clearTransforms, - i; - - if (props === "all" || props === true) { - style.cssText = ""; - clearTransforms = 1; - } else { - props = props.split(","); - i = props.length; - - while (--i > -1) { - prop = props[i]; - - if (_transformProps[prop]) { - clearTransforms = 1; - prop = prop === "transformOrigin" ? _transformOriginProp : _transformProp; - } - - _removeProperty(target, prop); - } - } - - if (clearTransforms) { - _removeProperty(target, _transformProp); - - if (cache) { - cache.svg && target.removeAttribute("transform"); - - _parseTransform(target, 1); // force all the cached values back to "normal"/identity, otherwise if there's another tween that's already set to render transforms on this element, it could display the wrong values. - - - cache.uncache = 1; - } - } - } -}, - // note: specialProps should return 1 if (and only if) they have a non-zero priority. It indicates we need to sort the linked list. -_specialProps = { - clearProps: function clearProps(plugin, target, property, endValue, tween) { - if (tween.data !== "isFromStart") { - var pt = plugin._pt = new PropTween(plugin._pt, target, property, 0, 0, _renderClearProps); - pt.u = endValue; - pt.pr = -10; - pt.tween = tween; - - plugin._props.push(property); - - return 1; - } - } - /* className feature (about 0.4kb gzipped). - , className(plugin, target, property, endValue, tween) { - let _renderClassName = (ratio, data) => { - data.css.render(ratio, data.css); - if (!ratio || ratio === 1) { - let inline = data.rmv, - target = data.t, - p; - target.setAttribute("class", ratio ? data.e : data.b); - for (p in inline) { - _removeProperty(target, p); - } - } - }, - _getAllStyles = (target) => { - let styles = {}, - computed = getComputedStyle(target), - p; - for (p in computed) { - if (isNaN(p) && p !== "cssText" && p !== "length") { - styles[p] = computed[p]; - } - } - _setDefaults(styles, _parseTransform(target, 1)); - return styles; - }, - startClassList = target.getAttribute("class"), - style = target.style, - cssText = style.cssText, - cache = target._gsap, - classPT = cache.classPT, - inlineToRemoveAtEnd = {}, - data = {t:target, plugin:plugin, rmv:inlineToRemoveAtEnd, b:startClassList, e:(endValue.charAt(1) !== "=") ? endValue : startClassList.replace(new RegExp("(?:\\s|^)" + endValue.substr(2) + "(?![\\w-])"), "") + ((endValue.charAt(0) === "+") ? " " + endValue.substr(2) : "")}, - changingVars = {}, - startVars = _getAllStyles(target), - transformRelated = /(transform|perspective)/i, - endVars, p; - if (classPT) { - classPT.r(1, classPT.d); - _removeLinkedListItem(classPT.d.plugin, classPT, "_pt"); - } - target.setAttribute("class", data.e); - endVars = _getAllStyles(target, true); - target.setAttribute("class", startClassList); - for (p in endVars) { - if (endVars[p] !== startVars[p] && !transformRelated.test(p)) { - changingVars[p] = endVars[p]; - if (!style[p] && style[p] !== "0") { - inlineToRemoveAtEnd[p] = 1; - } - } - } - cache.classPT = plugin._pt = new PropTween(plugin._pt, target, "className", 0, 0, _renderClassName, data, 0, -11); - if (style.cssText !== cssText) { //only apply if things change. Otherwise, in cases like a background-image that's pulled dynamically, it could cause a refresh. See https://greensock.com/forums/topic/20368-possible-gsap-bug-switching-classnames-in-chrome/. - style.cssText = cssText; //we recorded cssText before we swapped classes and ran _getAllStyles() because in cases when a className tween is overwritten, we remove all the related tweening properties from that class change (otherwise class-specific stuff can't override properties we've directly set on the target's style object due to specificity). - } - _parseTransform(target, true); //to clear the caching of transforms - data.css = new gsap.plugins.css(); - data.css.init(target, changingVars, tween); - plugin._props.push(...data.css._props); - return 1; - } - */ - -}, - -/* - * -------------------------------------------------------------------------------------- - * TRANSFORMS - * -------------------------------------------------------------------------------------- - */ -_identity2DMatrix = [1, 0, 0, 1, 0, 0], - _rotationalProperties = {}, - _isNullTransform = function _isNullTransform(value) { - return value === "matrix(1, 0, 0, 1, 0, 0)" || value === "none" || !value; -}, - _getComputedTransformMatrixAsArray = function _getComputedTransformMatrixAsArray(target) { - var matrixString = _getComputedProperty(target, _transformProp); - - return _isNullTransform(matrixString) ? _identity2DMatrix : matrixString.substr(7).match(_numExp).map(_round); -}, - _getMatrix = function _getMatrix(target, force2D) { - var cache = target._gsap || _getCache(target), - style = target.style, - matrix = _getComputedTransformMatrixAsArray(target), - parent, - nextSibling, - temp, - addedToDOM; - - if (cache.svg && target.getAttribute("transform")) { - temp = target.transform.baseVal.consolidate().matrix; //ensures that even complex values like "translate(50,60) rotate(135,0,0)" are parsed because it mashes it into a matrix. - - matrix = [temp.a, temp.b, temp.c, temp.d, temp.e, temp.f]; - return matrix.join(",") === "1,0,0,1,0,0" ? _identity2DMatrix : matrix; - } else if (matrix === _identity2DMatrix && !target.offsetParent && target !== _docElement && !cache.svg) { - //note: if offsetParent is null, that means the element isn't in the normal document flow, like if it has display:none or one of its ancestors has display:none). Firefox returns null for getComputedStyle() if the element is in an iframe that has display:none. https://bugzilla.mozilla.org/show_bug.cgi?id=548397 - //browsers don't report transforms accurately unless the element is in the DOM and has a display value that's not "none". Firefox and Microsoft browsers have a partial bug where they'll report transforms even if display:none BUT not any percentage-based values like translate(-50%, 8px) will be reported as if it's translate(0, 8px). - temp = style.display; - style.display = "block"; - parent = target.parentNode; - - if (!parent || !target.offsetParent) { - // note: in 3.3.0 we switched target.offsetParent to _doc.body.contains(target) to avoid [sometimes unnecessary] MutationObserver calls but that wasn't adequate because there are edge cases where nested position: fixed elements need to get reparented to accurately sense transforms. See https://github.com/greensock/GSAP/issues/388 and https://github.com/greensock/GSAP/issues/375 - addedToDOM = 1; //flag - - nextSibling = target.nextSibling; - - _docElement.appendChild(target); //we must add it to the DOM in order to get values properly - - } - - matrix = _getComputedTransformMatrixAsArray(target); - temp ? style.display = temp : _removeProperty(target, "display"); - - if (addedToDOM) { - nextSibling ? parent.insertBefore(target, nextSibling) : parent ? parent.appendChild(target) : _docElement.removeChild(target); - } - } - - return force2D && matrix.length > 6 ? [matrix[0], matrix[1], matrix[4], matrix[5], matrix[12], matrix[13]] : matrix; -}, - _applySVGOrigin = function _applySVGOrigin(target, origin, originIsAbsolute, smooth, matrixArray, pluginToAddPropTweensTo) { - var cache = target._gsap, - matrix = matrixArray || _getMatrix(target, true), - xOriginOld = cache.xOrigin || 0, - yOriginOld = cache.yOrigin || 0, - xOffsetOld = cache.xOffset || 0, - yOffsetOld = cache.yOffset || 0, - a = matrix[0], - b = matrix[1], - c = matrix[2], - d = matrix[3], - tx = matrix[4], - ty = matrix[5], - originSplit = origin.split(" "), - xOrigin = parseFloat(originSplit[0]) || 0, - yOrigin = parseFloat(originSplit[1]) || 0, - bounds, - determinant, - x, - y; - - if (!originIsAbsolute) { - bounds = _getBBox(target); - xOrigin = bounds.x + (~originSplit[0].indexOf("%") ? xOrigin / 100 * bounds.width : xOrigin); - yOrigin = bounds.y + (~(originSplit[1] || originSplit[0]).indexOf("%") ? yOrigin / 100 * bounds.height : yOrigin); - } else if (matrix !== _identity2DMatrix && (determinant = a * d - b * c)) { - //if it's zero (like if scaleX and scaleY are zero), skip it to avoid errors with dividing by zero. - x = xOrigin * (d / determinant) + yOrigin * (-c / determinant) + (c * ty - d * tx) / determinant; - y = xOrigin * (-b / determinant) + yOrigin * (a / determinant) - (a * ty - b * tx) / determinant; - xOrigin = x; - yOrigin = y; - } - - if (smooth || smooth !== false && cache.smooth) { - tx = xOrigin - xOriginOld; - ty = yOrigin - yOriginOld; - cache.xOffset = xOffsetOld + (tx * a + ty * c) - tx; - cache.yOffset = yOffsetOld + (tx * b + ty * d) - ty; - } else { - cache.xOffset = cache.yOffset = 0; - } - - cache.xOrigin = xOrigin; - cache.yOrigin = yOrigin; - cache.smooth = !!smooth; - cache.origin = origin; - cache.originIsAbsolute = !!originIsAbsolute; - target.style[_transformOriginProp] = "0px 0px"; //otherwise, if someone sets an origin via CSS, it will likely interfere with the SVG transform attribute ones (because remember, we're baking the origin into the matrix() value). - - if (pluginToAddPropTweensTo) { - _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOrigin", xOriginOld, xOrigin); - - _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOrigin", yOriginOld, yOrigin); - - _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOffset", xOffsetOld, cache.xOffset); - - _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOffset", yOffsetOld, cache.yOffset); - } - - target.setAttribute("data-svg-origin", xOrigin + " " + yOrigin); -}, - _parseTransform = function _parseTransform(target, uncache) { - var cache = target._gsap || new GSCache(target); - - if ("x" in cache && !uncache && !cache.uncache) { - return cache; - } - - var style = target.style, - invertedScaleX = cache.scaleX < 0, - px = "px", - deg = "deg", - origin = _getComputedProperty(target, _transformOriginProp) || "0", - x, - y, - z, - scaleX, - scaleY, - rotation, - rotationX, - rotationY, - skewX, - skewY, - perspective, - xOrigin, - yOrigin, - matrix, - angle, - cos, - sin, - a, - b, - c, - d, - a12, - a22, - t1, - t2, - t3, - a13, - a23, - a33, - a42, - a43, - a32; - x = y = z = rotation = rotationX = rotationY = skewX = skewY = perspective = 0; - scaleX = scaleY = 1; - cache.svg = !!(target.getCTM && _isSVG(target)); - matrix = _getMatrix(target, cache.svg); - - if (cache.svg) { - t1 = (!cache.uncache || origin === "0px 0px") && !uncache && target.getAttribute("data-svg-origin"); // if origin is 0,0 and cache.uncache is true, let the recorded data-svg-origin stay. Otherwise, whenever we set cache.uncache to true, we'd need to set element.style.transformOrigin = (cache.xOrigin - bbox.x) + "px " + (cache.yOrigin - bbox.y) + "px". Remember, to work around browser inconsistencies we always force SVG elements' transformOrigin to 0,0 and offset the translation accordingly. - - _applySVGOrigin(target, t1 || origin, !!t1 || cache.originIsAbsolute, cache.smooth !== false, matrix); - } - - xOrigin = cache.xOrigin || 0; - yOrigin = cache.yOrigin || 0; - - if (matrix !== _identity2DMatrix) { - a = matrix[0]; //a11 - - b = matrix[1]; //a21 - - c = matrix[2]; //a31 - - d = matrix[3]; //a41 - - x = a12 = matrix[4]; - y = a22 = matrix[5]; //2D matrix - - if (matrix.length === 6) { - scaleX = Math.sqrt(a * a + b * b); - scaleY = Math.sqrt(d * d + c * c); - rotation = a || b ? _atan2(b, a) * _RAD2DEG : 0; //note: if scaleX is 0, we cannot accurately measure rotation. Same for skewX with a scaleY of 0. Therefore, we default to the previously recorded value (or zero if that doesn't exist). - - skewX = c || d ? _atan2(c, d) * _RAD2DEG + rotation : 0; - skewX && (scaleY *= Math.abs(Math.cos(skewX * _DEG2RAD))); - - if (cache.svg) { - x -= xOrigin - (xOrigin * a + yOrigin * c); - y -= yOrigin - (xOrigin * b + yOrigin * d); - } //3D matrix - - } else { - a32 = matrix[6]; - a42 = matrix[7]; - a13 = matrix[8]; - a23 = matrix[9]; - a33 = matrix[10]; - a43 = matrix[11]; - x = matrix[12]; - y = matrix[13]; - z = matrix[14]; - angle = _atan2(a32, a33); - rotationX = angle * _RAD2DEG; //rotationX - - if (angle) { - cos = Math.cos(-angle); - sin = Math.sin(-angle); - t1 = a12 * cos + a13 * sin; - t2 = a22 * cos + a23 * sin; - t3 = a32 * cos + a33 * sin; - a13 = a12 * -sin + a13 * cos; - a23 = a22 * -sin + a23 * cos; - a33 = a32 * -sin + a33 * cos; - a43 = a42 * -sin + a43 * cos; - a12 = t1; - a22 = t2; - a32 = t3; - } //rotationY - - - angle = _atan2(-c, a33); - rotationY = angle * _RAD2DEG; - - if (angle) { - cos = Math.cos(-angle); - sin = Math.sin(-angle); - t1 = a * cos - a13 * sin; - t2 = b * cos - a23 * sin; - t3 = c * cos - a33 * sin; - a43 = d * sin + a43 * cos; - a = t1; - b = t2; - c = t3; - } //rotationZ - - - angle = _atan2(b, a); - rotation = angle * _RAD2DEG; - - if (angle) { - cos = Math.cos(angle); - sin = Math.sin(angle); - t1 = a * cos + b * sin; - t2 = a12 * cos + a22 * sin; - b = b * cos - a * sin; - a22 = a22 * cos - a12 * sin; - a = t1; - a12 = t2; - } - - if (rotationX && Math.abs(rotationX) + Math.abs(rotation) > 359.9) { - //when rotationY is set, it will often be parsed as 180 degrees different than it should be, and rotationX and rotation both being 180 (it looks the same), so we adjust for that here. - rotationX = rotation = 0; - rotationY = 180 - rotationY; - } - - scaleX = _round(Math.sqrt(a * a + b * b + c * c)); - scaleY = _round(Math.sqrt(a22 * a22 + a32 * a32)); - angle = _atan2(a12, a22); - skewX = Math.abs(angle) > 0.0002 ? angle * _RAD2DEG : 0; - perspective = a43 ? 1 / (a43 < 0 ? -a43 : a43) : 0; - } - - if (cache.svg) { - //sense if there are CSS transforms applied on an SVG element in which case we must overwrite them when rendering. The transform attribute is more reliable cross-browser, but we can't just remove the CSS ones because they may be applied in a CSS rule somewhere (not just inline). - t1 = target.getAttribute("transform"); - cache.forceCSS = target.setAttribute("transform", "") || !_isNullTransform(_getComputedProperty(target, _transformProp)); - t1 && target.setAttribute("transform", t1); - } - } - - if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) { - if (invertedScaleX) { - scaleX *= -1; - skewX += rotation <= 0 ? 180 : -180; - rotation += rotation <= 0 ? 180 : -180; - } else { - scaleY *= -1; - skewX += skewX <= 0 ? 180 : -180; - } - } - - cache.x = x - ((cache.xPercent = x && (cache.xPercent || (Math.round(target.offsetWidth / 2) === Math.round(-x) ? -50 : 0))) ? target.offsetWidth * cache.xPercent / 100 : 0) + px; - cache.y = y - ((cache.yPercent = y && (cache.yPercent || (Math.round(target.offsetHeight / 2) === Math.round(-y) ? -50 : 0))) ? target.offsetHeight * cache.yPercent / 100 : 0) + px; - cache.z = z + px; - cache.scaleX = _round(scaleX); - cache.scaleY = _round(scaleY); - cache.rotation = _round(rotation) + deg; - cache.rotationX = _round(rotationX) + deg; - cache.rotationY = _round(rotationY) + deg; - cache.skewX = skewX + deg; - cache.skewY = skewY + deg; - cache.transformPerspective = perspective + px; - - if (cache.zOrigin = parseFloat(origin.split(" ")[2]) || 0) { - style[_transformOriginProp] = _firstTwoOnly(origin); - } - - cache.xOffset = cache.yOffset = 0; - cache.force3D = _config.force3D; - cache.renderTransform = cache.svg ? _renderSVGTransforms : _supports3D ? _renderCSSTransforms : _renderNon3DTransforms; - cache.uncache = 0; - return cache; -}, - _firstTwoOnly = function _firstTwoOnly(value) { - return (value = value.split(" "))[0] + " " + value[1]; -}, - //for handling transformOrigin values, stripping out the 3rd dimension -_addPxTranslate = function _addPxTranslate(target, start, value) { - var unit = getUnit(start); - return _round(parseFloat(start) + parseFloat(_convertToUnit(target, "x", value + "px", unit))) + unit; -}, - _renderNon3DTransforms = function _renderNon3DTransforms(ratio, cache) { - cache.z = "0px"; - cache.rotationY = cache.rotationX = "0deg"; - cache.force3D = 0; - - _renderCSSTransforms(ratio, cache); -}, - _zeroDeg = "0deg", - _zeroPx = "0px", - _endParenthesis = ") ", - _renderCSSTransforms = function _renderCSSTransforms(ratio, cache) { - var _ref = cache || this, - xPercent = _ref.xPercent, - yPercent = _ref.yPercent, - x = _ref.x, - y = _ref.y, - z = _ref.z, - rotation = _ref.rotation, - rotationY = _ref.rotationY, - rotationX = _ref.rotationX, - skewX = _ref.skewX, - skewY = _ref.skewY, - scaleX = _ref.scaleX, - scaleY = _ref.scaleY, - transformPerspective = _ref.transformPerspective, - force3D = _ref.force3D, - target = _ref.target, - zOrigin = _ref.zOrigin, - transforms = "", - use3D = force3D === "auto" && ratio && ratio !== 1 || force3D === true; // Safari has a bug that causes it not to render 3D transform-origin values properly, so we force the z origin to 0, record it in the cache, and then do the math here to offset the translate values accordingly (basically do the 3D transform-origin part manually) - - - if (zOrigin && (rotationX !== _zeroDeg || rotationY !== _zeroDeg)) { - var angle = parseFloat(rotationY) * _DEG2RAD, - a13 = Math.sin(angle), - a33 = Math.cos(angle), - cos; - - angle = parseFloat(rotationX) * _DEG2RAD; - cos = Math.cos(angle); - x = _addPxTranslate(target, x, a13 * cos * -zOrigin); - y = _addPxTranslate(target, y, -Math.sin(angle) * -zOrigin); - z = _addPxTranslate(target, z, a33 * cos * -zOrigin + zOrigin); - } - - if (transformPerspective !== _zeroPx) { - transforms += "perspective(" + transformPerspective + _endParenthesis; - } - - if (xPercent || yPercent) { - transforms += "translate(" + xPercent + "%, " + yPercent + "%) "; - } - - if (use3D || x !== _zeroPx || y !== _zeroPx || z !== _zeroPx) { - transforms += z !== _zeroPx || use3D ? "translate3d(" + x + ", " + y + ", " + z + ") " : "translate(" + x + ", " + y + _endParenthesis; - } - - if (rotation !== _zeroDeg) { - transforms += "rotate(" + rotation + _endParenthesis; - } - - if (rotationY !== _zeroDeg) { - transforms += "rotateY(" + rotationY + _endParenthesis; - } - - if (rotationX !== _zeroDeg) { - transforms += "rotateX(" + rotationX + _endParenthesis; - } - - if (skewX !== _zeroDeg || skewY !== _zeroDeg) { - transforms += "skew(" + skewX + ", " + skewY + _endParenthesis; - } - - if (scaleX !== 1 || scaleY !== 1) { - transforms += "scale(" + scaleX + ", " + scaleY + _endParenthesis; - } - - target.style[_transformProp] = transforms || "translate(0, 0)"; -}, - _renderSVGTransforms = function _renderSVGTransforms(ratio, cache) { - var _ref2 = cache || this, - xPercent = _ref2.xPercent, - yPercent = _ref2.yPercent, - x = _ref2.x, - y = _ref2.y, - rotation = _ref2.rotation, - skewX = _ref2.skewX, - skewY = _ref2.skewY, - scaleX = _ref2.scaleX, - scaleY = _ref2.scaleY, - target = _ref2.target, - xOrigin = _ref2.xOrigin, - yOrigin = _ref2.yOrigin, - xOffset = _ref2.xOffset, - yOffset = _ref2.yOffset, - forceCSS = _ref2.forceCSS, - tx = parseFloat(x), - ty = parseFloat(y), - a11, - a21, - a12, - a22, - temp; - - rotation = parseFloat(rotation); - skewX = parseFloat(skewX); - skewY = parseFloat(skewY); - - if (skewY) { - //for performance reasons, we combine all skewing into the skewX and rotation values. Remember, a skewY of 10 degrees looks the same as a rotation of 10 degrees plus a skewX of 10 degrees. - skewY = parseFloat(skewY); - skewX += skewY; - rotation += skewY; - } - - if (rotation || skewX) { - rotation *= _DEG2RAD; - skewX *= _DEG2RAD; - a11 = Math.cos(rotation) * scaleX; - a21 = Math.sin(rotation) * scaleX; - a12 = Math.sin(rotation - skewX) * -scaleY; - a22 = Math.cos(rotation - skewX) * scaleY; - - if (skewX) { - skewY *= _DEG2RAD; - temp = Math.tan(skewX - skewY); - temp = Math.sqrt(1 + temp * temp); - a12 *= temp; - a22 *= temp; - - if (skewY) { - temp = Math.tan(skewY); - temp = Math.sqrt(1 + temp * temp); - a11 *= temp; - a21 *= temp; - } - } - - a11 = _round(a11); - a21 = _round(a21); - a12 = _round(a12); - a22 = _round(a22); - } else { - a11 = scaleX; - a22 = scaleY; - a21 = a12 = 0; - } - - if (tx && !~(x + "").indexOf("px") || ty && !~(y + "").indexOf("px")) { - tx = _convertToUnit(target, "x", x, "px"); - ty = _convertToUnit(target, "y", y, "px"); - } - - if (xOrigin || yOrigin || xOffset || yOffset) { - tx = _round(tx + xOrigin - (xOrigin * a11 + yOrigin * a12) + xOffset); - ty = _round(ty + yOrigin - (xOrigin * a21 + yOrigin * a22) + yOffset); - } - - if (xPercent || yPercent) { - //The SVG spec doesn't support percentage-based translation in the "transform" attribute, so we merge it into the translation to simulate it. - temp = target.getBBox(); - tx = _round(tx + xPercent / 100 * temp.width); - ty = _round(ty + yPercent / 100 * temp.height); - } - - temp = "matrix(" + a11 + "," + a21 + "," + a12 + "," + a22 + "," + tx + "," + ty + ")"; - target.setAttribute("transform", temp); - forceCSS && (target.style[_transformProp] = temp); //some browsers prioritize CSS transforms over the transform attribute. When we sense that the user has CSS transforms applied, we must overwrite them this way (otherwise some browser simply won't render the transform attribute changes!) -}, - _addRotationalPropTween = function _addRotationalPropTween(plugin, target, property, startNum, endValue, relative) { - var cap = 360, - isString = _isString(endValue), - endNum = parseFloat(endValue) * (isString && ~endValue.indexOf("rad") ? _RAD2DEG : 1), - change = relative ? endNum * relative : endNum - startNum, - finalValue = startNum + change + "deg", - direction, - pt; - - if (isString) { - direction = endValue.split("_")[1]; - - if (direction === "short") { - change %= cap; - - if (change !== change % (cap / 2)) { - change += change < 0 ? cap : -cap; - } - } - - if (direction === "cw" && change < 0) { - change = (change + cap * _bigNum) % cap - ~~(change / cap) * cap; - } else if (direction === "ccw" && change > 0) { - change = (change - cap * _bigNum) % cap - ~~(change / cap) * cap; - } - } - - plugin._pt = pt = new PropTween(plugin._pt, target, property, startNum, change, _renderPropWithEnd); - pt.e = finalValue; - pt.u = "deg"; - - plugin._props.push(property); - - return pt; -}, - _assign = function _assign(target, source) { - // Internet Explorer doesn't have Object.assign(), so we recreate it here. - for (var p in source) { - target[p] = source[p]; - } - - return target; -}, - _addRawTransformPTs = function _addRawTransformPTs(plugin, transforms, target) { - //for handling cases where someone passes in a whole transform string, like transform: "scale(2, 3) rotate(20deg) translateY(30em)" - var startCache = _assign({}, target._gsap), - exclude = "perspective,force3D,transformOrigin,svgOrigin", - style = target.style, - endCache, - p, - startValue, - endValue, - startNum, - endNum, - startUnit, - endUnit; - - if (startCache.svg) { - startValue = target.getAttribute("transform"); - target.setAttribute("transform", ""); - style[_transformProp] = transforms; - endCache = _parseTransform(target, 1); - - _removeProperty(target, _transformProp); - - target.setAttribute("transform", startValue); - } else { - startValue = getComputedStyle(target)[_transformProp]; - style[_transformProp] = transforms; - endCache = _parseTransform(target, 1); - style[_transformProp] = startValue; - } - - for (p in _transformProps) { - startValue = startCache[p]; - endValue = endCache[p]; - - if (startValue !== endValue && exclude.indexOf(p) < 0) { - //tweening to no perspective gives very unintuitive results - just keep the same perspective in that case. - startUnit = getUnit(startValue); - endUnit = getUnit(endValue); - startNum = startUnit !== endUnit ? _convertToUnit(target, p, startValue, endUnit) : parseFloat(startValue); - endNum = parseFloat(endValue); - plugin._pt = new PropTween(plugin._pt, endCache, p, startNum, endNum - startNum, _renderCSSProp); - plugin._pt.u = endUnit || 0; - - plugin._props.push(p); - } - } - - _assign(endCache, startCache); -}; // handle splitting apart padding, margin, borderWidth, and borderRadius into their 4 components. Firefox, for example, won't report borderRadius correctly - it will only do borderTopLeftRadius and the other corners. We also want to handle paddingTop, marginLeft, borderRightWidth, etc. - - -_forEachName("padding,margin,Width,Radius", function (name, index) { - var t = "Top", - r = "Right", - b = "Bottom", - l = "Left", - props = (index < 3 ? [t, r, b, l] : [t + l, t + r, b + r, b + l]).map(function (side) { - return index < 2 ? name + side : "border" + side + name; - }); - - _specialProps[index > 1 ? "border" + name : name] = function (plugin, target, property, endValue, tween) { - var a, vars; - - if (arguments.length < 4) { - // getter, passed target, property, and unit (from _get()) - a = props.map(function (prop) { - return _get(plugin, prop, property); - }); - vars = a.join(" "); - return vars.split(a[0]).length === 5 ? a[0] : vars; - } - - a = (endValue + "").split(" "); - vars = {}; - props.forEach(function (prop, i) { - return vars[prop] = a[i] = a[i] || a[(i - 1) / 2 | 0]; - }); - plugin.init(target, vars, tween); - }; -}); - -export var CSSPlugin = { - name: "css", - register: _initCore, - targetTest: function targetTest(target) { - return target.style && target.nodeType; - }, - init: function init(target, vars, tween, index, targets) { - var props = this._props, - style = target.style, - startAt = tween.vars.startAt, - startValue, - endValue, - endNum, - startNum, - type, - specialProp, - p, - startUnit, - endUnit, - relative, - isTransformRelated, - transformPropTween, - cache, - smooth, - hasPriority; - _pluginInitted || _initCore(); - - for (p in vars) { - if (p === "autoRound") { - continue; - } - - endValue = vars[p]; - - if (_plugins[p] && _checkPlugin(p, vars, tween, index, target, targets)) { - // plugins - continue; - } - - type = typeof endValue; - specialProp = _specialProps[p]; - - if (type === "function") { - endValue = endValue.call(tween, index, target, targets); - type = typeof endValue; - } - - if (type === "string" && ~endValue.indexOf("random(")) { - endValue = _replaceRandom(endValue); - } - - if (specialProp) { - specialProp(this, target, p, endValue, tween) && (hasPriority = 1); - } else if (p.substr(0, 2) === "--") { - //CSS variable - startValue = (getComputedStyle(target).getPropertyValue(p) + "").trim(); - endValue += ""; - _colorExp.lastIndex = 0; - - if (!_colorExp.test(startValue)) { - // colors don't have units - startUnit = getUnit(startValue); - endUnit = getUnit(endValue); - } - - endUnit ? startUnit !== endUnit && (startValue = _convertToUnit(target, p, startValue, endUnit) + endUnit) : startUnit && (endValue += startUnit); - this.add(style, "setProperty", startValue, endValue, index, targets, 0, 0, p); - props.push(p); - } else if (type !== "undefined") { - if (startAt && p in startAt) { - // in case someone hard-codes a complex value as the start, like top: "calc(2vh / 2)". Without this, it'd use the computed value (always in px) - startValue = typeof startAt[p] === "function" ? startAt[p].call(tween, index, target, targets) : startAt[p]; - p in _config.units && !getUnit(startValue) && (startValue += _config.units[p]); // for cases when someone passes in a unitless value like {x: 100}; if we try setting translate(100, 0px) it won't work. - - (startValue + "").charAt(1) === "=" && (startValue = _get(target, p)); // can't work with relative values - } else { - startValue = _get(target, p); - } - - startNum = parseFloat(startValue); - relative = type === "string" && endValue.charAt(1) === "=" ? +(endValue.charAt(0) + "1") : 0; - relative && (endValue = endValue.substr(2)); - endNum = parseFloat(endValue); - - if (p in _propertyAliases) { - if (p === "autoAlpha") { - //special case where we control the visibility along with opacity. We still allow the opacity value to pass through and get tweened. - if (startNum === 1 && _get(target, "visibility") === "hidden" && endNum) { - //if visibility is initially set to "hidden", we should interpret that as intent to make opacity 0 (a convenience) - startNum = 0; - } - - _addNonTweeningPT(this, style, "visibility", startNum ? "inherit" : "hidden", endNum ? "inherit" : "hidden", !endNum); - } - - if (p !== "scale" && p !== "transform") { - p = _propertyAliases[p]; - ~p.indexOf(",") && (p = p.split(",")[0]); - } - } - - isTransformRelated = p in _transformProps; //--- TRANSFORM-RELATED --- - - if (isTransformRelated) { - if (!transformPropTween) { - cache = target._gsap; - cache.renderTransform && !vars.parseTransform || _parseTransform(target, vars.parseTransform); // if, for example, gsap.set(... {transform:"translateX(50vw)"}), the _get() call doesn't parse the transform, thus cache.renderTransform won't be set yet so force the parsing of the transform here. - - smooth = vars.smoothOrigin !== false && cache.smooth; - transformPropTween = this._pt = new PropTween(this._pt, style, _transformProp, 0, 1, cache.renderTransform, cache, 0, -1); //the first time through, create the rendering PropTween so that it runs LAST (in the linked list, we keep adding to the beginning) - - transformPropTween.dep = 1; //flag it as dependent so that if things get killed/overwritten and this is the only PropTween left, we can safely kill the whole tween. - } - - if (p === "scale") { - this._pt = new PropTween(this._pt, cache, "scaleY", cache.scaleY, (relative ? relative * endNum : endNum - cache.scaleY) || 0); - props.push("scaleY", p); - p += "X"; - } else if (p === "transformOrigin") { - endValue = _convertKeywordsToPercentages(endValue); //in case something like "left top" or "bottom right" is passed in. Convert to percentages. - - if (cache.svg) { - _applySVGOrigin(target, endValue, 0, smooth, 0, this); - } else { - endUnit = parseFloat(endValue.split(" ")[2]) || 0; //handle the zOrigin separately! - - endUnit !== cache.zOrigin && _addNonTweeningPT(this, cache, "zOrigin", cache.zOrigin, endUnit); - - _addNonTweeningPT(this, style, p, _firstTwoOnly(startValue), _firstTwoOnly(endValue)); - } - - continue; - } else if (p === "svgOrigin") { - _applySVGOrigin(target, endValue, 1, smooth, 0, this); - - continue; - } else if (p in _rotationalProperties) { - _addRotationalPropTween(this, cache, p, startNum, endValue, relative); - - continue; - } else if (p === "smoothOrigin") { - _addNonTweeningPT(this, cache, "smooth", cache.smooth, endValue); - - continue; - } else if (p === "force3D") { - cache[p] = endValue; - continue; - } else if (p === "transform") { - _addRawTransformPTs(this, endValue, target); - - continue; - } - } else if (!(p in style)) { - p = _checkPropPrefix(p) || p; - } - - if (isTransformRelated || (endNum || endNum === 0) && (startNum || startNum === 0) && !_complexExp.test(endValue) && p in style) { - startUnit = (startValue + "").substr((startNum + "").length); - endNum || (endNum = 0); // protect against NaN - - endUnit = getUnit(endValue) || (p in _config.units ? _config.units[p] : startUnit); - startUnit !== endUnit && (startNum = _convertToUnit(target, p, startValue, endUnit)); - this._pt = new PropTween(this._pt, isTransformRelated ? cache : style, p, startNum, relative ? relative * endNum : endNum - startNum, !isTransformRelated && (endUnit === "px" || p === "zIndex") && vars.autoRound !== false ? _renderRoundedCSSProp : _renderCSSProp); - this._pt.u = endUnit || 0; - - if (startUnit !== endUnit) { - //when the tween goes all the way back to the beginning, we need to revert it to the OLD/ORIGINAL value (with those units). We record that as a "b" (beginning) property and point to a render method that handles that. (performance optimization) - this._pt.b = startValue; - this._pt.r = _renderCSSPropWithBeginning; - } - } else if (!(p in style)) { - if (p in target) { - //maybe it's not a style - it could be a property added directly to an element in which case we'll try to animate that. - this.add(target, p, startValue || target[p], endValue, index, targets); - } else { - _missingPlugin(p, endValue); - - continue; - } - } else { - _tweenComplexCSSString.call(this, target, p, startValue, endValue); - } - - props.push(p); - } - } - - hasPriority && _sortPropTweensByPriority(this); - }, - get: _get, - aliases: _propertyAliases, - getSetter: function getSetter(target, property, plugin) { - //returns a setter function that accepts target, property, value and applies it accordingly. Remember, properties like "x" aren't as simple as target.style.property = value because they've got to be applied to a proxy object and then merged into a transform string in a renderer. - var p = _propertyAliases[property]; - p && p.indexOf(",") < 0 && (property = p); - return property in _transformProps && property !== _transformOriginProp && (target._gsap.x || _get(target, "x")) ? plugin && _recentSetterPlugin === plugin ? property === "scale" ? _setterScale : _setterTransform : (_recentSetterPlugin = plugin || {}) && (property === "scale" ? _setterScaleWithRender : _setterTransformWithRender) : target.style && !_isUndefined(target.style[property]) ? _setterCSSStyle : ~property.indexOf("-") ? _setterCSSProp : _getSetter(target, property); - }, - core: { - _removeProperty: _removeProperty, - _getMatrix: _getMatrix - } -}; -gsap.utils.checkPrefix = _checkPropPrefix; - -(function (positionAndScale, rotation, others, aliases) { - var all = _forEachName(positionAndScale + "," + rotation + "," + others, function (name) { - _transformProps[name] = 1; - }); - - _forEachName(rotation, function (name) { - _config.units[name] = "deg"; - _rotationalProperties[name] = 1; - }); - - _propertyAliases[all[13]] = positionAndScale + "," + rotation; - - _forEachName(aliases, function (name) { - var split = name.split(":"); - _propertyAliases[split[1]] = all[split[0]]; - }); -})("x,y,z,scale,scaleX,scaleY,xPercent,yPercent", "rotation,rotationX,rotationY,skewX,skewY", "transform,transformOrigin,svgOrigin,force3D,smoothOrigin,transformPerspective", "0:translateX,1:translateY,2:translateZ,8:rotate,8:rotationZ,8:rotateZ,9:rotateX,10:rotateY"); - -_forEachName("x,y,z,top,right,bottom,left,width,height,fontSize,padding,margin,perspective", function (name) { - _config.units[name] = "px"; -}); - -gsap.registerPlugin(CSSPlugin); -export { CSSPlugin as default, _getBBox, _createElement, _checkPropPrefix as checkPrefix }; \ No newline at end of file diff --git a/dev/libraries/gsap/esm/CSSRulePlugin.js b/dev/libraries/gsap/esm/CSSRulePlugin.js deleted file mode 100644 index 35e1e54..0000000 --- a/dev/libraries/gsap/esm/CSSRulePlugin.js +++ /dev/null @@ -1,134 +0,0 @@ -/*! - * CSSRulePlugin 3.7.1 - * https://greensock.com - * - * @license Copyright 2008-2021, GreenSock. All rights reserved. - * Subject to the terms at https://greensock.com/standard-license or for - * Club GreenSock members, the agreement issued with that membership. - * @author: Jack Doyle, jack@greensock.com -*/ - -/* eslint-disable */ -var gsap, - _coreInitted, - _win, - _doc, - CSSPlugin, - _windowExists = function _windowExists() { - return typeof window !== "undefined"; -}, - _getGSAP = function _getGSAP() { - return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap; -}, - _checkRegister = function _checkRegister() { - if (!_coreInitted) { - _initCore(); - - if (!CSSPlugin) { - console.warn("Please gsap.registerPlugin(CSSPlugin, CSSRulePlugin)"); - } - } - - return _coreInitted; -}, - _initCore = function _initCore(core) { - gsap = core || _getGSAP(); - - if (_windowExists()) { - _win = window; - _doc = document; - } - - if (gsap) { - CSSPlugin = gsap.plugins.css; - - if (CSSPlugin) { - _coreInitted = 1; - } - } -}; - -export var CSSRulePlugin = { - version: "3.7.1", - name: "cssRule", - init: function init(target, value, tween, index, targets) { - if (!_checkRegister() || typeof target.cssText === "undefined") { - return false; - } - - var div = target._gsProxy = target._gsProxy || _doc.createElement("div"); - - this.ss = target; - this.style = div.style; - div.style.cssText = target.cssText; - CSSPlugin.prototype.init.call(this, div, value, tween, index, targets); //we just offload all the work to the regular CSSPlugin and then copy the cssText back over to the rule in the render() method. This allows us to have all of the updates to CSSPlugin automatically flow through to CSSRulePlugin instead of having to maintain both - }, - render: function render(ratio, data) { - var pt = data._pt, - style = data.style, - ss = data.ss, - i; - - while (pt) { - pt.r(ratio, pt.d); - pt = pt._next; - } - - i = style.length; - - while (--i > -1) { - ss[style[i]] = style[style[i]]; - } - }, - getRule: function getRule(selector) { - _checkRegister(); - - var ruleProp = _doc.all ? "rules" : "cssRules", - styleSheets = _doc.styleSheets, - i = styleSheets.length, - pseudo = selector.charAt(0) === ":", - j, - curSS, - cs, - a; - selector = (pseudo ? "" : ",") + selector.split("::").join(":").toLowerCase() + ","; //note: old versions of IE report tag name selectors as upper case, so we just change everything to lowercase. - - if (pseudo) { - a = []; - } - - while (i--) { - //Firefox may throw insecure operation errors when css is loaded from other domains, so try/catch. - try { - curSS = styleSheets[i][ruleProp]; - - if (!curSS) { - continue; - } - - j = curSS.length; - } catch (e) { - console.warn(e); - continue; - } - - while (--j > -1) { - cs = curSS[j]; - - if (cs.selectorText && ("," + cs.selectorText.split("::").join(":").toLowerCase() + ",").indexOf(selector) !== -1) { - //note: IE adds an extra ":" to pseudo selectors, so .myClass:after becomes .myClass::after, so we need to strip the extra one out. - if (pseudo) { - a.push(cs.style); - } else { - return cs.style; - } - } - } - } - - return a; - }, - register: _initCore -}; -_getGSAP() && gsap.registerPlugin(CSSRulePlugin); -export { CSSRulePlugin as default }; \ No newline at end of file diff --git a/dev/libraries/gsap/esm/Draggable.js b/dev/libraries/gsap/esm/Draggable.js deleted file mode 100644 index cb819a5..0000000 --- a/dev/libraries/gsap/esm/Draggable.js +++ /dev/null @@ -1,2666 +0,0 @@ -function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } - -function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } - -/*! - * Draggable 3.7.1 - * https://greensock.com - * - * @license Copyright 2008-2021, GreenSock. All rights reserved. - * Subject to the terms at https://greensock.com/standard-license or for - * Club GreenSock members, the agreement issued with that membership. - * @author: Jack Doyle, jack@greensock.com - */ - -/* eslint-disable */ -import { getGlobalMatrix, Matrix2D } from "./utils/matrix.js"; - -var gsap, - _win, - _doc, - _docElement, - _body, - _tempDiv, - _placeholderDiv, - _coreInitted, - _checkPrefix, - _toArray, - _supportsPassive, - _isTouchDevice, - _touchEventLookup, - _dragCount, - _isMultiTouching, - _isAndroid, - InertiaPlugin, - _defaultCursor, - _supportsPointer, - _windowExists = function _windowExists() { - return typeof window !== "undefined"; -}, - _getGSAP = function _getGSAP() { - return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap; -}, - _isFunction = function _isFunction(value) { - return typeof value === "function"; -}, - _isObject = function _isObject(value) { - return typeof value === "object"; -}, - _isUndefined = function _isUndefined(value) { - return typeof value === "undefined"; -}, - _emptyFunc = function _emptyFunc() { - return false; -}, - _transformProp = "transform", - _transformOriginProp = "transformOrigin", - _round = function _round(value) { - return Math.round(value * 10000) / 10000; -}, - _isArray = Array.isArray, - _createElement = function _createElement(type, ns) { - var e = _doc.createElementNS ? _doc.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc.createElement(type); //some servers swap in https for http in the namespace which can break things, making "style" inaccessible. - - return e.style ? e : _doc.createElement(type); //some environments won't allow access to the element's style when created with a namespace in which case we default to the standard createElement() to work around the issue. Also note that when GSAP is embedded directly inside an SVG file, createElement() won't allow access to the style object in Firefox (see https://greensock.com/forums/topic/20215-problem-using-tweenmax-in-standalone-self-containing-svg-file-err-cannot-set-property-csstext-of-undefined/). -}, - _RAD2DEG = 180 / Math.PI, - _bigNum = 1e20, - _identityMatrix = new Matrix2D(), - _getTime = Date.now || function () { - return new Date().getTime(); -}, - _renderQueue = [], - _lookup = {}, - //when a Draggable is created, the target gets a unique _gsDragID property that allows gets associated with the Draggable instance for quick lookups in Draggable.get(). This avoids circular references that could cause gc problems. -_lookupCount = 0, - _clickableTagExp = /^(?:a|input|textarea|button|select)$/i, - _lastDragTime = 0, - _temp1 = {}, - // a simple object we reuse and populate (usually x/y properties) to conserve memory and improve performance. -_windowProxy = {}, - //memory/performance optimization - we reuse this object during autoScroll to store window-related bounds/offsets. -_copy = function _copy(obj, factor) { - var copy = {}, - p; - - for (p in obj) { - copy[p] = factor ? obj[p] * factor : obj[p]; - } - - return copy; -}, - _extend = function _extend(obj, defaults) { - for (var p in defaults) { - if (!(p in obj)) { - obj[p] = defaults[p]; - } - } - - return obj; -}, - _setTouchActionForAllDescendants = function _setTouchActionForAllDescendants(elements, value) { - var i = elements.length, - children; - - while (i--) { - value ? elements[i].style.touchAction = value : elements[i].style.removeProperty("touch-action"); - children = elements[i].children; - children && children.length && _setTouchActionForAllDescendants(children, value); - } -}, - _renderQueueTick = function _renderQueueTick() { - return _renderQueue.forEach(function (func) { - return func(); - }); -}, - _addToRenderQueue = function _addToRenderQueue(func) { - _renderQueue.push(func); - - if (_renderQueue.length === 1) { - gsap.ticker.add(_renderQueueTick); - } -}, - _renderQueueTimeout = function _renderQueueTimeout() { - return !_renderQueue.length && gsap.ticker.remove(_renderQueueTick); -}, - _removeFromRenderQueue = function _removeFromRenderQueue(func) { - var i = _renderQueue.length; - - while (i--) { - if (_renderQueue[i] === func) { - _renderQueue.splice(i, 1); - } - } - - gsap.to(_renderQueueTimeout, { - overwrite: true, - delay: 15, - duration: 0, - onComplete: _renderQueueTimeout, - data: "_draggable" - }); //remove the "tick" listener only after the render queue is empty for 15 seconds (to improve performance). Adding/removing it constantly for every click/touch wouldn't deliver optimal speed, and we also don't want the ticker to keep calling the render method when things are idle for long periods of time (we want to improve battery life on mobile devices). -}, - _setDefaults = function _setDefaults(obj, defaults) { - for (var p in defaults) { - if (!(p in obj)) { - obj[p] = defaults[p]; - } - } - - return obj; -}, - _addListener = function _addListener(element, type, func, capture) { - if (element.addEventListener) { - var touchType = _touchEventLookup[type]; - capture = capture || (_supportsPassive ? { - passive: false - } : null); - element.addEventListener(touchType || type, func, capture); - touchType && type !== touchType && element.addEventListener(type, func, capture); //some browsers actually support both, so must we. But pointer events cover all. - } -}, - _removeListener = function _removeListener(element, type, func) { - if (element.removeEventListener) { - var touchType = _touchEventLookup[type]; - element.removeEventListener(touchType || type, func); - touchType && type !== touchType && element.removeEventListener(type, func); - } -}, - _preventDefault = function _preventDefault(event) { - event.preventDefault && event.preventDefault(); - event.preventManipulation && event.preventManipulation(); //for some Microsoft browsers -}, - _hasTouchID = function _hasTouchID(list, ID) { - var i = list.length; - - while (i--) { - if (list[i].identifier === ID) { - return true; - } - } -}, - _onMultiTouchDocumentEnd = function _onMultiTouchDocumentEnd(event) { - _isMultiTouching = event.touches && _dragCount < event.touches.length; - - _removeListener(event.target, "touchend", _onMultiTouchDocumentEnd); -}, - _onMultiTouchDocument = function _onMultiTouchDocument(event) { - _isMultiTouching = event.touches && _dragCount < event.touches.length; - - _addListener(event.target, "touchend", _onMultiTouchDocumentEnd); -}, - _getDocScrollTop = function _getDocScrollTop(doc) { - return _win.pageYOffset || doc.scrollTop || doc.documentElement.scrollTop || doc.body.scrollTop || 0; -}, - _getDocScrollLeft = function _getDocScrollLeft(doc) { - return _win.pageXOffset || doc.scrollLeft || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0; -}, - _addScrollListener = function _addScrollListener(e, callback) { - _addListener(e, "scroll", callback); - - if (!_isRoot(e.parentNode)) { - _addScrollListener(e.parentNode, callback); - } -}, - _removeScrollListener = function _removeScrollListener(e, callback) { - _removeListener(e, "scroll", callback); - - if (!_isRoot(e.parentNode)) { - _removeScrollListener(e.parentNode, callback); - } -}, - _isRoot = function _isRoot(e) { - return !!(!e || e === _docElement || e.nodeType === 9 || e === _doc.body || e === _win || !e.nodeType || !e.parentNode); -}, - _getMaxScroll = function _getMaxScroll(element, axis) { - var dim = axis === "x" ? "Width" : "Height", - scroll = "scroll" + dim, - client = "client" + dim; - return Math.max(0, _isRoot(element) ? Math.max(_docElement[scroll], _body[scroll]) - (_win["inner" + dim] || _docElement[client] || _body[client]) : element[scroll] - element[client]); -}, - _recordMaxScrolls = function _recordMaxScrolls(e, skipCurrent) { - //records _gsMaxScrollX and _gsMaxScrollY properties for the element and all ancestors up the chain so that we can cap it, otherwise dragging beyond the edges with autoScroll on can endlessly scroll. - var x = _getMaxScroll(e, "x"), - y = _getMaxScroll(e, "y"); - - if (_isRoot(e)) { - e = _windowProxy; - } else { - _recordMaxScrolls(e.parentNode, skipCurrent); - } - - e._gsMaxScrollX = x; - e._gsMaxScrollY = y; - - if (!skipCurrent) { - e._gsScrollX = e.scrollLeft || 0; - e._gsScrollY = e.scrollTop || 0; - } -}, - _setStyle = function _setStyle(element, property, value) { - var style = element.style; - - if (!style) { - return; - } - - if (_isUndefined(style[property])) { - property = _checkPrefix(property, element) || property; - } - - if (value == null) { - style.removeProperty && style.removeProperty(property.replace(/([A-Z])/g, "-$1").toLowerCase()); - } else { - style[property] = value; - } -}, - _getComputedStyle = function _getComputedStyle(element) { - return _win.getComputedStyle(element instanceof Element ? element : element.host || (element.parentNode || {}).host || element); -}, - //the "host" stuff helps to accommodate ShadowDom objects. -_tempRect = {}, - //reuse to reduce garbage collection tasks -_parseRect = function _parseRect(e) { - //accepts a DOM element, a mouse event, or a rectangle object and returns the corresponding rectangle with left, right, width, height, top, and bottom properties - if (e === _win) { - _tempRect.left = _tempRect.top = 0; - _tempRect.width = _tempRect.right = _docElement.clientWidth || e.innerWidth || _body.clientWidth || 0; - _tempRect.height = _tempRect.bottom = (e.innerHeight || 0) - 20 < _docElement.clientHeight ? _docElement.clientHeight : e.innerHeight || _body.clientHeight || 0; - return _tempRect; - } - - var doc = e.ownerDocument || _doc, - r = !_isUndefined(e.pageX) ? { - left: e.pageX - _getDocScrollLeft(doc), - top: e.pageY - _getDocScrollTop(doc), - right: e.pageX - _getDocScrollLeft(doc) + 1, - bottom: e.pageY - _getDocScrollTop(doc) + 1 - } : !e.nodeType && !_isUndefined(e.left) && !_isUndefined(e.top) ? e : _toArray(e)[0].getBoundingClientRect(); - - if (_isUndefined(r.right) && !_isUndefined(r.width)) { - r.right = r.left + r.width; - r.bottom = r.top + r.height; - } else if (_isUndefined(r.width)) { - //some browsers don't include width and height properties. We can't just set them directly on r because some browsers throw errors, so create a new generic object. - r = { - width: r.right - r.left, - height: r.bottom - r.top, - right: r.right, - left: r.left, - bottom: r.bottom, - top: r.top - }; - } - - return r; -}, - _dispatchEvent = function _dispatchEvent(target, type, callbackName) { - var vars = target.vars, - callback = vars[callbackName], - listeners = target._listeners[type], - result; - - if (_isFunction(callback)) { - result = callback.apply(vars.callbackScope || target, vars[callbackName + "Params"] || [target.pointerEvent]); - } - - if (listeners && target.dispatchEvent(type) === false) { - result = false; - } - - return result; -}, - _getBounds = function _getBounds(target, context) { - //accepts any of the following: a DOM element, jQuery object, selector text, or an object defining bounds as {top, left, width, height} or {minX, maxX, minY, maxY}. Returns an object with left, top, width, and height properties. - var e = _toArray(target)[0], - top, - left, - offset; - - if (!e.nodeType && e !== _win) { - if (!_isUndefined(target.left)) { - offset = { - x: 0, - y: 0 - }; //_getOffsetTransformOrigin(context); //the bounds should be relative to the origin - - return { - left: target.left - offset.x, - top: target.top - offset.y, - width: target.width, - height: target.height - }; - } - - left = target.min || target.minX || target.minRotation || 0; - top = target.min || target.minY || 0; - return { - left: left, - top: top, - width: (target.max || target.maxX || target.maxRotation || 0) - left, - height: (target.max || target.maxY || 0) - top - }; - } - - return _getElementBounds(e, context); -}, - _point1 = {}, - //we reuse to minimize garbage collection tasks. -_getElementBounds = function _getElementBounds(element, context) { - context = _toArray(context)[0]; - var isSVG = element.getBBox && element.ownerSVGElement, - doc = element.ownerDocument || _doc, - left, - right, - top, - bottom, - matrix, - p1, - p2, - p3, - p4, - bbox, - width, - height, - cs, - contextParent; - - if (element === _win) { - top = _getDocScrollTop(doc); - left = _getDocScrollLeft(doc); - right = left + (doc.documentElement.clientWidth || element.innerWidth || doc.body.clientWidth || 0); - bottom = top + ((element.innerHeight || 0) - 20 < doc.documentElement.clientHeight ? doc.documentElement.clientHeight : element.innerHeight || doc.body.clientHeight || 0); //some browsers (like Firefox) ignore absolutely positioned elements, and collapse the height of the documentElement, so it could be 8px, for example, if you have just an absolutely positioned div. In that case, we use the innerHeight to resolve this. - } else if (context === _win || _isUndefined(context)) { - return element.getBoundingClientRect(); - } else { - left = top = 0; - - if (isSVG) { - bbox = element.getBBox(); - width = bbox.width; - height = bbox.height; - } else { - if (element.viewBox && (bbox = element.viewBox.baseVal)) { - left = bbox.x || 0; - top = bbox.y || 0; - width = bbox.width; - height = bbox.height; - } - - if (!width) { - cs = _getComputedStyle(element); - bbox = cs.boxSizing === "border-box"; - width = (parseFloat(cs.width) || element.clientWidth || 0) + (bbox ? 0 : parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth)); - height = (parseFloat(cs.height) || element.clientHeight || 0) + (bbox ? 0 : parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth)); - } - } - - right = width; - bottom = height; - } - - if (element === context) { - return { - left: left, - top: top, - width: right - left, - height: bottom - top - }; - } - - matrix = getGlobalMatrix(context, true).multiply(getGlobalMatrix(element)); - p1 = matrix.apply({ - x: left, - y: top - }); - p2 = matrix.apply({ - x: right, - y: top - }); - p3 = matrix.apply({ - x: right, - y: bottom - }); - p4 = matrix.apply({ - x: left, - y: bottom - }); - left = Math.min(p1.x, p2.x, p3.x, p4.x); - top = Math.min(p1.y, p2.y, p3.y, p4.y); - contextParent = context.parentNode || {}; - return { - left: left + (contextParent.scrollLeft || 0), - top: top + (contextParent.scrollTop || 0), - width: Math.max(p1.x, p2.x, p3.x, p4.x) - left, - height: Math.max(p1.y, p2.y, p3.y, p4.y) - top - }; -}, - _parseInertia = function _parseInertia(draggable, snap, max, min, factor, forceZeroVelocity) { - var vars = {}, - a, - i, - l; - - if (snap) { - if (factor !== 1 && snap instanceof Array) { - //some data must be altered to make sense, like if the user passes in an array of rotational values in degrees, we must convert it to radians. Or for scrollLeft and scrollTop, we invert the values. - vars.end = a = []; - l = snap.length; - - if (_isObject(snap[0])) { - //if the array is populated with objects, like points ({x:100, y:200}), make copies before multiplying by the factor, otherwise we'll mess up the originals and the user may reuse it elsewhere. - for (i = 0; i < l; i++) { - a[i] = _copy(snap[i], factor); - } - } else { - for (i = 0; i < l; i++) { - a[i] = snap[i] * factor; - } - } - - max += 1.1; //allow 1.1 pixels of wiggle room when snapping in order to work around some browser inconsistencies in the way bounds are reported which can make them roughly a pixel off. For example, if "snap:[-$('#menu').width(), 0]" was defined and #menu had a wrapper that was used as the bounds, some browsers would be one pixel off, making the minimum -752 for example when snap was [-753,0], thus instead of snapping to -753, it would snap to 0 since -753 was below the minimum. - - min -= 1.1; - } else if (_isFunction(snap)) { - vars.end = function (value) { - var result = snap.call(draggable, value), - copy, - p; - - if (factor !== 1) { - if (_isObject(result)) { - copy = {}; - - for (p in result) { - copy[p] = result[p] * factor; - } - - result = copy; - } else { - result *= factor; - } - } - - return result; //we need to ensure that we can scope the function call to the Draggable instance itself so that users can access important values like maxX, minX, maxY, minY, x, and y from within that function. - }; - } else { - vars.end = snap; - } - } - - if (max || max === 0) { - vars.max = max; - } - - if (min || min === 0) { - vars.min = min; - } - - if (forceZeroVelocity) { - vars.velocity = 0; - } - - return vars; -}, - _isClickable = function _isClickable(element) { - //sometimes it's convenient to mark an element as clickable by adding a data-clickable="true" attribute (in which case we won't preventDefault() the mouse/touch event). This method checks if the element is an , , or