diff --git a/.gitignore b/.gitignore index 4a87ee74a9..718092f0b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,30 +1,25 @@ *~ .DS_Store -node_modules -jspm_packages *.sw[mnpcod] *.log *.tmp *.tmp.* log.txt -example/cordova/iOS/www/js/framework - -example/cordova/iOS/www/js/framework -.sass-cache/ -framework.sublime-project - -framework.sublime-workspace +*.sublime-project +*.sublime-workspace UserInterfaceState.xcuserstate -*.sublime-project +.idea/ +.sass-cache/ +node_modules/ +tmp/ +temp/ +dist/ -*.sublime-workspace - -bower_components/ -tmp -temp -dist -angular2 - -.idea -/src/components/split-view/test/settings/main.js +scripts/resources/web-animations-js/test/ +scripts/resources/web-animations-js/inter-* +scripts/resources/web-animations-js/**/*.map +scripts/resources/web-animations-js/**/*.md +scripts/resources/web-animations-js/**/*.sh +scripts/resources/web-animations-js/**/*.yml +scripts/resources/web-animations-js/**/*.gz diff --git a/package.json b/package.json index 013a713bde..7c540abcad 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,6 @@ "traceur": "0.0.91", "typescript": "^1.5.3", "vinyl": "^0.4.6", - "web-animations-js": "tlancina/web-animations-js", "yargs": "^3.6.0" } } diff --git a/scripts/build/config.js b/scripts/build/config.js index 04ddc9b588..2064d6f1d4 100644 --- a/scripts/build/config.js +++ b/scripts/build/config.js @@ -1,3 +1,4 @@ + module.exports = { dist: 'dist', distLib: 'dist/lib', @@ -18,7 +19,7 @@ module.exports = { 'node_modules/angular2/bundles/angular2.dev.js', 'node_modules/angular2/bundles/router.dev.js', 'dist/js/ionic.js', - 'node_modules/web-animations-js/web-animations.min.js' + 'scripts/resources/web-animations-js/web-animations.min.js' ], protractorPort: 8876, diff --git a/scripts/resources/web-animations-js/COPYING b/scripts/resources/web-animations-js/COPYING new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/scripts/resources/web-animations-js/COPYING @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/scripts/resources/web-animations-js/Gruntfile.js b/scripts/resources/web-animations-js/Gruntfile.js new file mode 100644 index 0000000000..fb232839d5 --- /dev/null +++ b/scripts/resources/web-animations-js/Gruntfile.js @@ -0,0 +1,293 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +module.exports = function(grunt) { + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-gjslint'); + grunt.loadNpmTasks('grunt-checkrepo'); + grunt.loadNpmTasks('grunt-karma'); + grunt.loadNpmTasks('grunt-saucelabs'); + grunt.loadNpmTasks('grunt-git-status'); + grunt.loadNpmTasks('grunt-template'); + + var targetConfig = require('./target-config.js'); + + var sourceMap = require('source-map'); + + var config = { + uglify: {}, + template: {}, + wrap: {}, + sourceMapConcat: {}, + }; + + function concat(sources, target, defines) { + config.uglify[target] = { + options: { + sourceMap: true, + sourceMapName: target + '.map', + wrap: false, + compress: { + global_defs: defines, + dead_code: false + }, + mangle: false + }, + nonull: true, + dest: target, + src: sources + }; + return 'uglify:' + target; + } + + function compress(source, target, defines) { + var name = concat([source], target, defines); + var record = config.uglify[target]; + record.options.sourceMapIn = source + '.map'; + record.options.banner = grunt.file.read('templates/boilerplate'); + record.options.wrap = true; + record.options.compress.dead_code = true; + record.options.mangle = { eval: true }; + return name; + } + + function genTarget(target) { + var config = targetConfig[target]; + var newGens = [ + generateFromTemplate('templates/web-animations.js', {target: target}, target + '.dev.js'), + generateFromTemplate('templates/web-animations.html', {src: config.src}, target + '.dev.html'), + generateFromTemplate('templates/runner.html', {target: target}, 'test/runner-' + target + '.html')]; + return newGens; + } + + function generateFromTemplate(source, data, target) { + var targetSpec = {}; + targetSpec[target] = [source]; + config.template[target] = { + options: { + data: data + }, + files: targetSpec + } + return 'template:' + target; + } + + function guard(source, target) { + config.wrap[target] = { + source: source, + preamble: '(function() {\n' + + ' if (document.documentElement.animate) {\n' + + ' var player = document.documentElement.animate([], 0);\n' + + ' var load = true;\n' + + ' if (player) {\n' + + ' load = false;\n' + + ' "play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(t) {\n' + + ' if (player[t] === undefined) {\n' + + ' load = true;\n' + + ' }\n' + + ' });\n' + + ' }\n' + + ' if (!load) { return; }' + + ' }\n', + postamble: '})();' + }; + return 'wrap:' + target; + } + + function concatWithMaps(sources, target) { + config.sourceMapConcat[target] = { + sources: sources + } + return 'sourceMapConcat:' + target; + }; + + var concatDefines = { + WEB_ANIMATIONS_TESTING: false + }; + + function buildWebAnimations1(target) { + var config = targetConfig[target]; + return genTarget(target).concat([ + concat(config.scopeSrc.concat(config.sharedSrc).concat(config.webAnimations1Src), 'inter-raw-' + target + '.js', concatDefines), + guard('inter-raw-' + target + '.js', 'inter-' + target + '.js'), + compress('inter-' + target + '.js', target + '.min.js', concatDefines) + ]); + } + + function buildWebAnimationsNext(target) { + var config = targetConfig[target]; + return genTarget(target).concat([ + concat(config.scopeSrc.concat(config.sharedSrc), 'inter-' + target + '-preamble.js', concatDefines), + concat(config.webAnimations1Src, 'inter-component-' + target + 'web-animations-1.js', concatDefines), + guard('inter-component-' + target + 'web-animations-1.js', 'inter-guarded-' + target + '-web-animations-1.js'), + concat(config.webAnimationsNextSrc, 'inter-component-' + target + '.js', concatDefines), + concatWithMaps(['inter-' + target + '-preamble.js', 'inter-guarded-' + target + '-web-animations-1.js', 'inter-component-' + target + '.js'], + 'inter-' + target + '.js'), + compress('inter-' + target + '.js', target + '.min.js', concatDefines) + ]); + } + + grunt.registerTask('web-animations', buildWebAnimations1('web-animations')); + grunt.registerTask('web-animations-next', buildWebAnimationsNext('web-animations-next')); + grunt.registerTask('web-animations-next-lite', buildWebAnimationsNext('web-animations-next-lite')); + + var testTargets = {'web-animations': {}, 'web-animations-next': {}}; + + grunt.initConfig({ + uglify: config.uglify, + template: config.template, + wrap: config.wrap, + sourceMapConcat: config.sourceMapConcat, + checkrepo: { + all: { + clean: true, + }, + }, + 'git-status': { + all: { + }, + }, + gjslint: { + options: { + flags: [ + '--nojsdoc', + '--strict', + '--disable 7,121,110', // 7: Wrong blank line count + // 121: Illegal comma at end of object literal + // 110: Line too long + ], + reporter: { + name: 'console' + } + }, + all: { + src: [ + 'src/*.js', + 'test/*.js', + 'test/js/*.js', + ], + } + }, + test: testTargets, + sauce: testTargets, + }); + + + grunt.task.registerMultiTask('test', 'Run tests under Karma', function() { + var done = this.async(); + var karmaConfig = require('karma/lib/config').parseConfig(require('path').resolve('test/karma-config.js'), {}); + var config = targetConfig[this.target]; + karmaConfig.files = ['test/karma-setup.js'].concat(config.src, config.test); + var karmaServer = require('karma').server; + karmaServer.start(karmaConfig, function(exitCode) { + done(exitCode === 0); + }); + }); + + grunt.task.registerMultiTask('sauce', 'Run tests under Karma on Saucelabs', function() { + var done = this.async(); + var karmaConfig = require('karma/lib/config').parseConfig(require('path').resolve('test/karma-config-ci.js'), {}); + var config = targetConfig[this.target]; + karmaConfig.files = ['test/karma-setup.js'].concat(config.src, config.test); + karmaConfig.sauceLabs.testName = 'web-animation-next ' + this.target + ' Unit tests'; + var karmaServer = require('karma').server; + karmaServer.start(karmaConfig, function(exitCode) { + done(exitCode === 0); + }); + }); + + grunt.task.registerMultiTask('sourceMapConcat', 'concat source files and produce combined source map', + function() { + var sources = this.data.sources.map(grunt.file.read); + var sourceMaps = this.data.sources.map(function(f) { return grunt.file.read(f + '.map'); }); + var out = ""; + var outMapGenerator = new sourceMap.SourceMapGenerator({file: this.target}); + var lineDelta = 0; + for (var i = 0; i < sources.length; i++) { + out += sources[i]; + new sourceMap.SourceMapConsumer(sourceMaps[i]).eachMapping(function(mapping) { + outMapGenerator.addMapping({ + generated: {line: mapping.generatedLine + lineDelta, column: mapping.generatedColumn}, + original: {line: mapping.originalLine, column: mapping.originalColumn}, + source: mapping.source, name: mapping.name}); + }); + var sourceLines = sources[i].split('\n'); + lineDelta += sourceLines.length; + if (sources[i][sources[i].length - 1] !== '\n') { + out += '\n'; + } + } + grunt.file.write(this.target, out); + grunt.file.write(this.target + '.map', outMapGenerator.toString()); + }); + + grunt.task.registerMultiTask('wrap', 'Wrap source file and update source map', + function() { + var inFile = grunt.file.read(this.data.source); + var inMap = grunt.file.read(this.data.source + '.map'); + var inLines = inFile.split('\n'); + var i = 0; + + // Discover copyright header + while (inLines[i].length < 2 || inLines[i].substring(0, 2) == '//') { + i++; + } + + // Fix mapping footer + var postamble = this.data.postamble; + if (inLines[inLines.length - 1].substring(0, 21) == '//# sourceMappingURL=') { + postamble += '\n//# sourceMappingURL=' + this.target + '.map'; + } + + if (i > 0) { + var banner = inLines.slice(0, i).join('\n') + '\n'; + } else { + var banner = ''; + } + + var source = inLines.slice(i, inLines.length - 1).join('\n'); + + grunt.file.write(this.target, banner + this.data.preamble + source + postamble); + var preLines = this.data.preamble.split('\n'); + var lineDelta = preLines.length; + if (this.data.preamble[this.data.preamble.length - 1] == '\n') { + var charDelta = 0; + } else { + var charDelta = preLines[lineDelta - 1].length; + lineDelta -= 1; + } + var inMapConsumer = new sourceMap.SourceMapConsumer(inMap); + var outMapGenerator = new sourceMap.SourceMapGenerator({file: this.target}); + inMapConsumer.eachMapping(function(mapping) { + if (mapping.generatedLine == i + 1) { + mapping.generatedColumn += charDelta; + } + mapping.generatedLine += lineDelta; + outMapGenerator.addMapping( + {generated: {line: mapping.generatedLine, column: mapping.generatedColumn}, + original: {line: mapping.originalLine, column: mapping.originalColumn}, + source: mapping.source, name: mapping.name}); + }); + grunt.file.write(this.target + '.map', outMapGenerator.toString()); + }); + + grunt.task.registerTask('clean', 'Remove files generated by grunt', function() { + grunt.file.expand('web-animations*').concat(grunt.file.expand('test/runner-*.html')).concat(grunt.file.expand('inter-*')).forEach(function(file) { + grunt.file.delete(file); + grunt.log.writeln('File ' + file + ' removed'); + }); + }); + + grunt.task.registerTask('default', ['web-animations', 'web-animations-next', 'web-animations-next-lite', 'gjslint']); +}; diff --git a/scripts/resources/web-animations-js/bower.json b/scripts/resources/web-animations-js/bower.json new file mode 100644 index 0000000000..22f26b5e5c --- /dev/null +++ b/scripts/resources/web-animations-js/bower.json @@ -0,0 +1,31 @@ +{ + "name": "web-animations-js", + "description": "JavaScript implementation of the Web Animations API", + "homepage": "https://github.com/web-animations/web-animations-js", + "main": "web-animations.min.js", + "moduleType": [ + "globals" + ], + "keywords": [ + "animations", + "polyfill" + ], + "license": "Apache-2.0", + "ignore": [ + "**/.*", + "node_modules", + "templates", + "test", + "src", + "Gruntfile.js", + "package.json", + "target-config.js", + "target-loader.js", + "web-animations.dev.html", + "web-animations.dev.js", + "web-animations-next.dev.html", + "web-animations-next.dev.js", + "web-animations-next-lite.dev.html", + "web-animations-next-lite.dev.js" + ] +} diff --git a/scripts/resources/web-animations-js/package.json b/scripts/resources/web-animations-js/package.json new file mode 100644 index 0000000000..b579b79d6c --- /dev/null +++ b/scripts/resources/web-animations-js/package.json @@ -0,0 +1,33 @@ +{ + "name": "web-animations-js", + "private": true, + "repository": { + "type": "git", + "url": "https://github.com/web-animations/web-animations-js.git" + }, + "devDependencies": { + "mocha": "1.21.4", + "chai": "^1.9.1", + "grunt": "~0.4.5", + "grunt-contrib-uglify": "^0.4.0", + "grunt-gjslint": "^0.1.4", + "grunt-karma": "^0.8.2", + "karma": "^0.12.14", + "karma-mocha": "^0.1.3", + "karma-chai": "^0.1.0", + "karma-chrome-launcher": "~0.1.4", + "karma-firefox-launcher": "~0.1.3", + "karma-ie-launcher": "~0.1.5", + "karma-safari-launcher": "~0.1.1", + "karma-sauce-launcher": "~0.2.3", + "grunt-checkrepo": "~0.1.0", + "grunt-saucelabs": "~4.0.2", + "grunt-checkrepo": "~0.1.0", + "grunt-git-status": "~1.0.0", + "grunt-template": "~0.2.3", + "source-map": "~0.1.40" + }, + "scripts": { + "test": "grunt test gjslint git-status checkrepo" + } +} diff --git a/scripts/resources/web-animations-js/src/animation.js b/scripts/resources/web-animations-js/src/animation.js new file mode 100644 index 0000000000..4cf89f24fe --- /dev/null +++ b/scripts/resources/web-animations-js/src/animation.js @@ -0,0 +1,229 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + + shared.sequenceNumber = 0; + + var AnimationEvent = function(target, currentTime, timelineTime) { + this.target = target; + this.currentTime = currentTime; + this.timelineTime = timelineTime; + + this.type = 'finish'; + this.bubbles = false; + this.cancelable = false; + this.currentTarget = target; + this.defaultPrevented = false; + this.eventPhase = Event.AT_TARGET; + this.timeStamp = Date.now(); + }; + + scope.Animation = function(effect) { + this._sequenceNumber = shared.sequenceNumber++; + this._currentTime = 0; + this._startTime = null; + this._paused = false; + this._playbackRate = 1; + this._inTimeline = true; + this._finishedFlag = false; + this.onfinish = null; + this._finishHandlers = []; + this._effect = effect; + this._inEffect = this._effect._update(0); + this._idle = true; + this._currentTimePending = false; + }; + + scope.Animation.prototype = { + _ensureAlive: function() { + // If an animation is playing backwards and is not fill backwards/both + // then it should go out of effect when it reaches the start of its + // active interval (currentTime == 0). + if (this.playbackRate < 0 && this.currentTime === 0) { + this._inEffect = this._effect._update(-1); + } else { + this._inEffect = this._effect._update(this.currentTime); + } + if (!this._inTimeline && (this._inEffect || !this._finishedFlag)) { + this._inTimeline = true; + scope.timeline._animations.push(this); + } + }, + _tickCurrentTime: function(newTime, ignoreLimit) { + if (newTime != this._currentTime) { + this._currentTime = newTime; + if (this._isFinished && !ignoreLimit) + this._currentTime = this._playbackRate > 0 ? this._totalDuration : 0; + this._ensureAlive(); + } + }, + get currentTime() { + if (this._idle || this._currentTimePending) + return null; + return this._currentTime; + }, + set currentTime(newTime) { + newTime = +newTime; + if (isNaN(newTime)) + return; + scope.restart(); + if (!this._paused && this._startTime != null) { + this._startTime = this._timeline.currentTime - newTime / this._playbackRate; + } + this._currentTimePending = false; + if (this._currentTime == newTime) + return; + this._tickCurrentTime(newTime, true); + scope.invalidateEffects(); + }, + get startTime() { + return this._startTime; + }, + set startTime(newTime) { + newTime = +newTime; + if (isNaN(newTime)) + return; + if (this._paused || this._idle) + return; + this._startTime = newTime; + this._tickCurrentTime((this._timeline.currentTime - this._startTime) * this.playbackRate); + scope.invalidateEffects(); + }, + get playbackRate() { + return this._playbackRate; + }, + set playbackRate(value) { + if (value == this._playbackRate) { + return; + } + var oldCurrentTime = this.currentTime; + this._playbackRate = value; + this._startTime = null; + if (this.playState != 'paused' && this.playState != 'idle') { + this.play(); + } + if (oldCurrentTime != null) { + this.currentTime = oldCurrentTime; + } + }, + get _isFinished() { + return !this._idle && (this._playbackRate > 0 && this._currentTime >= this._totalDuration || + this._playbackRate < 0 && this._currentTime <= 0); + }, + get _totalDuration() { return this._effect._totalDuration; }, + get playState() { + if (this._idle) + return 'idle'; + if ((this._startTime == null && !this._paused && this.playbackRate != 0) || this._currentTimePending) + return 'pending'; + if (this._paused) + return 'paused'; + if (this._isFinished) + return 'finished'; + return 'running'; + }, + play: function() { + this._paused = false; + if (this._isFinished || this._idle) { + this._currentTime = this._playbackRate > 0 ? 0 : this._totalDuration; + this._startTime = null; + scope.invalidateEffects(); + } + this._finishedFlag = false; + scope.restart(); + this._idle = false; + this._ensureAlive(); + }, + pause: function() { + if (!this._isFinished && !this._paused && !this._idle) { + this._currentTimePending = true; + } + this._startTime = null; + this._paused = true; + }, + finish: function() { + if (this._idle) + return; + this.currentTime = this._playbackRate > 0 ? this._totalDuration : 0; + this._startTime = this._totalDuration - this.currentTime; + this._currentTimePending = false; + }, + cancel: function() { + if (!this._inEffect) + return; + this._inEffect = false; + this._idle = true; + this.currentTime = 0; + this._startTime = null; + this._effect._update(null); + // effects are invalid after cancellation as the animation state + // needs to un-apply. + scope.invalidateEffects(); + // in the absence of effect revalidation via getComputedStyle, we + // need a single tick to remove the effect of the cancelled + // animation. + scope.restart(); + }, + reverse: function() { + this.playbackRate *= -1; + this.play(); + }, + addEventListener: function(type, handler) { + if (typeof handler == 'function' && type == 'finish') + this._finishHandlers.push(handler); + }, + removeEventListener: function(type, handler) { + if (type != 'finish') + return; + var index = this._finishHandlers.indexOf(handler); + if (index >= 0) + this._finishHandlers.splice(index, 1); + }, + _fireEvents: function(baseTime) { + var finished = this._isFinished; + if ((finished || this._idle) && !this._finishedFlag) { + var event = new AnimationEvent(this, this._currentTime, baseTime); + var handlers = this._finishHandlers.concat(this.onfinish ? [this.onfinish] : []); + + // IONIC HACK! + // CANNOT SETTIMEOUT OR ELSE THE BROWSER HAS A CHANCE TO + // RENDER AND CAUSES A FLICKER ON SAFAR + //setTimeout(function() { + handlers.forEach(function(handler) { + handler.call(event.target, event); + }); + //}, 0); + } + this._finishedFlag = finished; + }, + _tick: function(timelineTime) { + if (!this._idle && !this._paused) { + if (this._startTime == null) + this.startTime = timelineTime - this._currentTime / this.playbackRate; + else if (!this._isFinished) + this._tickCurrentTime((timelineTime - this._startTime) * this.playbackRate); + } + + this._currentTimePending = false; + this._fireEvents(timelineTime); + return !this._idle && (this._inEffect || !this._finishedFlag); + }, + }; + + if (WEB_ANIMATIONS_TESTING) { + testing.webAnimations1Animation = scope.Animation; + } + +})(webAnimationsShared, webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/apply-preserving-inline-style.js b/scripts/resources/web-animations-js/src/apply-preserving-inline-style.js new file mode 100644 index 0000000000..795be36452 --- /dev/null +++ b/scripts/resources/web-animations-js/src/apply-preserving-inline-style.js @@ -0,0 +1,191 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + var styleAttributes = { + cssText: 1, + length: 1, + parentRule: 1, + }; + + var styleMethods = { + getPropertyCSSValue: 1, + getPropertyPriority: 1, + getPropertyValue: 1, + item: 1, + removeProperty: 1, + setProperty: 1, + }; + + var styleMutatingMethods = { + removeProperty: 1, + setProperty: 1, + }; + + function configureProperty(object, property, descriptor) { + descriptor.enumerable = true; + descriptor.configurable = true; + Object.defineProperty(object, property, descriptor); + } + + function AnimatedCSSStyleDeclaration(element) { + WEB_ANIMATIONS_TESTING && console.assert(!(element.style instanceof AnimatedCSSStyleDeclaration), + 'Element must not already have an animated style attached.'); + + // Stores the inline style of the element on its behalf while the + // polyfill uses the element's inline style to simulate web animations. + // This is needed to fake regular inline style CSSOM access on the element. + this._surrogateStyle = document.createElementNS('http://www.w3.org/1999/xhtml', 'div').style; + this._style = element.style; + this._length = 0; + this._isAnimatedProperty = {}; + + // Copy the inline style contents over to the surrogate. + for (var i = 0; i < this._style.length; i++) { + var property = this._style[i]; + this._surrogateStyle[property] = this._style[property]; + } + this._updateIndices(); + } + + AnimatedCSSStyleDeclaration.prototype = { + get cssText() { + return this._surrogateStyle.cssText; + }, + set cssText(text) { + var isAffectedProperty = {}; + for (var i = 0; i < this._surrogateStyle.length; i++) { + isAffectedProperty[this._surrogateStyle[i]] = true; + } + this._surrogateStyle.cssText = text; + this._updateIndices(); + for (var i = 0; i < this._surrogateStyle.length; i++) { + isAffectedProperty[this._surrogateStyle[i]] = true; + } + for (var property in isAffectedProperty) { + if (!this._isAnimatedProperty[property]) { + this._style.setProperty(property, this._surrogateStyle.getPropertyValue(property)); + } + } + }, + get length() { + return this._surrogateStyle.length; + }, + get parentRule() { + return this._style.parentRule; + }, + // Mirror the indexed getters and setters of the surrogate style. + _updateIndices: function() { + while (this._length < this._surrogateStyle.length) { + Object.defineProperty(this, this._length, { + configurable: true, + enumerable: false, + get: (function(index) { + return function() { return this._surrogateStyle[index]; }; + })(this._length) + }); + this._length++; + } + while (this._length > this._surrogateStyle.length) { + this._length--; + Object.defineProperty(this, this._length, { + configurable: true, + enumerable: false, + value: undefined + }); + } + }, + _set: function(property, value) { + this._style[property] = value; + this._isAnimatedProperty[property] = true; + }, + _clear: function(property) { + this._style[property] = this._surrogateStyle[property]; + delete this._isAnimatedProperty[property]; + }, + }; + + // Wrap the style methods. + for (var method in styleMethods) { + AnimatedCSSStyleDeclaration.prototype[method] = (function(method, modifiesStyle) { + return function() { + var result = this._surrogateStyle[method].apply(this._surrogateStyle, arguments); + if (modifiesStyle) { + if (!this._isAnimatedProperty[arguments[0]]) + this._style[method].apply(this._style, arguments); + this._updateIndices(); + } + return result; + } + })(method, method in styleMutatingMethods); + } + + // Wrap the style.cssProperty getters and setters. + for (var property in document.documentElement.style) { + if (property in styleAttributes || property in styleMethods) { + continue; + } + (function(property) { + configureProperty(AnimatedCSSStyleDeclaration.prototype, property, { + get: function() { + return this._surrogateStyle[property]; + }, + set: function(value) { + this._surrogateStyle[property] = value; + this._updateIndices(); + if (!this._isAnimatedProperty[property]) + this._style[property] = value; + } + }); + })(property); + } + + function ensureStyleIsPatched(element) { + if (element._webAnimationsPatchedStyle) + return; + + var animatedStyle = new AnimatedCSSStyleDeclaration(element); + try { + configureProperty(element, 'style', { get: function() { return animatedStyle; } }); + } catch (_) { + // iOS and older versions of Safari (pre v7) do not support overriding an element's + // style object. Animations will clobber any inline styles as a result. + element.style._set = function(property, value) { + element.style[property] = value; + }; + element.style._clear = function(property) { + element.style[property] = ''; + }; + } + + // We must keep a handle on the patched style to prevent it from getting GC'd. + element._webAnimationsPatchedStyle = element.style; + } + + scope.apply = function(element, property, value) { + ensureStyleIsPatched(element); + element.style._set(scope.propertyName(property), value); + }; + + scope.clear = function(element, property) { + if (element._webAnimationsPatchedStyle) { + element.style._clear(scope.propertyName(property)); + } + }; + + if (WEB_ANIMATIONS_TESTING) + testing.ensureStyleIsPatched = ensureStyleIsPatched; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/apply.js b/scripts/resources/web-animations-js/src/apply.js new file mode 100644 index 0000000000..3200f967ea --- /dev/null +++ b/scripts/resources/web-animations-js/src/apply.js @@ -0,0 +1,25 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + scope.apply = function(element, property, value) { + element.style[scope.propertyName(property)] = value; + }; + + scope.clear = function(element, property) { + element.style[scope.propertyName(property)] = ''; + }; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/box-handler.js b/scripts/resources/web-animations-js/src/box-handler.js new file mode 100644 index 0000000000..3399263a48 --- /dev/null +++ b/scripts/resources/web-animations-js/src/box-handler.js @@ -0,0 +1,57 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + function consumeLengthPercentOrAuto(string) { + return scope.consumeLengthOrPercent(string) || scope.consumeToken(/^auto/, string); + } + function parseBox(string) { + var result = scope.consumeList([ + scope.ignore(scope.consumeToken.bind(null, /^rect/)), + scope.ignore(scope.consumeToken.bind(null, /^\(/)), + scope.consumeRepeated.bind(null, consumeLengthPercentOrAuto, /^,/), + scope.ignore(scope.consumeToken.bind(null, /^\)/)), + ], string); + if (result && result[0].length == 4) { + return result[0]; + } + } + + function mergeComponent(left, right) { + if (left == 'auto' || right == 'auto') { + return [true, false, function(t) { + var result = t ? left : right; + if (result == 'auto') { + return 'auto'; + } + // FIXME: There's probably a better way to turn a dimension back into a string. + var merged = scope.mergeDimensions(result, result); + return merged[2](merged[0]); + }]; + } + return scope.mergeDimensions(left, right); + } + + function wrap(result) { + return 'rect(' + result + ')'; + } + + var mergeBoxes = scope.mergeWrappedNestedRepeated.bind(null, wrap, mergeComponent, ', '); + + scope.parseBox = parseBox; + scope.mergeBoxes = mergeBoxes; + + scope.addPropertiesHandler(parseBox, mergeBoxes, ['clip']); + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/color-handler.js b/scripts/resources/web-animations-js/src/color-handler.js new file mode 100644 index 0000000000..b32a889962 --- /dev/null +++ b/scripts/resources/web-animations-js/src/color-handler.js @@ -0,0 +1,62 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas'); + canvas.width = canvas.height = 1; + var context = canvas.getContext('2d'); + + function parseColor(string) { + string = string.trim(); + // The context ignores invalid colors + context.fillStyle = '#000'; + context.fillStyle = string; + var contextSerializedFillStyle = context.fillStyle; + context.fillStyle = '#fff'; + context.fillStyle = string; + if (contextSerializedFillStyle != context.fillStyle) + return; + context.fillRect(0, 0, 1, 1); + var pixelColor = context.getImageData(0, 0, 1, 1).data; + context.clearRect(0, 0, 1, 1); + var alpha = pixelColor[3] / 255; + return [pixelColor[0] * alpha, pixelColor[1] * alpha, pixelColor[2] * alpha, alpha]; + } + + function mergeColors(left, right) { + return [left, right, function(x) { + function clamp(v) { + return Math.max(0, Math.min(255, v)); + } + if (x[3]) { + for (var i = 0; i < 3; i++) + x[i] = Math.round(clamp(x[i] / x[3])); + } + x[3] = scope.numberToString(scope.clamp(0, 1, x[3])); + return 'rgba(' + x.join(',') + ')'; + }]; + } + + scope.addPropertiesHandler(parseColor, mergeColors, + ['background-color', 'border-bottom-color', 'border-left-color', 'border-right-color', + 'border-top-color', 'color', 'outline-color', 'text-decoration-color']); + scope.consumeColor = scope.consumeParenthesised.bind(null, parseColor); + scope.mergeColors = mergeColors; + + if (WEB_ANIMATIONS_TESTING) { + testing.parseColor = parseColor; + } + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/deprecation.js b/scripts/resources/web-animations-js/src/deprecation.js new file mode 100644 index 0000000000..3349937987 --- /dev/null +++ b/scripts/resources/web-animations-js/src/deprecation.js @@ -0,0 +1,43 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared) { + + var silenced = {}; + + shared.isDeprecated = function(feature, date, advice, plural) { + var auxVerb = plural ? 'are' : 'is'; + var today = new Date(); + var expiry = new Date(date); + expiry.setMonth(expiry.getMonth() + 3); // 3 months grace period + + if (today < expiry) { + if (!(feature in silenced)) { + console.warn('Web Animations: ' + feature + ' ' + auxVerb + ' deprecated and will stop working on ' + expiry.toDateString() + '. ' + advice); + } + silenced[feature] = true; + return false; + } else { + return true; + } + }; + + shared.deprecated = function(feature, date, advice, plural) { + var auxVerb = plural ? 'are' : 'is'; + if (shared.isDeprecated(feature, date, advice, plural)) { + throw new Error(feature + ' ' + auxVerb + ' no longer supported. ' + advice); + } + }; + +})(webAnimationsShared); diff --git a/scripts/resources/web-animations-js/src/dev.js b/scripts/resources/web-animations-js/src/dev.js new file mode 100644 index 0000000000..a5e225c08c --- /dev/null +++ b/scripts/resources/web-animations-js/src/dev.js @@ -0,0 +1,16 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var WEB_ANIMATIONS_TESTING = false; +var webAnimationsTesting = null; diff --git a/scripts/resources/web-animations-js/src/dimension-handler.js b/scripts/resources/web-animations-js/src/dimension-handler.js new file mode 100644 index 0000000000..66afe0d2e2 --- /dev/null +++ b/scripts/resources/web-animations-js/src/dimension-handler.js @@ -0,0 +1,167 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + function parseDimension(unitRegExp, string) { + string = string.trim().toLowerCase(); + + if (string == '0' && 'px'.search(unitRegExp) >= 0) + return {px: 0}; + + // If we have parenthesis, we're a calc and need to start with 'calc'. + if (!/^[^(]*$|^calc/.test(string)) + return; + string = string.replace(/calc\(/g, '('); + + // We tag units by prefixing them with 'U' (note that we are already + // lowercase) to prevent problems with types which are substrings of + // each other (although prefixes may be problematic!) + var matchedUnits = {}; + string = string.replace(unitRegExp, function(match) { + matchedUnits[match] = null; + return 'U' + match; + }); + var taggedUnitRegExp = 'U(' + unitRegExp.source + ')'; + + // Validating input is simply applying as many reductions as we can. + var typeCheck = string.replace(/[-+]?(\d*\.)?\d+/g, 'N') + .replace(new RegExp('N' + taggedUnitRegExp, 'g'), 'D') + .replace(/\s[+-]\s/g, 'O') + .replace(/\s/g, ''); + var reductions = [/N\*(D)/g, /(N|D)[*/]N/g, /(N|D)O\1/g, /\((N|D)\)/g]; + var i = 0; + while (i < reductions.length) { + if (reductions[i].test(typeCheck)) { + typeCheck = typeCheck.replace(reductions[i], '$1'); + i = 0; + } else { + i++; + } + } + if (typeCheck != 'D') + return; + + for (var unit in matchedUnits) { + var result = eval(string.replace(new RegExp('U' + unit, 'g'), '').replace(new RegExp(taggedUnitRegExp, 'g'), '*0')); + if (!isFinite(result)) + return; + matchedUnits[unit] = result; + } + return matchedUnits; + } + + function mergeDimensionsNonNegative(left, right) { + return mergeDimensions(left, right, true); + } + + function mergeDimensions(left, right, nonNegative) { + var units = [], unit; + for (unit in left) + units.push(unit); + for (unit in right) { + if (units.indexOf(unit) < 0) + units.push(unit); + } + + left = units.map(function(unit) { return left[unit] || 0; }); + right = units.map(function(unit) { return right[unit] || 0; }); + return [left, right, function(values) { + var result = values.map(function(value, i) { + if (values.length == 1 && nonNegative) { + value = Math.max(value, 0); + } + // Scientific notation (e.g. 1e2) is not yet widely supported by browser vendors. + return scope.numberToString(value) + units[i]; + }).join(' + '); + return values.length > 1 ? 'calc(' + result + ')' : result; + }]; + } + + var lengthUnits = 'px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc'; + var parseLength = parseDimension.bind(null, new RegExp(lengthUnits, 'g')); + var parseLengthOrPercent = parseDimension.bind(null, new RegExp(lengthUnits + '|%', 'g')); + var parseAngle = parseDimension.bind(null, /deg|rad|grad|turn/g); + + scope.parseLength = parseLength; + scope.parseLengthOrPercent = parseLengthOrPercent; + scope.consumeLengthOrPercent = scope.consumeParenthesised.bind(null, parseLengthOrPercent); + scope.parseAngle = parseAngle; + scope.mergeDimensions = mergeDimensions; + + var consumeLength = scope.consumeParenthesised.bind(null, parseLength); + var consumeSizePair = scope.consumeRepeated.bind(undefined, consumeLength, /^/); + var consumeSizePairList = scope.consumeRepeated.bind(undefined, consumeSizePair, /^,/); + scope.consumeSizePairList = consumeSizePairList; + + var parseSizePairList = function(input) { + var result = consumeSizePairList(input); + if (result && result[1] == '') { + return result[0]; + } + }; + + var mergeNonNegativeSizePair = scope.mergeNestedRepeated.bind(undefined, mergeDimensionsNonNegative, ' '); + var mergeNonNegativeSizePairList = scope.mergeNestedRepeated.bind(undefined, mergeNonNegativeSizePair, ','); + scope.mergeNonNegativeSizePair = mergeNonNegativeSizePair; + + scope.addPropertiesHandler(parseSizePairList, mergeNonNegativeSizePairList, [ + 'background-size' + ]); + + scope.addPropertiesHandler(parseLengthOrPercent, mergeDimensionsNonNegative, [ + 'border-bottom-width', + 'border-image-width', + 'border-left-width', + 'border-right-width', + 'border-top-width', + 'flex-basis', + 'font-size', + 'height', + 'line-height', + 'max-height', + 'max-width', + 'outline-width', + 'width', + ]); + + scope.addPropertiesHandler(parseLengthOrPercent, mergeDimensions, [ + 'border-bottom-left-radius', + 'border-bottom-right-radius', + 'border-top-left-radius', + 'border-top-right-radius', + 'bottom', + 'left', + 'letter-spacing', + 'margin-bottom', + 'margin-left', + 'margin-right', + 'margin-top', + 'min-height', + 'min-width', + 'outline-offset', + 'padding-bottom', + 'padding-left', + 'padding-right', + 'padding-top', + 'perspective', + 'right', + 'shape-margin', + 'text-indent', + 'top', + 'vertical-align', + 'word-spacing', + ]); + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/effect-callback.js b/scripts/resources/web-animations-js/src/effect-callback.js new file mode 100644 index 0000000000..f1a88dd112 --- /dev/null +++ b/scripts/resources/web-animations-js/src/effect-callback.js @@ -0,0 +1,98 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +(function(shared, scope, testing) { + + var nullTarget = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); + + var sequenceNumber = 0; + scope.bindAnimationForCustomEffect = function(animation) { + var target = animation.effect.target; + var effectFunction; + var isKeyframeEffect = typeof animation.effect.getFrames() == 'function'; + if (isKeyframeEffect) { + effectFunction = animation.effect.getFrames(); + } else { + effectFunction = animation.effect._onsample; + } + var timing = animation.effect.timing; + var last = null; + timing = shared.normalizeTimingInput(timing); + var callback = function() { + var t = callback._animation ? callback._animation.currentTime : null; + if (t !== null) { + t = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), t, timing); + if (isNaN(t)) + t = null; + } + // FIXME: There are actually more conditions under which the effectFunction + // should be called. + if (t !== last) { + if (isKeyframeEffect) { + effectFunction(t, target, animation.effect); + } else { + effectFunction(t, animation.effect, animation.effect._animation); + } + } + last = t; + }; + + callback._animation = animation; + callback._registered = false; + callback._sequenceNumber = sequenceNumber++; + animation._callback = callback; + register(callback); + }; + + var callbacks = []; + var ticking = false; + function register(callback) { + if (callback._registered) + return; + callback._registered = true; + callbacks.push(callback); + if (!ticking) { + ticking = true; + requestAnimationFrame(tick); + } + } + + function tick(t) { + var updating = callbacks; + callbacks = []; + updating.sort(function(left, right) { + return left._sequenceNumber - right._sequenceNumber; + }); + updating = updating.filter(function(callback) { + callback(); + var playState = callback._animation ? callback._animation.playState : 'idle'; + if (playState != 'running' && playState != 'pending') + callback._registered = false; + return callback._registered; + }); + callbacks.push.apply(callbacks, updating); + + if (callbacks.length) { + ticking = true; + requestAnimationFrame(tick); + } else { + ticking = false; + } + } + + scope.Animation.prototype._register = function() { + if (this._callback) + register(this._callback); + }; + +})(webAnimationsShared, webAnimationsNext, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/element-animatable.js b/scripts/resources/web-animations-js/src/element-animatable.js new file mode 100644 index 0000000000..6bcf1dce7a --- /dev/null +++ b/scripts/resources/web-animations-js/src/element-animatable.js @@ -0,0 +1,19 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + window.Element.prototype.animate = function(effectInput, timingInput) { + return scope.timeline._play(scope.KeyframeEffect(this, effectInput, timingInput)); + }; +})(webAnimations1); diff --git a/scripts/resources/web-animations-js/src/font-weight-handler.js b/scripts/resources/web-animations-js/src/font-weight-handler.js new file mode 100644 index 0000000000..4760486a66 --- /dev/null +++ b/scripts/resources/web-animations-js/src/font-weight-handler.js @@ -0,0 +1,42 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + function parse(string) { + var out = Number(string); + if (isNaN(out) || out < 100 || out > 900 || out % 100 !== 0) { + return; + } + return out; + } + + function toCss(value) { + value = Math.round(value / 100) * 100; + value = scope.clamp(100, 900, value); + if (value === 400) { + return 'normal'; + } + if (value === 700) { + return 'bold'; + } + return String(value); + } + + function merge(left, right) { + return [left, right, toCss]; + } + + scope.addPropertiesHandler(parse, merge, ['font-weight']); + +})(webAnimations1); diff --git a/scripts/resources/web-animations-js/src/group-constructors.js b/scripts/resources/web-animations-js/src/group-constructors.js new file mode 100644 index 0000000000..2457c22036 --- /dev/null +++ b/scripts/resources/web-animations-js/src/group-constructors.js @@ -0,0 +1,203 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + + function groupChildDuration(node) { + return node._timing.delay + node.activeDuration + node._timing.endDelay; + } + + function constructor(children, timingInput) { + this._parent = null; + this.children = children || []; + this._reparent(this.children); + timingInput = shared.numericTimingToObject(timingInput); + this._timingInput = shared.cloneTimingInput(timingInput); + this._timing = shared.normalizeTimingInput(timingInput, true); + this.timing = shared.makeTiming(timingInput, true, this); + this.timing._effect = this; + + if (this._timing.duration === 'auto') { + this._timing.duration = this.activeDuration; + } + } + + window.SequenceEffect = function() { + constructor.apply(this, arguments); + }; + + window.GroupEffect = function() { + constructor.apply(this, arguments); + }; + + constructor.prototype = { + _isAncestor: function(effect) { + var a = this; + while (a !== null) { + if (a == effect) + return true; + a = a._parent; + } + return false; + }, + _rebuild: function() { + // Re-calculate durations for ancestors with specified duration 'auto'. + var node = this; + while (node) { + if (node.timing.duration === 'auto') { + node._timing.duration = node.activeDuration; + } + node = node._parent; + } + if (this._animation) { + this._animation._rebuildUnderlyingAnimation(); + } + }, + _reparent: function(newChildren) { + scope.removeMulti(newChildren); + for (var i = 0; i < newChildren.length; i++) { + newChildren[i]._parent = this; + } + }, + _putChild: function(args, isAppend) { + var message = isAppend ? 'Cannot append an ancestor or self' : 'Cannot prepend an ancestor or self'; + for (var i = 0; i < args.length; i++) { + if (this._isAncestor(args[i])) { + throw { + type: DOMException.HIERARCHY_REQUEST_ERR, + name: 'HierarchyRequestError', + message: message + }; + } + } + var oldParents = []; + for (var i = 0; i < args.length; i++) { + isAppend ? this.children.push(args[i]) : this.children.unshift(args[i]); + } + this._reparent(args); + this._rebuild(); + }, + append: function() { + this._putChild(arguments, true); + }, + prepend: function() { + this._putChild(arguments, false); + }, + get parent() { + return this._parent; + }, + get firstChild() { + return this.children.length ? this.children[0] : null; + }, + get lastChild() { + return this.children.length ? this.children[this.children.length - 1] : null; + }, + clone: function() { + var clonedTiming = shared.cloneTimingInput(this._timingInput); + var clonedChildren = []; + for (var i = 0; i < this.children.length; i++) { + clonedChildren.push(this.children[i].clone()); + } + return (this instanceof GroupEffect) ? + new GroupEffect(clonedChildren, clonedTiming) : + new SequenceEffect(clonedChildren, clonedTiming); + }, + remove: function() { + scope.removeMulti([this]); + } + }; + + window.SequenceEffect.prototype = Object.create(constructor.prototype); + Object.defineProperty( + window.SequenceEffect.prototype, + 'activeDuration', + { + get: function() { + var total = 0; + this.children.forEach(function(child) { + total += groupChildDuration(child); + }); + return Math.max(total, 0); + } + }); + + window.GroupEffect.prototype = Object.create(constructor.prototype); + Object.defineProperty( + window.GroupEffect.prototype, + 'activeDuration', + { + get: function() { + var max = 0; + this.children.forEach(function(child) { + max = Math.max(max, groupChildDuration(child)); + }); + return max; + } + }); + + scope.newUnderlyingAnimationForGroup = function(group) { + var underlyingAnimation; + var timing = null; + var ticker = function(tf) { + var animation = underlyingAnimation._wrapper; + if (!animation) { + return; + } + if (animation.playState == 'pending') { + return; + } + if (!animation.effect) { + return; + } + if (tf == null) { + animation._removeChildAnimations(); + return; + } + + // If the group has a negative playback rate and is not fill backwards/both, then it should go + // out of effect when it reaches the start of its active interval (tf == 0). If it is fill + // backwards/both then it should stay in effect. calculateTimeFraction will return 0 in the + // backwards-filling case, and null otherwise. + if (tf == 0 && animation.playbackRate < 0) { + if (!timing) { + timing = shared.normalizeTimingInput(animation.effect.timing); + } + tf = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), -1, timing); + if (isNaN(tf) || tf == null) { + animation._forEachChild(function(child) { + child.currentTime = -1; + }); + animation._removeChildAnimations(); + return; + } + } + }; + + var underlyingEffect = new KeyframeEffect(null, [], group._timing); + underlyingEffect.onsample = ticker; + underlyingAnimation = scope.timeline._play(underlyingEffect); + return underlyingAnimation; + }; + + scope.bindAnimationForGroup = function(animation) { + animation._animation._wrapper = animation; + animation._isGroup = true; + scope.awaitStartTime(animation); + animation._constructChildAnimations(); + animation._setExternalAnimation(animation); + }; + + scope.groupChildDuration = groupChildDuration; + +})(webAnimationsShared, webAnimationsNext, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/handler-utils.js b/scripts/resources/web-animations-js/src/handler-utils.js new file mode 100644 index 0000000000..d9f05e17e9 --- /dev/null +++ b/scripts/resources/web-animations-js/src/handler-utils.js @@ -0,0 +1,177 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + + // consume* functions return a 2 value array of [parsed-data, '' or not-yet consumed input] + + // Regex should be anchored with /^ + function consumeToken(regex, string) { + var result = regex.exec(string); + if (result) { + result = regex.ignoreCase ? result[0].toLowerCase() : result[0]; + return [result, string.substr(result.length)]; + } + } + + function consumeTrimmed(consumer, string) { + string = string.replace(/^\s*/, ''); + var result = consumer(string); + if (result) { + return [result[0], result[1].replace(/^\s*/, '')]; + } + } + + function consumeRepeated(consumer, separator, string) { + consumer = consumeTrimmed.bind(null, consumer); + var list = []; + while (true) { + var result = consumer(string); + if (!result) { + return [list, string]; + } + list.push(result[0]); + string = result[1]; + result = consumeToken(separator, string); + if (!result || result[1] == '') { + return [list, string]; + } + string = result[1]; + } + } + + // Consumes a token or expression with balanced parentheses + function consumeParenthesised(parser, string) { + var nesting = 0; + for (var n = 0; n < string.length; n++) { + if (/\s|,/.test(string[n]) && nesting == 0) { + break; + } else if (string[n] == '(') { + nesting++; + } else if (string[n] == ')') { + nesting--; + if (nesting == 0) + n++; + if (nesting <= 0) + break; + } + } + var parsed = parser(string.substr(0, n)); + return parsed == undefined ? undefined : [parsed, string.substr(n)]; + } + + function lcm(a, b) { + var c = a; + var d = b; + while (c && d) + c > d ? c %= d : d %= c; + c = (a * b) / (c + d); + return c; + } + + function ignore(value) { + return function(input) { + var result = value(input); + if (result) + result[0] = undefined; + return result; + } + } + + function optional(value, defaultValue) { + return function(input) { + var result = value(input); + if (result) + return result; + return [defaultValue, input]; + } + } + + function consumeList(list, input) { + var output = []; + for (var i = 0; i < list.length; i++) { + var result = scope.consumeTrimmed(list[i], input); + if (!result || result[0] == '') + return; + if (result[0] !== undefined) + output.push(result[0]); + input = result[1]; + } + if (input == '') { + return output; + } + } + + function mergeWrappedNestedRepeated(wrap, nestedMerge, separator, left, right) { + var matchingLeft = []; + var matchingRight = []; + var reconsititution = []; + var length = lcm(left.length, right.length); + for (var i = 0; i < length; i++) { + var thing = nestedMerge(left[i % left.length], right[i % right.length]); + if (!thing) { + return; + } + matchingLeft.push(thing[0]); + matchingRight.push(thing[1]); + reconsititution.push(thing[2]); + } + return [matchingLeft, matchingRight, function(positions) { + var result = positions.map(function(position, i) { + return reconsititution[i](position); + }).join(separator); + return wrap ? wrap(result) : result; + }]; + } + + function mergeList(left, right, list) { + var lefts = []; + var rights = []; + var functions = []; + var j = 0; + for (var i = 0; i < list.length; i++) { + if (typeof list[i] == 'function') { + var result = list[i](left[j], right[j++]); + lefts.push(result[0]); + rights.push(result[1]); + functions.push(result[2]); + } else { + (function(pos) { + lefts.push(false); + rights.push(false); + functions.push(function() { return list[pos]; }); + })(i); + } + } + return [lefts, rights, function(results) { + var result = ''; + for (var i = 0; i < results.length; i++) { + result += functions[i](results[i]); + } + return result; + }]; + } + + scope.consumeToken = consumeToken; + scope.consumeTrimmed = consumeTrimmed; + scope.consumeRepeated = consumeRepeated; + scope.consumeParenthesised = consumeParenthesised; + scope.ignore = ignore; + scope.optional = optional; + scope.consumeList = consumeList; + scope.mergeNestedRepeated = mergeWrappedNestedRepeated.bind(null, null); + scope.mergeWrappedNestedRepeated = mergeWrappedNestedRepeated; + scope.mergeList = mergeList; + +})(webAnimations1); diff --git a/scripts/resources/web-animations-js/src/interpolation.js b/scripts/resources/web-animations-js/src/interpolation.js new file mode 100644 index 0000000000..ba63ed358f --- /dev/null +++ b/scripts/resources/web-animations-js/src/interpolation.js @@ -0,0 +1,49 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + function interpolate(from, to, f) { + if ((typeof from == 'number') && (typeof to == 'number')) { + return from * (1 - f) + to * f; + } + if ((typeof from == 'boolean') && (typeof to == 'boolean')) { + return f < 0.5 ? from : to; + } + + WEB_ANIMATIONS_TESTING && console.assert( + Array.isArray(from) && Array.isArray(to), + 'If interpolation arguments are not numbers or bools they must be arrays'); + + if (from.length == to.length) { + var r = []; + for (var i = 0; i < from.length; i++) { + r.push(interpolate(from[i], to[i], f)); + } + return r; + } + throw 'Mismatched interpolation arguments ' + from + ':' + to; + } + + scope.Interpolation = function(from, to, convertToString) { + return function(f) { + return convertToString(interpolate(from, to, f)); + } + }; + + if (WEB_ANIMATIONS_TESTING) { + testing.interpolate = interpolate; + } + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/keyframe-effect-constructor.js b/scripts/resources/web-animations-js/src/keyframe-effect-constructor.js new file mode 100644 index 0000000000..f906b14bc8 --- /dev/null +++ b/scripts/resources/web-animations-js/src/keyframe-effect-constructor.js @@ -0,0 +1,177 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + + var disassociate = function(effect) { + effect._animation = undefined; + if (effect instanceof window.SequenceEffect || effect instanceof window.GroupEffect) { + for (var i = 0; i < effect.children.length; i++) { + disassociate(effect.children[i]); + } + } + }; + + scope.removeMulti = function(effects) { + var oldParents = []; + for (var i = 0; i < effects.length; i++) { + var effect = effects[i]; + if (effect._parent) { + if (oldParents.indexOf(effect._parent) == -1) { + oldParents.push(effect._parent); + } + effect._parent.children.splice(effect._parent.children.indexOf(effect), 1); + effect._parent = null; + disassociate(effect); + } else if (effect._animation && (effect._animation.effect == effect)) { + effect._animation.cancel(); + effect._animation.effect = new KeyframeEffect(null, []); + if (effect._animation._callback) { + effect._animation._callback._animation = null; + } + effect._animation._rebuildUnderlyingAnimation(); + disassociate(effect); + } + } + for (i = 0; i < oldParents.length; i++) { + oldParents[i]._rebuild(); + } + }; + + function KeyframeList(effectInput) { + this._frames = shared.normalizeKeyframes(effectInput); + } + + scope.KeyframeEffect = function(target, effectInput, timingInput) { + this.target = target; + this._parent = null; + + timingInput = shared.numericTimingToObject(timingInput); + this._timingInput = shared.cloneTimingInput(timingInput); + this._timing = shared.normalizeTimingInput(timingInput); + + this.timing = shared.makeTiming(timingInput, false, this); + this.timing._effect = this; + if (typeof effectInput == 'function') { + shared.deprecated('Custom KeyframeEffect', '2015-06-22', 'Use KeyframeEffect.onsample instead.'); + this._normalizedKeyframes = effectInput; + } else { + this._normalizedKeyframes = new KeyframeList(effectInput); + } + this._keyframes = effectInput; + this.activeDuration = shared.calculateActiveDuration(this._timing); + return this; + }; + + scope.KeyframeEffect.prototype = { + getFrames: function() { + if (typeof this._normalizedKeyframes == 'function') + return this._normalizedKeyframes; + return this._normalizedKeyframes._frames; + }, + set onsample(callback) { + if (typeof this.getFrames() == 'function') { + throw new Error('Setting onsample on custom effect KeyframeEffect is not supported.'); + } + this._onsample = callback; + if (this._animation) { + this._animation._rebuildUnderlyingAnimation(); + } + }, + get parent() { + return this._parent; + }, + clone: function() { + if (typeof this.getFrames() == 'function') { + throw new Error('Cloning custom effects is not supported.'); + } + var clone = new KeyframeEffect(this.target, [], shared.cloneTimingInput(this._timingInput)); + clone._normalizedKeyframes = this._normalizedKeyframes; + clone._keyframes = this._keyframes; + return clone; + }, + remove: function() { + scope.removeMulti([this]); + } + }; + + var originalElementAnimate = Element.prototype.animate; + Element.prototype.animate = function(effectInput, timing) { + return scope.timeline._play(new scope.KeyframeEffect(this, effectInput, timing)); + }; + + var nullTarget = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); + scope.newUnderlyingAnimationForKeyframeEffect = function(keyframeEffect) { + if (keyframeEffect) { + var target = keyframeEffect.target || nullTarget; + var keyframes = keyframeEffect._keyframes; + if (typeof keyframes == 'function') { + keyframes = []; + } + var timing = keyframeEffect._timingInput; + } else { + var target = nullTarget; + var keyframes = []; + var timing = 0; + } + return originalElementAnimate.apply(target, [keyframes, timing]); + }; + + // TODO: Remove this once we remove support for custom KeyframeEffects. + scope.bindAnimationForKeyframeEffect = function(animation) { + if (animation.effect && typeof animation.effect._normalizedKeyframes == 'function') { + scope.bindAnimationForCustomEffect(animation); + } + }; + + var pendingGroups = []; + scope.awaitStartTime = function(groupAnimation) { + if (groupAnimation.startTime !== null || !groupAnimation._isGroup) + return; + if (pendingGroups.length == 0) { + requestAnimationFrame(updatePendingGroups); + } + pendingGroups.push(groupAnimation); + }; + function updatePendingGroups() { + var updated = false; + while (pendingGroups.length) { + var group = pendingGroups.shift(); + group._updateChildren(); + updated = true; + } + return updated; + } + var originalGetComputedStyle = window.getComputedStyle; + Object.defineProperty(window, 'getComputedStyle', { + configurable: true, + enumerable: true, + value: function() { + window.document.timeline._updateAnimationsPromises(); + var result = originalGetComputedStyle.apply(this, arguments); + if (updatePendingGroups()) + result = originalGetComputedStyle.apply(this, arguments); + window.document.timeline._updateAnimationsPromises(); + return result; + }, + }); + + window.KeyframeEffect = scope.KeyframeEffect; + window.Element.prototype.getAnimations = function() { + return document.timeline.getAnimations().filter(function(animation) { + return animation.effect !== null && animation.effect.target == this; + }.bind(this)); + }; + +}(webAnimationsShared, webAnimationsNext, webAnimationsTesting)); diff --git a/scripts/resources/web-animations-js/src/keyframe-effect.js b/scripts/resources/web-animations-js/src/keyframe-effect.js new file mode 100644 index 0000000000..c910d35e03 --- /dev/null +++ b/scripts/resources/web-animations-js/src/keyframe-effect.js @@ -0,0 +1,80 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + + function EffectTime(timing) { + var timeFraction = 0; + var activeDuration = shared.calculateActiveDuration(timing); + var effectTime = function(localTime) { + return shared.calculateTimeFraction(activeDuration, localTime, timing); + }; + effectTime._totalDuration = timing.delay + activeDuration + timing.endDelay; + effectTime._isCurrent = function(localTime) { + var phase = shared.calculatePhase(activeDuration, localTime, timing); + return phase === PhaseActive || phase === PhaseBefore; + }; + return effectTime; + } + + scope.KeyframeEffect = function(target, effectInput, timingInput) { + var effectTime = EffectTime(shared.normalizeTimingInput(timingInput)); + var interpolations = scope.convertEffectInput(effectInput); + var timeFraction; + var keyframeEffect = function() { + WEB_ANIMATIONS_TESTING && console.assert(typeof timeFraction !== 'undefined'); + interpolations(target, timeFraction); + }; + // Returns whether the keyframeEffect is in effect or not after the timing update. + keyframeEffect._update = function(localTime) { + timeFraction = effectTime(localTime); + return timeFraction !== null; + }; + keyframeEffect._clear = function() { + interpolations(target, null); + }; + keyframeEffect._hasSameTarget = function(otherTarget) { + return target === otherTarget; + }; + keyframeEffect._isCurrent = effectTime._isCurrent; + keyframeEffect._totalDuration = effectTime._totalDuration; + return keyframeEffect; + }; + + scope.NullEffect = function(clear) { + var nullEffect = function() { + if (clear) { + clear(); + clear = null; + } + }; + nullEffect._update = function() { + return null; + }; + nullEffect._totalDuration = 0; + nullEffect._isCurrent = function() { + return false; + }; + nullEffect._hasSameTarget = function() { + return false; + }; + return nullEffect; + }; + + if (WEB_ANIMATIONS_TESTING) { + testing.webAnimations1KeyframeEffect = scope.KeyframeEffect; + testing.effectTime = EffectTime; + } + +})(webAnimationsShared, webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/keyframe-interpolations.js b/scripts/resources/web-animations-js/src/keyframe-interpolations.js new file mode 100644 index 0000000000..cdd6fc2bef --- /dev/null +++ b/scripts/resources/web-animations-js/src/keyframe-interpolations.js @@ -0,0 +1,110 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + + scope.convertEffectInput = function(effectInput) { + var keyframes = shared.normalizeKeyframes(effectInput); + var propertySpecificKeyframeGroups = makePropertySpecificKeyframeGroups(keyframes); + var interpolations = makeInterpolations(propertySpecificKeyframeGroups); + return function(target, fraction) { + if (fraction != null) { + interpolations.filter(function(interpolation) { + return (fraction <= 0 && interpolation.startTime == 0) || + (fraction >= 1 && interpolation.endTime == 1) || + (fraction >= interpolation.startTime && fraction <= interpolation.endTime); + }).forEach(function(interpolation) { + var offsetFraction = fraction - interpolation.startTime; + var localDuration = interpolation.endTime - interpolation.startTime; + var scaledLocalTime = localDuration == 0 ? 0 : interpolation.easing(offsetFraction / localDuration); + scope.apply(target, interpolation.property, interpolation.interpolation(scaledLocalTime)); + }); + } else { + for (var property in propertySpecificKeyframeGroups) + if (property != 'offset' && property != 'easing' && property != 'composite') + scope.clear(target, property); + } + }; + }; + + + function makePropertySpecificKeyframeGroups(keyframes) { + var propertySpecificKeyframeGroups = {}; + + for (var i = 0; i < keyframes.length; i++) { + for (var member in keyframes[i]) { + if (member != 'offset' && member != 'easing' && member != 'composite') { + var propertySpecificKeyframe = { + offset: keyframes[i].offset, + easing: keyframes[i].easing, + value: keyframes[i][member] + }; + propertySpecificKeyframeGroups[member] = propertySpecificKeyframeGroups[member] || []; + propertySpecificKeyframeGroups[member].push(propertySpecificKeyframe); + } + } + } + + for (var groupName in propertySpecificKeyframeGroups) { + var group = propertySpecificKeyframeGroups[groupName]; + if (group[0].offset != 0 || group[group.length - 1].offset != 1) { + throw { + type: DOMException.NOT_SUPPORTED_ERR, + name: 'NotSupportedError', + message: 'Partial keyframes are not supported' + }; + } + } + return propertySpecificKeyframeGroups; + } + + + function makeInterpolations(propertySpecificKeyframeGroups) { + var interpolations = []; + for (var groupName in propertySpecificKeyframeGroups) { + var group = propertySpecificKeyframeGroups[groupName]; + for (var i = 0; i < group.length - 1; i++) { + var startTime = group[i].offset; + var endTime = group[i + 1].offset; + var startValue = group[i].value; + var endValue = group[i + 1].value; + if (startTime == endTime) { + if (endTime == 1) { + startValue = endValue; + } else { + endValue = startValue; + } + } + interpolations.push({ + startTime: startTime, + endTime: endTime, + easing: group[i].easing, + property: groupName, + interpolation: scope.propertyInterpolation(groupName, startValue, endValue) + }); + } + } + interpolations.sort(function(leftInterpolation, rightInterpolation) { + return leftInterpolation.startTime - rightInterpolation.startTime; + }); + return interpolations; + } + + + if (WEB_ANIMATIONS_TESTING) { + testing.makePropertySpecificKeyframeGroups = makePropertySpecificKeyframeGroups; + testing.makeInterpolations = makeInterpolations; + } + +})(webAnimationsShared, webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/matrix-decomposition.js b/scripts/resources/web-animations-js/src/matrix-decomposition.js new file mode 100644 index 0000000000..4ba99deaca --- /dev/null +++ b/scripts/resources/web-animations-js/src/matrix-decomposition.js @@ -0,0 +1,446 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + var decomposeMatrix = (function() { + function determinant(m) { + return m[0][0] * m[1][1] * m[2][2] + + m[1][0] * m[2][1] * m[0][2] + + m[2][0] * m[0][1] * m[1][2] - + m[0][2] * m[1][1] * m[2][0] - + m[1][2] * m[2][1] * m[0][0] - + m[2][2] * m[0][1] * m[1][0]; + } + + // from Wikipedia: + // + // [A B]^-1 = [A^-1 + A^-1B(D - CA^-1B)^-1CA^-1 -A^-1B(D - CA^-1B)^-1] + // [C D] [-(D - CA^-1B)^-1CA^-1 (D - CA^-1B)^-1 ] + // + // Therefore + // + // [A [0]]^-1 = [A^-1 [0]] + // [C 1 ] [ -CA^-1 1 ] + function inverse(m) { + var iDet = 1 / determinant(m); + var a = m[0][0], b = m[0][1], c = m[0][2]; + var d = m[1][0], e = m[1][1], f = m[1][2]; + var g = m[2][0], h = m[2][1], k = m[2][2]; + var Ainv = [ + [(e * k - f * h) * iDet, (c * h - b * k) * iDet, + (b * f - c * e) * iDet, 0], + [(f * g - d * k) * iDet, (a * k - c * g) * iDet, + (c * d - a * f) * iDet, 0], + [(d * h - e * g) * iDet, (g * b - a * h) * iDet, + (a * e - b * d) * iDet, 0] + ]; + var lastRow = []; + for (var i = 0; i < 3; i++) { + var val = 0; + for (var j = 0; j < 3; j++) { + val += m[3][j] * Ainv[j][i]; + } + lastRow.push(val); + } + lastRow.push(1); + Ainv.push(lastRow); + return Ainv; + } + + function transposeMatrix4(m) { + return [[m[0][0], m[1][0], m[2][0], m[3][0]], + [m[0][1], m[1][1], m[2][1], m[3][1]], + [m[0][2], m[1][2], m[2][2], m[3][2]], + [m[0][3], m[1][3], m[2][3], m[3][3]]]; + } + + function multVecMatrix(v, m) { + var result = []; + for (var i = 0; i < 4; i++) { + var val = 0; + for (var j = 0; j < 4; j++) { + val += v[j] * m[j][i]; + } + result.push(val); + } + return result; + } + + function normalize(v) { + var len = length(v); + return [v[0] / len, v[1] / len, v[2] / len]; + } + + function length(v) { + return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + } + + function combine(v1, v2, v1s, v2s) { + return [v1s * v1[0] + v2s * v2[0], v1s * v1[1] + v2s * v2[1], + v1s * v1[2] + v2s * v2[2]]; + } + + function cross(v1, v2) { + return [v1[1] * v2[2] - v1[2] * v2[1], + v1[2] * v2[0] - v1[0] * v2[2], + v1[0] * v2[1] - v1[1] * v2[0]]; + } + + function decomposeMatrix(matrix) { + var m3d = [ + matrix.slice(0, 4), + matrix.slice(4, 8), + matrix.slice(8, 12), + matrix.slice(12, 16) + ]; + + // skip normalization step as m3d[3][3] should always be 1 + if (m3d[3][3] !== 1) { + return null; + } + + var perspectiveMatrix = []; + for (var i = 0; i < 4; i++) { + perspectiveMatrix.push(m3d[i].slice()); + } + + for (var i = 0; i < 3; i++) { + perspectiveMatrix[i][3] = 0; + } + + if (determinant(perspectiveMatrix) === 0) { + return false; + } + + var rhs = []; + + var perspective; + if (m3d[0][3] || m3d[1][3] || m3d[2][3]) { + rhs.push(m3d[0][3]); + rhs.push(m3d[1][3]); + rhs.push(m3d[2][3]); + rhs.push(m3d[3][3]); + + var inversePerspectiveMatrix = inverse(perspectiveMatrix); + var transposedInversePerspectiveMatrix = + transposeMatrix4(inversePerspectiveMatrix); + perspective = multVecMatrix(rhs, transposedInversePerspectiveMatrix); + } else { + perspective = [0, 0, 0, 1]; + } + + var translate = m3d[3].slice(0, 3); + + var row = []; + row.push(m3d[0].slice(0, 3)); + var scale = []; + scale.push(length(row[0])); + row[0] = normalize(row[0]); + + var skew = []; + row.push(m3d[1].slice(0, 3)); + skew.push(dot(row[0], row[1])); + row[1] = combine(row[1], row[0], 1.0, -skew[0]); + + scale.push(length(row[1])); + row[1] = normalize(row[1]); + skew[0] /= scale[1]; + + row.push(m3d[2].slice(0, 3)); + skew.push(dot(row[0], row[2])); + row[2] = combine(row[2], row[0], 1.0, -skew[1]); + skew.push(dot(row[1], row[2])); + row[2] = combine(row[2], row[1], 1.0, -skew[2]); + + scale.push(length(row[2])); + row[2] = normalize(row[2]); + skew[1] /= scale[2]; + skew[2] /= scale[2]; + + var pdum3 = cross(row[1], row[2]); + if (dot(row[0], pdum3) < 0) { + for (var i = 0; i < 3; i++) { + scale[i] *= -1; + row[i][0] *= -1; + row[i][1] *= -1; + row[i][2] *= -1; + } + } + + var t = row[0][0] + row[1][1] + row[2][2] + 1; + var s; + var quaternion; + + if (t > 1e-4) { + s = 0.5 / Math.sqrt(t); + quaternion = [ + (row[2][1] - row[1][2]) * s, + (row[0][2] - row[2][0]) * s, + (row[1][0] - row[0][1]) * s, + 0.25 / s + ]; + } else if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) { + s = Math.sqrt(1 + row[0][0] - row[1][1] - row[2][2]) * 2.0; + quaternion = [ + 0.25 * s, + (row[0][1] + row[1][0]) / s, + (row[0][2] + row[2][0]) / s, + (row[2][1] - row[1][2]) / s + ]; + } else if (row[1][1] > row[2][2]) { + s = Math.sqrt(1.0 + row[1][1] - row[0][0] - row[2][2]) * 2.0; + quaternion = [ + (row[0][1] + row[1][0]) / s, + 0.25 * s, + (row[1][2] + row[2][1]) / s, + (row[0][2] - row[2][0]) / s + ]; + } else { + s = Math.sqrt(1.0 + row[2][2] - row[0][0] - row[1][1]) * 2.0; + quaternion = [ + (row[0][2] + row[2][0]) / s, + (row[1][2] + row[2][1]) / s, + 0.25 * s, + (row[1][0] - row[0][1]) / s + ]; + } + + return [translate, scale, skew, quaternion, perspective]; + } + return decomposeMatrix; + })(); + + function dot(v1, v2) { + var result = 0; + for (var i = 0; i < v1.length; i++) { + result += v1[i] * v2[i]; + } + return result; + } + + function multiplyMatrices(a, b) { + return [ + a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3], + a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3], + a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3], + a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3], + + a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7], + a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7], + a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7], + a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7], + + a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11], + a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11], + a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11], + a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11], + + a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15], + a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15], + a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15], + a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15] + ]; + } + + function convertItemToMatrix(item) { + switch (item.t) { + case 'rotatex': + var rads = item.d[0].rad || 0; + var degs = item.d[0].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + return [1, 0, 0, 0, + 0, Math.cos(angle), Math.sin(angle), 0, + 0, -Math.sin(angle), Math.cos(angle), 0, + 0, 0, 0, 1]; + case 'rotatey': + var rads = item.d[0].rad || 0; + var degs = item.d[0].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + return [Math.cos(angle), 0, -Math.sin(angle), 0, + 0, 1, 0, 0, + Math.sin(angle), 0, Math.cos(angle), 0, + 0, 0, 0, 1]; + case 'rotate': + case 'rotatez': + var rads = item.d[0].rad || 0; + var degs = item.d[0].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + return [Math.cos(angle), Math.sin(angle), 0, 0, + -Math.sin(angle), Math.cos(angle), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'rotate3d': + var x = item.d[0]; + var y = item.d[1]; + var z = item.d[2]; + var rads = item.d[3].rad || 0; + var degs = item.d[3].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + + var sqrLength = x * x + y * y + z * z; + if (sqrLength === 0) { + x = 1; + y = 0; + z = 0; + } else if (sqrLength !== 1) { + var length = Math.sqrt(sqrLength); + x /= length; + y /= length; + z /= length; + } + + var s = Math.sin(angle / 2); + var sc = s * Math.cos(angle / 2); + var sq = s * s; + return [ + 1 - 2 * (y * y + z * z) * sq, + 2 * (x * y * sq + z * sc), + 2 * (x * z * sq - y * sc), + 0, + + 2 * (x * y * sq - z * sc), + 1 - 2 * (x * x + z * z) * sq, + 2 * (y * z * sq + x * sc), + 0, + + 2 * (x * z * sq + y * sc), + 2 * (y * z * sq - x * sc), + 1 - 2 * (x * x + y * y) * sq, + 0, + + 0, 0, 0, 1 + ]; + case 'scale': + return [item.d[0], 0, 0, 0, + 0, item.d[1], 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'scalex': + return [item.d[0], 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'scaley': + return [1, 0, 0, 0, + 0, item.d[0], 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'scalez': + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, item.d[0], 0, + 0, 0, 0, 1]; + case 'scale3d': + return [item.d[0], 0, 0, 0, + 0, item.d[1], 0, 0, + 0, 0, item.d[2], 0, + 0, 0, 0, 1]; + case 'skew': + var xDegs = item.d[0].deg || 0; + var xRads = item.d[0].rad || 0; + var yDegs = item.d[1].deg || 0; + var yRads = item.d[1].rad || 0; + var xAngle = (xDegs * Math.PI / 180) + xRads; + var yAngle = (yDegs * Math.PI / 180) + yRads; + return [1, Math.tan(yAngle), 0, 0, + Math.tan(xAngle), 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'skewx': + var rads = item.d[0].rad || 0; + var degs = item.d[0].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + return [1, 0, 0, 0, + Math.tan(angle), 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'skewy': + var rads = item.d[0].rad || 0; + var degs = item.d[0].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + return [1, Math.tan(angle), 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'translate': + var x = item.d[0].px || 0; + var y = item.d[1].px || 0; + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, y, 0, 1]; + case 'translatex': + var x = item.d[0].px || 0; + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, 0, 0, 1]; + case 'translatey': + var y = item.d[0].px || 0; + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, y, 0, 1]; + case 'translatez': + var z = item.d[0].px || 0; + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, z, 1]; + case 'translate3d': + var x = item.d[0].px || 0; + var y = item.d[1].px || 0; + var z = item.d[2].px || 0; + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, y, z, 1]; + case 'perspective': + var p = item.d[0].px ? (-1 / item.d[0].px) : 0; + return [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, p, + 0, 0, 0, 1]; + case 'matrix': + return [item.d[0], item.d[1], 0, 0, + item.d[2], item.d[3], 0, 0, + 0, 0, 1, 0, + item.d[4], item.d[5], 0, 1]; + case 'matrix3d': + return item.d; + default: + WEB_ANIMATIONS_TESTING && console.assert(false, 'Transform item type ' + item.t + + ' conversion to matrix not yet implemented.'); + } + } + + function convertToMatrix(transformList) { + if (transformList.length === 0) { + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + } + return transformList.map(convertItemToMatrix).reduce(multiplyMatrices); + } + + function makeMatrixDecomposition(transformList) { + return [decomposeMatrix(convertToMatrix(transformList))]; + } + + scope.dot = dot; + scope.makeMatrixDecomposition = makeMatrixDecomposition; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/matrix-interpolation.js b/scripts/resources/web-animations-js/src/matrix-interpolation.js new file mode 100644 index 0000000000..9a35de3bef --- /dev/null +++ b/scripts/resources/web-animations-js/src/matrix-interpolation.js @@ -0,0 +1,130 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + var composeMatrix = (function() { + function multiply(a, b) { + var result = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]; + for (var i = 0; i < 4; i++) { + for (var j = 0; j < 4; j++) { + for (var k = 0; k < 4; k++) { + result[i][j] += b[i][k] * a[k][j]; + } + } + } + return result; + } + + function is2D(m) { + return ( + m[0][2] == 0 && + m[0][3] == 0 && + m[1][2] == 0 && + m[1][3] == 0 && + m[2][0] == 0 && + m[2][1] == 0 && + m[2][2] == 1 && + m[2][3] == 0 && + m[3][2] == 0 && + m[3][3] == 1); + } + + function composeMatrix(translate, scale, skew, quat, perspective) { + var matrix = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; + + for (var i = 0; i < 4; i++) { + matrix[i][3] = perspective[i]; + } + + for (var i = 0; i < 3; i++) { + for (var j = 0; j < 3; j++) { + matrix[3][i] += translate[j] * matrix[j][i]; + } + } + + var x = quat[0], y = quat[1], z = quat[2], w = quat[3]; + + var rotMatrix = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; + + rotMatrix[0][0] = 1 - 2 * (y * y + z * z); + rotMatrix[0][1] = 2 * (x * y - z * w); + rotMatrix[0][2] = 2 * (x * z + y * w); + rotMatrix[1][0] = 2 * (x * y + z * w); + rotMatrix[1][1] = 1 - 2 * (x * x + z * z); + rotMatrix[1][2] = 2 * (y * z - x * w); + rotMatrix[2][0] = 2 * (x * z - y * w); + rotMatrix[2][1] = 2 * (y * z + x * w); + rotMatrix[2][2] = 1 - 2 * (x * x + y * y); + + matrix = multiply(matrix, rotMatrix); + + var temp = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; + if (skew[2]) { + temp[2][1] = skew[2]; + matrix = multiply(matrix, temp); + } + + if (skew[1]) { + temp[2][1] = 0; + temp[2][0] = skew[0]; + matrix = multiply(matrix, temp); + } + + if (skew[0]) { + temp[2][0] = 0; + temp[1][0] = skew[0]; + matrix = multiply(matrix, temp); + } + + for (var i = 0; i < 3; i++) { + for (var j = 0; j < 3; j++) { + matrix[i][j] *= scale[i]; + } + } + + if (is2D(matrix)) { + return [matrix[0][0], matrix[0][1], matrix[1][0], matrix[1][1], matrix[3][0], matrix[3][1]]; + } + return matrix[0].concat(matrix[1], matrix[2], matrix[3]); + } + return composeMatrix; + })(); + + function clamp(x, min, max) { + return Math.max(Math.min(x, max), min); + }; + + function quat(fromQ, toQ, f) { + var product = scope.dot(fromQ, toQ); + product = clamp(product, -1.0, 1.0); + + var quat = []; + if (product === 1.0) { + quat = fromQ; + } else { + var theta = Math.acos(product); + var w = Math.sin(f * theta) * 1 / Math.sqrt(1 - product * product); + + for (var i = 0; i < 4; i++) { + quat.push(fromQ[i] * (Math.cos(f * theta) - product * w) + + toQ[i] * w); + } + } + return quat; + } + + scope.composeMatrix = composeMatrix; + scope.quat = quat; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/normalize-keyframes.js b/scripts/resources/web-animations-js/src/normalize-keyframes.js new file mode 100644 index 0000000000..dbab8bf87a --- /dev/null +++ b/scripts/resources/web-animations-js/src/normalize-keyframes.js @@ -0,0 +1,259 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, testing) { + var shorthandToLonghand = { + background: [ + 'backgroundImage', + 'backgroundPosition', + 'backgroundSize', + 'backgroundRepeat', + 'backgroundAttachment', + 'backgroundOrigin', + 'backgroundClip', + 'backgroundColor' + ], + border: [ + 'borderTopColor', + 'borderTopStyle', + 'borderTopWidth', + 'borderRightColor', + 'borderRightStyle', + 'borderRightWidth', + 'borderBottomColor', + 'borderBottomStyle', + 'borderBottomWidth', + 'borderLeftColor', + 'borderLeftStyle', + 'borderLeftWidth' + ], + borderBottom: [ + 'borderBottomWidth', + 'borderBottomStyle', + 'borderBottomColor' + ], + borderColor: [ + 'borderTopColor', + 'borderRightColor', + 'borderBottomColor', + 'borderLeftColor' + ], + borderLeft: [ + 'borderLeftWidth', + 'borderLeftStyle', + 'borderLeftColor' + ], + borderRadius: [ + 'borderTopLeftRadius', + 'borderTopRightRadius', + 'borderBottomRightRadius', + 'borderBottomLeftRadius' + ], + borderRight: [ + 'borderRightWidth', + 'borderRightStyle', + 'borderRightColor' + ], + borderTop: [ + 'borderTopWidth', + 'borderTopStyle', + 'borderTopColor' + ], + borderWidth: [ + 'borderTopWidth', + 'borderRightWidth', + 'borderBottomWidth', + 'borderLeftWidth' + ], + flex: [ + 'flexGrow', + 'flexShrink', + 'flexBasis' + ], + font: [ + 'fontFamily', + 'fontSize', + 'fontStyle', + 'fontVariant', + 'fontWeight', + 'lineHeight' + ], + margin: [ + 'marginTop', + 'marginRight', + 'marginBottom', + 'marginLeft' + ], + outline: [ + 'outlineColor', + 'outlineStyle', + 'outlineWidth' + ], + padding: [ + 'paddingTop', + 'paddingRight', + 'paddingBottom', + 'paddingLeft' + ] + }; + + var shorthandExpanderElem = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); + + var borderWidthAliases = { + thin: '1px', + medium: '3px', + thick: '5px' + }; + + var aliases = { + borderBottomWidth: borderWidthAliases, + borderLeftWidth: borderWidthAliases, + borderRightWidth: borderWidthAliases, + borderTopWidth: borderWidthAliases, + fontSize: { + 'xx-small': '60%', + 'x-small': '75%', + 'small': '89%', + 'medium': '100%', + 'large': '120%', + 'x-large': '150%', + 'xx-large': '200%' + }, + fontWeight: { + normal: '400', + bold: '700' + }, + outlineWidth: borderWidthAliases, + textShadow: { + none: '0px 0px 0px transparent' + }, + boxShadow: { + none: '0px 0px 0px 0px transparent' + } + }; + + function antiAlias(property, value) { + if (property in aliases) { + return aliases[property][value] || value; + } + return value; + } + + // This delegates parsing shorthand value syntax to the browser. + function expandShorthandAndAntiAlias(property, value, result) { + var longProperties = shorthandToLonghand[property]; + if (longProperties) { + shorthandExpanderElem.style[property] = value; + for (var i in longProperties) { + var longProperty = longProperties[i]; + var longhandValue = shorthandExpanderElem.style[longProperty]; + result[longProperty] = antiAlias(longProperty, longhandValue); + } + } else { + result[property] = antiAlias(property, value); + } + }; + + function normalizeKeyframes(effectInput) { + if (!Array.isArray(effectInput) && effectInput !== null) + throw new TypeError('Keyframes must be null or an array of keyframes'); + + if (effectInput == null) + return []; + + var keyframes = effectInput.map(function(originalKeyframe) { + var keyframe = {}; + for (var member in originalKeyframe) { + var memberValue = originalKeyframe[member]; + if (member == 'offset') { + if (memberValue != null) { + memberValue = Number(memberValue); + if (!isFinite(memberValue)) + throw new TypeError('keyframe offsets must be numbers.'); + } + } else if (member == 'composite') { + throw { + type: DOMException.NOT_SUPPORTED_ERR, + name: 'NotSupportedError', + message: 'add compositing is not supported' + }; + } else if (member == 'easing') { + memberValue = shared.toTimingFunction(memberValue); + } else { + memberValue = '' + memberValue; + } + expandShorthandAndAntiAlias(member, memberValue, keyframe); + } + if (keyframe.offset == undefined) + keyframe.offset = null; + if (keyframe.easing == undefined) + keyframe.easing = shared.toTimingFunction('linear'); + return keyframe; + }); + + var everyFrameHasOffset = true; + var looselySortedByOffset = true; + var previousOffset = -Infinity; + for (var i = 0; i < keyframes.length; i++) { + var offset = keyframes[i].offset; + if (offset != null) { + if (offset < previousOffset) { + throw { + code: DOMException.INVALID_MODIFICATION_ERR, + name: 'InvalidModificationError', + message: 'Keyframes are not loosely sorted by offset. Sort or specify offsets.' + }; + } + previousOffset = offset; + } else { + everyFrameHasOffset = false; + } + } + + keyframes = keyframes.filter(function(keyframe) { + return keyframe.offset >= 0 && keyframe.offset <= 1; + }); + + function spaceKeyframes() { + var length = keyframes.length; + if (keyframes[length - 1].offset == null) + keyframes[length - 1].offset = 1; + if (length > 1 && keyframes[0].offset == null) + keyframes[0].offset = 0; + + var previousIndex = 0; + var previousOffset = keyframes[0].offset; + for (var i = 1; i < length; i++) { + var offset = keyframes[i].offset; + if (offset != null) { + for (var j = 1; j < i - previousIndex; j++) + keyframes[previousIndex + j].offset = previousOffset + (offset - previousOffset) * j / (i - previousIndex); + previousIndex = i; + previousOffset = offset; + } + } + } + if (!everyFrameHasOffset) + spaceKeyframes(); + + return keyframes; + } + + shared.normalizeKeyframes = normalizeKeyframes; + + if (WEB_ANIMATIONS_TESTING) { + testing.normalizeKeyframes = normalizeKeyframes; + } + +})(webAnimationsShared, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/number-handler.js b/scripts/resources/web-animations-js/src/number-handler.js new file mode 100644 index 0000000000..750937392d --- /dev/null +++ b/scripts/resources/web-animations-js/src/number-handler.js @@ -0,0 +1,70 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + function numberToString(x) { + return x.toFixed(3).replace('.000', ''); + } + + function clamp(min, max, x) { + return Math.min(max, Math.max(min, x)); + } + + function parseNumber(string) { + if (/^\s*[-+]?(\d*\.)?\d+\s*$/.test(string)) + return Number(string); + } + + function mergeNumbers(left, right) { + return [left, right, numberToString]; + } + + // FIXME: This should probably go in it's own handler. + function mergeFlex(left, right) { + if (left == 0) + return; + return clampedMergeNumbers(0, Infinity)(left, right); + } + + function mergePositiveIntegers(left, right) { + return [left, right, function(x) { + return Math.round(clamp(1, Infinity, x)); + }]; + } + + function clampedMergeNumbers(min, max) { + return function(left, right) { + return [left, right, function(x) { + return numberToString(clamp(min, max, x)); + }]; + }; + } + + function round(left, right) { + return [left, right, Math.round]; + } + + scope.clamp = clamp; + scope.addPropertiesHandler(parseNumber, clampedMergeNumbers(0, Infinity), ['border-image-width', 'line-height']); + scope.addPropertiesHandler(parseNumber, clampedMergeNumbers(0, 1), ['opacity', 'shape-image-threshold']); + scope.addPropertiesHandler(parseNumber, mergeFlex, ['flex-grow', 'flex-shrink']); + scope.addPropertiesHandler(parseNumber, mergePositiveIntegers, ['orphans', 'widows']); + scope.addPropertiesHandler(parseNumber, round, ['z-index']); + + scope.parseNumber = parseNumber; + scope.mergeNumbers = mergeNumbers; + scope.numberToString = numberToString; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/position-handler.js b/scripts/resources/web-animations-js/src/position-handler.js new file mode 100644 index 0000000000..18cea438cd --- /dev/null +++ b/scripts/resources/web-animations-js/src/position-handler.js @@ -0,0 +1,117 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + + function negateDimension(dimension) { + var result = {}; + for (var k in dimension) { + result[k] = -dimension[k]; + } + return result; + } + + function consumeOffset(string) { + return scope.consumeToken(/^(left|center|right|top|bottom)\b/i, string) || scope.consumeLengthOrPercent(string); + } + + var offsetMap = { + left: {'%': 0}, + center: {'%': 50}, + right: {'%': 100}, + top: {'%': 0}, + bottom: {'%': 100}, + }; + + function parseOrigin(slots, string) { + var result = scope.consumeRepeated(consumeOffset, /^/, string); + if (!result || result[1] != '') return; + var tokens = result[0]; + tokens[0] = tokens[0] || 'center'; + tokens[1] = tokens[1] || 'center'; + if (slots == 3) { + tokens[2] = tokens[2] || {px: 0}; + } + if (tokens.length != slots) { + return; + } + // Reorder so that the horizontal axis comes first. + if (/top|bottom/.test(tokens[0]) || /left|right/.test(tokens[1])) { + var tmp = tokens[0]; + tokens[0] = tokens[1]; + tokens[1] = tmp; + } + // Invalid if not horizontal then vertical. + if (!/left|right|center|Object/.test(tokens[0])) + return; + if (!/top|bottom|center|Object/.test(tokens[1])) + return; + return tokens.map(function(position) { + return typeof position == 'object' ? position : offsetMap[position]; + }); + } + + var mergeOffsetList = scope.mergeNestedRepeated.bind(null, scope.mergeDimensions, ' '); + scope.addPropertiesHandler(parseOrigin.bind(null, 3), mergeOffsetList, ['transform-origin']); + scope.addPropertiesHandler(parseOrigin.bind(null, 2), mergeOffsetList, ['perspective-origin']); + + function consumePosition(string) { + var result = scope.consumeRepeated(consumeOffset, /^/, string); + if (!result) { + return; + } + + var tokens = result[0]; + var out = [{'%': 50}, {'%': 50}]; + var pos = 0; + var bottomOrRight = false; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (typeof token == 'string') { + bottomOrRight = /bottom|right/.test(token); + pos = {left: 0, right: 0, center: pos, top: 1, bottom: 1}[token]; + out[pos] = offsetMap[token]; + if (token == 'center') { + // Center doesn't accept a length offset. + pos++; + } + } else { + if (bottomOrRight) { + // If bottom or right we need to subtract the length from 100% + token = negateDimension(token); + token['%'] = (token['%'] || 0) + 100; + } + out[pos] = token; + pos++; + bottomOrRight = false; + } + } + return [out, result[1]]; + } + + function parsePositionList(string) { + var result = scope.consumeRepeated(consumePosition, /^,/, string); + if (result && result[1] == '') { + return result[0]; + } + } + + scope.consumePosition = consumePosition; + scope.mergeOffsetList = mergeOffsetList; + + var mergePositionList = scope.mergeNestedRepeated.bind(null, mergeOffsetList, ', '); + scope.addPropertiesHandler(parsePositionList, mergePositionList, ['background-position', 'object-position']); + +})(webAnimations1); diff --git a/scripts/resources/web-animations-js/src/property-interpolation.js b/scripts/resources/web-animations-js/src/property-interpolation.js new file mode 100644 index 0000000000..88c3fc2d34 --- /dev/null +++ b/scripts/resources/web-animations-js/src/property-interpolation.js @@ -0,0 +1,125 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + var propertyHandlers = {}; + + function addPropertyHandler(parser, merger, property) { + propertyHandlers[property] = propertyHandlers[property] || []; + propertyHandlers[property].push([parser, merger]); + } + function addPropertiesHandler(parser, merger, properties) { + for (var i = 0; i < properties.length; i++) { + var property = properties[i]; + WEB_ANIMATIONS_TESTING && console.assert(property.toLowerCase() === property); + addPropertyHandler(parser, merger, property); + if (/-/.test(property)) { + // Add camel cased variant. + addPropertyHandler(parser, merger, property.replace(/-(.)/g, function(_, c) { + return c.toUpperCase(); + })); + } + } + } + scope.addPropertiesHandler = addPropertiesHandler; + + var initialValues = { + backgroundColor: 'transparent', + backgroundPosition: '0% 0%', + borderBottomColor: 'currentColor', + borderBottomLeftRadius: '0px', + borderBottomRightRadius: '0px', + borderBottomWidth: '3px', + borderLeftColor: 'currentColor', + borderLeftWidth: '3px', + borderRightColor: 'currentColor', + borderRightWidth: '3px', + // Spec says this should be 0 but in practise it is 2px. + borderSpacing: '2px', + borderTopColor: 'currentColor', + borderTopLeftRadius: '0px', + borderTopRightRadius: '0px', + borderTopWidth: '3px', + bottom: 'auto', + clip: 'rect(0px, 0px, 0px, 0px)', + color: 'black', // Depends on user agent. + fontSize: '100%', + fontWeight: '400', + height: 'auto', + left: 'auto', + letterSpacing: 'normal', + lineHeight: '120%', + marginBottom: '0px', + marginLeft: '0px', + marginRight: '0px', + marginTop: '0px', + maxHeight: 'none', + maxWidth: 'none', + minHeight: '0px', + minWidth: '0px', + opacity: '1.0', + outlineColor: 'invert', + outlineOffset: '0px', + outlineWidth: '3px', + paddingBottom: '0px', + paddingLeft: '0px', + paddingRight: '0px', + paddingTop: '0px', + right: 'auto', + textIndent: '0px', + textShadow: '0px 0px 0px transparent', + top: 'auto', + transform: '', + verticalAlign: '0px', + visibility: 'visible', + width: 'auto', + wordSpacing: 'normal', + zIndex: 'auto' + }; + + function propertyInterpolation(property, left, right) { + if (left == 'initial' || right == 'initial') { + var ucProperty = property.replace(/-(.)/g, function(_, c) { + return c.toUpperCase(); + }); + if (left == 'initial') + left = initialValues[ucProperty]; + if (right == 'initial') + right = initialValues[ucProperty]; + } + var handlers = left == right ? [] : propertyHandlers[property]; + for (var i = 0; handlers && i < handlers.length; i++) { + var parsedLeft = handlers[i][0](left); + var parsedRight = handlers[i][0](right); + if (parsedLeft !== undefined && parsedRight !== undefined) { + var interpolationArgs = handlers[i][1](parsedLeft, parsedRight); + if (interpolationArgs) { + var interp = scope.Interpolation.apply(null, interpolationArgs); + return function(t) { + if (t == 0) return left; + if (t == 1) return right; + return interp(t); + }; + } + } + } + return scope.Interpolation(false, true, function(bool) { + return bool ? right : left; + }); + } + scope.propertyInterpolation = propertyInterpolation; + +})(webAnimations1, webAnimationsTesting); + diff --git a/scripts/resources/web-animations-js/src/property-names.js b/scripts/resources/web-animations-js/src/property-names.js new file mode 100644 index 0000000000..c52d990cdb --- /dev/null +++ b/scripts/resources/web-animations-js/src/property-names.js @@ -0,0 +1,35 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + var aliased = {}; + + function alias(name, aliases) { + aliases.concat([name]).forEach(function(candidate) { + if (candidate in document.documentElement.style) { + aliased[name] = candidate; + } + }); + } + alias('transform', ['webkitTransform', 'msTransform']); + alias('transformOrigin', ['webkitTransformOrigin']); + alias('perspective', ['webkitPerspective']); + alias('perspectiveOrigin', ['webkitPerspectiveOrigin']); + + scope.propertyName = function(property) { + return aliased[property] || property; + }; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/scope.js b/scripts/resources/web-animations-js/src/scope.js new file mode 100644 index 0000000000..c8248802bc --- /dev/null +++ b/scripts/resources/web-animations-js/src/scope.js @@ -0,0 +1,20 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var webAnimationsShared = {}; +var webAnimations1 = {}; +var webAnimationsNext = {}; + +if (!WEB_ANIMATIONS_TESTING) + var webAnimationsTesting = null; diff --git a/scripts/resources/web-animations-js/src/shadow-handler.js b/scripts/resources/web-animations-js/src/shadow-handler.js new file mode 100644 index 0000000000..3f8201d8a4 --- /dev/null +++ b/scripts/resources/web-animations-js/src/shadow-handler.js @@ -0,0 +1,108 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + + function consumeShadow(string) { + var shadow = { + inset: false, + lengths: [], + color: null, + }; + function consumePart(string) { + var result = scope.consumeToken(/^inset/i, string); + if (result) { + shadow.inset = true; + return result; + } + var result = scope.consumeLengthOrPercent(string); + if (result) { + shadow.lengths.push(result[0]); + return result; + } + var result = scope.consumeColor(string); + if (result) { + shadow.color = result[0]; + return result; + } + } + var result = scope.consumeRepeated(consumePart, /^/, string); + if (result && result[0].length) { + return [shadow, result[1]]; + } + } + + function parseShadowList(string) { + var result = scope.consumeRepeated(consumeShadow, /^,/, string); + if (result && result[1] == '') { + return result[0]; + } + } + + function mergeShadow(left, right) { + while (left.lengths.length < Math.max(left.lengths.length, right.lengths.length)) + left.lengths.push({px: 0}); + while (right.lengths.length < Math.max(left.lengths.length, right.lengths.length)) + right.lengths.push({px: 0}); + + if (left.inset != right.inset || !!left.color != !!right.color) { + return; + } + var lengthReconstitution = []; + var colorReconstitution; + var matchingLeft = [[], 0]; + var matchingRight = [[], 0]; + for (var i = 0; i < left.lengths.length; i++) { + var mergedDimensions = scope.mergeDimensions(left.lengths[i], right.lengths[i], i == 2); + matchingLeft[0].push(mergedDimensions[0]); + matchingRight[0].push(mergedDimensions[1]); + lengthReconstitution.push(mergedDimensions[2]); + } + if (left.color && right.color) { + var mergedColor = scope.mergeColors(left.color, right.color); + matchingLeft[1] = mergedColor[0]; + matchingRight[1] = mergedColor[1]; + colorReconstitution = mergedColor[2]; + } + return [matchingLeft, matchingRight, function(value) { + var result = left.inset ? 'inset ' : ' '; + for (var i = 0; i < lengthReconstitution.length; i++) { + result += lengthReconstitution[i](value[0][i]) + ' '; + } + if (colorReconstitution) { + result += colorReconstitution(value[1]); + } + return result; + }]; + } + + function mergeNestedRepeatedShadow(nestedMerge, separator, left, right) { + var leftCopy = []; + var rightCopy = []; + function defaultShadow(inset) { + return {inset: inset, color: [0, 0, 0, 0], lengths: [{px: 0}, {px: 0}, {px: 0}, {px: 0}]}; + } + for (var i = 0; i < left.length || i < right.length; i++) { + var l = left[i] || defaultShadow(right[i].inset); + var r = right[i] || defaultShadow(left[i].inset); + leftCopy.push(l); + rightCopy.push(r); + } + return scope.mergeNestedRepeated(nestedMerge, separator, leftCopy, rightCopy); + } + + var mergeShadowList = mergeNestedRepeatedShadow.bind(null, mergeShadow, ', '); + scope.addPropertiesHandler(parseShadowList, mergeShadowList, ['box-shadow', 'text-shadow']); + +})(webAnimations1); diff --git a/scripts/resources/web-animations-js/src/shape-handler.js b/scripts/resources/web-animations-js/src/shape-handler.js new file mode 100644 index 0000000000..6bbf79fe48 --- /dev/null +++ b/scripts/resources/web-animations-js/src/shape-handler.js @@ -0,0 +1,85 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + + var consumeLengthOrPercent = scope.consumeParenthesised.bind(null, scope.parseLengthOrPercent); + var consumeLengthOrPercentPair = scope.consumeRepeated.bind(undefined, consumeLengthOrPercent, /^/); + + var mergeSizePair = scope.mergeNestedRepeated.bind(undefined, scope.mergeDimensions, ' '); + var mergeSizePairList = scope.mergeNestedRepeated.bind(undefined, mergeSizePair, ','); + + function parseShape(input) { + var circle = scope.consumeToken(/^circle/, input); + if (circle && circle[0]) { + return ['circle'].concat(scope.consumeList([ + scope.ignore(scope.consumeToken.bind(undefined, /^\(/)), + consumeLengthOrPercent, + scope.ignore(scope.consumeToken.bind(undefined, /^at/)), + scope.consumePosition, + scope.ignore(scope.consumeToken.bind(undefined, /^\)/)) + ], circle[1])); + } + var ellipse = scope.consumeToken(/^ellipse/, input); + if (ellipse && ellipse[0]) { + return ['ellipse'].concat(scope.consumeList([ + scope.ignore(scope.consumeToken.bind(undefined, /^\(/)), + consumeLengthOrPercentPair, + scope.ignore(scope.consumeToken.bind(undefined, /^at/)), + scope.consumePosition, + scope.ignore(scope.consumeToken.bind(undefined, /^\)/)) + ], ellipse[1])); + } + var polygon = scope.consumeToken(/^polygon/, input); + if (polygon && polygon[0]) { + return ['polygon'].concat(scope.consumeList([ + scope.ignore(scope.consumeToken.bind(undefined, /^\(/)), + scope.optional(scope.consumeToken.bind(undefined, /^nonzero\s*,|^evenodd\s*,/), 'nonzero,'), + scope.consumeSizePairList, + scope.ignore(scope.consumeToken.bind(undefined, /^\)/)) + ], polygon[1])); + } + } + + function mergeShapes(left, right) { + if (left[0] !== right[0]) + return; + if (left[0] == 'circle') { + return scope.mergeList(left.slice(1), right.slice(1), [ + 'circle(', + scope.mergeDimensions, + ' at ', + scope.mergeOffsetList, + ')']); + } + if (left[0] == 'ellipse') { + return scope.mergeList(left.slice(1), right.slice(1), [ + 'ellipse(', + scope.mergeNonNegativeSizePair, + ' at ', + scope.mergeOffsetList, + ')']); + } + if (left[0] == 'polygon' && left[1] == right[1]) { + return scope.mergeList(left.slice(2), right.slice(2), [ + 'polygon(', + left[1], + mergeSizePairList, + ')']); + } + } + + scope.addPropertiesHandler(parseShape, mergeShapes, ['shape-outside']); + +})(webAnimations1); diff --git a/scripts/resources/web-animations-js/src/tick.js b/scripts/resources/web-animations-js/src/tick.js new file mode 100644 index 0000000000..6e1fb5e49a --- /dev/null +++ b/scripts/resources/web-animations-js/src/tick.js @@ -0,0 +1,171 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +(function(shared, scope, testing) { + var originalRequestAnimationFrame = window.requestAnimationFrame; + var rafCallbacks = []; + var rafId = 0; + window.requestAnimationFrame = function(f) { + var id = rafId++; + if (rafCallbacks.length == 0 && !WEB_ANIMATIONS_TESTING) { + originalRequestAnimationFrame(processRafCallbacks); + } + rafCallbacks.push([id, f]); + return id; + }; + + window.cancelAnimationFrame = function(id) { + rafCallbacks.forEach(function(entry) { + if (entry[0] == id) { + entry[1] = function() {}; + } + }); + }; + + function processRafCallbacks(t) { + var processing = rafCallbacks; + rafCallbacks = []; + if (t < timeline.currentTime) + t = timeline.currentTime; + tick(t); + processing.forEach(function(entry) { entry[1](t); }); + if (needsRetick) + tick(t); + applyPendingEffects(); + _now = undefined; + } + + function compareAnimations(leftAnimation, rightAnimation) { + return leftAnimation._sequenceNumber - rightAnimation._sequenceNumber; + } + + function InternalTimeline() { + this._animations = []; + // Android 4.3 browser has window.performance, but not window.performance.now + this.currentTime = window.performance && performance.now ? performance.now() : 0; + }; + + InternalTimeline.prototype = { + _play: function(effect) { + effect._timing = shared.normalizeTimingInput(effect.timing); + var animation = new scope.Animation(effect); + animation._idle = false; + animation._timeline = this; + this._animations.push(animation); + scope.restart(); + scope.invalidateEffects(); + return animation; + } + }; + + var _now = undefined; + + if (WEB_ANIMATIONS_TESTING) { + var now = function() { return timeline.currentTime; }; + } else { + var now = function() { + if (_now == undefined) + _now = performance.now(); + return _now; + }; + } + + var ticking = false; + var hasRestartedThisFrame = false; + + scope.restart = function() { + if (!ticking) { + ticking = true; + requestAnimationFrame(function() {}); + hasRestartedThisFrame = true; + } + return hasRestartedThisFrame; + }; + + var needsRetick = false; + scope.invalidateEffects = function() { + needsRetick = true; + }; + + var pendingEffects = []; + function applyPendingEffects() { + pendingEffects.forEach(function(f) { f(); }); + pendingEffects.length = 0; + } + + var t60hz = 1000 / 60; + + var originalGetComputedStyle = window.getComputedStyle; + Object.defineProperty(window, 'getComputedStyle', { + configurable: true, + enumerable: true, + value: function() { + if (needsRetick) { + var time = now(); + if (time - timeline.currentTime > 0) + timeline.currentTime += t60hz * (Math.floor((time - timeline.currentTime) / t60hz) + 1); + tick(timeline.currentTime); + } + applyPendingEffects(); + return originalGetComputedStyle.apply(this, arguments); + }, + }); + + function tick(t) { + hasRestartedThisFrame = false; + var timeline = scope.timeline; + timeline.currentTime = t; + timeline._animations.sort(compareAnimations); + ticking = false; + var updatingAnimations = timeline._animations; + timeline._animations = []; + + var newPendingClears = []; + var newPendingEffects = []; + updatingAnimations = updatingAnimations.filter(function(animation) { + animation._inTimeline = animation._tick(t); + + if (!animation._inEffect) + newPendingClears.push(animation._effect); + else + newPendingEffects.push(animation._effect); + + if (!animation._isFinished && !animation._paused && !animation._idle) + ticking = true; + + return animation._inTimeline; + }); + + // FIXME: Should remove dupliactes from pendingEffects. + pendingEffects.push.apply(pendingEffects, newPendingClears); + pendingEffects.push.apply(pendingEffects, newPendingEffects); + + timeline._animations.push.apply(timeline._animations, updatingAnimations); + needsRetick = false; + + if (ticking) + requestAnimationFrame(function() {}); + }; + + if (WEB_ANIMATIONS_TESTING) { + testing.tick = function(t) { timeline.currentTime = t; processRafCallbacks(t); }; + testing.isTicking = function() { return ticking; }; + testing.setTicking = function(newVal) { ticking = newVal; }; + } + + var timeline = new InternalTimeline(); + scope.timeline = timeline; + +})(webAnimationsShared, webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/timeline.js b/scripts/resources/web-animations-js/src/timeline.js new file mode 100644 index 0000000000..cbd784aa9e --- /dev/null +++ b/scripts/resources/web-animations-js/src/timeline.js @@ -0,0 +1,101 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +(function(shared, scope, testing) { + var originalRequestAnimationFrame = window.requestAnimationFrame; + window.requestAnimationFrame = function(f) { + return originalRequestAnimationFrame(function(x) { + window.document.timeline._updateAnimationsPromises(); + f(x); + window.document.timeline._updateAnimationsPromises(); + }); + }; + + scope.AnimationTimeline = function() { + this._animations = []; + this.currentTime = undefined; + }; + + scope.AnimationTimeline.prototype = { + getAnimations: function() { + this._discardAnimations(); + return this._animations.slice(); + }, + _updateAnimationsPromises: function() { + scope.animationsWithPromises = scope.animationsWithPromises.filter(function(animation) { + return animation._updatePromises(); + }); + }, + _discardAnimations: function() { + this._updateAnimationsPromises(); + this._animations = this._animations.filter(function(animation) { + return animation.playState != 'finished' && animation.playState != 'idle'; + }); + }, + _play: function(effect) { + var animation = new scope.Animation(effect, this); + this._animations.push(animation); + scope.restartWebAnimationsNextTick(); + // Use animation._animation.play() here, NOT animation.play(). + // + // Timeline.play calls new scope.Animation(effect) which (indirectly) calls Timeline.play on + // effect's children, and Animation.play is also recursive. We only need to call play on each + // animation in the tree once. + animation._updatePromises(); + animation._animation.play(); + animation._updatePromises(); + return animation; + }, + play: function(effect) { + if (effect) { + effect.remove(); + } + return this._play(effect); + } + }; + + var ticking = false; + + scope.restartWebAnimationsNextTick = function() { + if (!ticking) { + ticking = true; + requestAnimationFrame(webAnimationsNextTick); + } + }; + + function webAnimationsNextTick(t) { + var timeline = window.document.timeline; + timeline.currentTime = t; + timeline._discardAnimations(); + if (timeline._animations.length == 0) + ticking = false; + else + requestAnimationFrame(webAnimationsNextTick); + } + + var timeline = new scope.AnimationTimeline(); + scope.timeline = timeline; + + try { + Object.defineProperty(window.document, 'timeline', { + configurable: true, + get: function() { return timeline; } + }); + } catch (e) { } + try { + window.document.timeline = timeline; + } catch (e) { } + +})(webAnimationsShared, webAnimationsNext, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/timing-utilities.js b/scripts/resources/web-animations-js/src/timing-utilities.js new file mode 100644 index 0000000000..f2f89614e6 --- /dev/null +++ b/scripts/resources/web-animations-js/src/timing-utilities.js @@ -0,0 +1,341 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, testing) { + + var fills = 'backwards|forwards|both|none'.split('|'); + var directions = 'reverse|alternate|alternate-reverse'.split('|'); + + function cloneTimingInput(timingInput) { + if (typeof timingInput == 'number') { + return timingInput; + } + var clone = {}; + for (var m in timingInput) { + clone[m] = timingInput[m]; + } + return clone; + } + + function AnimationEffectTiming() { + this._delay = 0; + this._endDelay = 0; + this._fill = 'none'; + this._iterationStart = 0; + this._iterations = 1; + this._duration = 0; + this._playbackRate = 1; + this._direction = 'normal'; + this._easing = 'linear'; + } + + AnimationEffectTiming.prototype = { + _setMember: function(member, value) { + this['_' + member] = value; + if (this._effect) { + this._effect._timingInput[member] = value; + this._effect._timing = shared.normalizeTimingInput(shared.normalizeTimingInput(this._effect._timingInput)); + this._effect.activeDuration = shared.calculateActiveDuration(this._effect._timing); + if (this._effect._animation) { + this._effect._animation._rebuildUnderlyingAnimation(); + } + } + }, + get playbackRate() { + return this._playbackRate; + }, + set delay(value) { + this._setMember('delay', value); + }, + get delay() { + return this._delay; + }, + set endDelay(value) { + this._setMember('endDelay', value); + }, + get endDelay() { + return this._endDelay; + }, + set fill(value) { + this._setMember('fill', value); + }, + get fill() { + return this._fill; + }, + set iterationStart(value) { + this._setMember('iterationStart', value); + }, + get iterationStart() { + return this._iterationStart; + }, + set duration(value) { + this._setMember('duration', value); + }, + get duration() { + return this._duration; + }, + set direction(value) { + this._setMember('direction', value); + }, + get direction() { + return this._direction; + }, + set easing(value) { + this._setMember('easing', value); + }, + get easing() { + return this._easing; + }, + set iterations(value) { + this._setMember('iterations', value); + }, + get iterations() { + return this._iterations; + } + }; + + function makeTiming(timingInput, forGroup, effect) { + var timing = new AnimationEffectTiming(); + if (forGroup) { + timing.fill = 'both'; + timing.duration = 'auto'; + } + if (typeof timingInput == 'number' && !isNaN(timingInput)) { + timing.duration = timingInput; + } else if (timingInput !== undefined) { + Object.getOwnPropertyNames(timingInput).forEach(function(property) { + if (timingInput[property] != 'auto') { + if (typeof timing[property] == 'number' || property == 'duration') { + if (typeof timingInput[property] != 'number' || isNaN(timingInput[property])) { + return; + } + } + if ((property == 'fill') && (fills.indexOf(timingInput[property]) == -1)) { + return; + } + if ((property == 'direction') && (directions.indexOf(timingInput[property]) == -1)) { + return; + } + if (property == 'playbackRate' && timingInput[property] !== 1 && shared.isDeprecated('AnimationEffectTiming.playbackRate', '2014-11-28', 'Use Animation.playbackRate instead.')) { + return; + } + timing[property] = timingInput[property]; + } + }); + } + return timing; + } + + function numericTimingToObject(timingInput) { + if (typeof timingInput == 'number') { + if (isNaN(timingInput)) { + timingInput = { duration: 0 }; + } else { + timingInput = { duration: timingInput }; + } + } + return timingInput; + } + + function normalizeTimingInput(timingInput, forGroup) { + timingInput = shared.numericTimingToObject(timingInput); + var timing = makeTiming(timingInput, forGroup); + timing._easing = toTimingFunction(timing.easing); + return timing; + } + + function cubic(a, b, c, d) { + if (a < 0 || a > 1 || c < 0 || c > 1) { + return linear; + } + return function(x) { + if (x == 0 || x == 1) { + return x; + } + var start = 0, end = 1; + while (1) { + var mid = (start + end) / 2; + function f(a, b, m) { return 3 * a * (1 - m) * (1 - m) * m + 3 * b * (1 - m) * m * m + m * m * m}; + var xEst = f(a, c, mid); + if (Math.abs(x - xEst) < 0.001) { + return f(b, d, mid); + } + if (xEst < x) { + start = mid; + } else { + end = mid; + } + } + } + } + + var Start = 1; + var Middle = 0.5; + var End = 0; + + function step(count, pos) { + return function(x) { + if (x >= 1) { + return 1; + } + var stepSize = 1 / count; + x += pos * stepSize; + return x - x % stepSize; + } + } + + var presets = { + 'ease': cubic(0.25, 0.1, 0.25, 1), + 'ease-in': cubic(0.42, 0, 1, 1), + 'ease-out': cubic(0, 0, 0.58, 1), + 'ease-in-out': cubic(0.42, 0, 0.58, 1), + 'step-start': step(1, Start), + 'step-middle': step(1, Middle), + 'step-end': step(1, End) + }; + + var numberString = '\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*'; + var cubicBezierRe = new RegExp('cubic-bezier\\(' + numberString + ',' + numberString + ',' + numberString + ',' + numberString + '\\)'); + var stepRe = /steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/; + var linear = function(x) { return x; }; + + function toTimingFunction(easing) { + var cubicData = cubicBezierRe.exec(easing); + if (cubicData) { + return cubic.apply(this, cubicData.slice(1).map(Number)); + } + var stepData = stepRe.exec(easing); + if (stepData) { + return step(Number(stepData[1]), {'start': Start, 'middle': Middle, 'end': End}[stepData[2]]); + } + var preset = presets[easing]; + if (preset) { + return preset; + } + return linear; + }; + + function calculateActiveDuration(timing) { + return Math.abs(repeatedDuration(timing) / timing.playbackRate); + } + + function repeatedDuration(timing) { + return timing.duration * timing.iterations; + } + + var PhaseNone = 0; + var PhaseBefore = 1; + var PhaseAfter = 2; + var PhaseActive = 3; + + function calculatePhase(activeDuration, localTime, timing) { + if (localTime == null) { + return PhaseNone; + } + if (localTime < timing.delay) { + return PhaseBefore; + } + if (localTime >= timing.delay + activeDuration) { + return PhaseAfter; + } + return PhaseActive; + } + + function calculateActiveTime(activeDuration, fillMode, localTime, phase, delay) { + switch (phase) { + case PhaseBefore: + if (fillMode == 'backwards' || fillMode == 'both') + return 0; + return null; + case PhaseActive: + return localTime - delay; + case PhaseAfter: + if (fillMode == 'forwards' || fillMode == 'both') + return activeDuration; + return null; + case PhaseNone: + return null; + } + } + + function calculateScaledActiveTime(activeDuration, activeTime, startOffset, timing) { + return (timing.playbackRate < 0 ? activeTime - activeDuration : activeTime) * timing.playbackRate + startOffset; + } + + function calculateIterationTime(iterationDuration, repeatedDuration, scaledActiveTime, startOffset, timing) { + if (scaledActiveTime === Infinity || scaledActiveTime === -Infinity || (scaledActiveTime - startOffset == repeatedDuration && timing.iterations && ((timing.iterations + timing.iterationStart) % 1 == 0))) { + return iterationDuration; + } + + return scaledActiveTime % iterationDuration; + } + + function calculateCurrentIteration(iterationDuration, iterationTime, scaledActiveTime, timing) { + if (scaledActiveTime === 0) { + return 0; + } + if (iterationTime == iterationDuration) { + return timing.iterationStart + timing.iterations - 1; + } + return Math.floor(scaledActiveTime / iterationDuration); + } + + function calculateTransformedTime(currentIteration, iterationDuration, iterationTime, timing) { + var currentIterationIsOdd = currentIteration % 2 >= 1; + var currentDirectionIsForwards = timing.direction == 'normal' || timing.direction == (currentIterationIsOdd ? 'alternate-reverse' : 'alternate'); + var directedTime = currentDirectionIsForwards ? iterationTime : iterationDuration - iterationTime; + var timeFraction = directedTime / iterationDuration; + return iterationDuration * timing.easing(timeFraction); + } + + function calculateTimeFraction(activeDuration, localTime, timing) { + var phase = calculatePhase(activeDuration, localTime, timing); + var activeTime = calculateActiveTime(activeDuration, timing.fill, localTime, phase, timing.delay); + if (activeTime === null) + return null; + if (activeDuration === 0) + return phase === PhaseBefore ? 0 : 1; + var startOffset = timing.iterationStart * timing.duration; + var scaledActiveTime = calculateScaledActiveTime(activeDuration, activeTime, startOffset, timing); + var iterationTime = calculateIterationTime(timing.duration, repeatedDuration(timing), scaledActiveTime, startOffset, timing); + var currentIteration = calculateCurrentIteration(timing.duration, iterationTime, scaledActiveTime, timing); + return calculateTransformedTime(currentIteration, timing.duration, iterationTime, timing) / timing.duration; + } + + shared.cloneTimingInput = cloneTimingInput; + shared.makeTiming = makeTiming; + shared.numericTimingToObject = numericTimingToObject; + shared.normalizeTimingInput = normalizeTimingInput; + shared.calculateActiveDuration = calculateActiveDuration; + shared.calculateTimeFraction = calculateTimeFraction; + shared.calculatePhase = calculatePhase; + shared.toTimingFunction = toTimingFunction; + + if (WEB_ANIMATIONS_TESTING) { + testing.normalizeTimingInput = normalizeTimingInput; + testing.toTimingFunction = toTimingFunction; + testing.calculateActiveDuration = calculateActiveDuration; + testing.calculatePhase = calculatePhase; + testing.PhaseNone = PhaseNone; + testing.PhaseBefore = PhaseBefore; + testing.PhaseActive = PhaseActive; + testing.PhaseAfter = PhaseAfter; + testing.calculateActiveTime = calculateActiveTime; + testing.calculateScaledActiveTime = calculateScaledActiveTime; + testing.calculateIterationTime = calculateIterationTime; + testing.calculateCurrentIteration = calculateCurrentIteration; + testing.calculateTransformedTime = calculateTransformedTime; + } + +})(webAnimationsShared, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/transform-handler.js b/scripts/resources/web-animations-js/src/transform-handler.js new file mode 100644 index 0000000000..c44829610b --- /dev/null +++ b/scripts/resources/web-animations-js/src/transform-handler.js @@ -0,0 +1,262 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + // This returns a function for converting transform functions to equivalent + // primitive functions, which will take an array of values from the + // derivative type and fill in the blanks (underscores) with them. + var _ = null; + function cast(pattern) { + return function(contents) { + var i = 0; + return pattern.map(function(x) { return x === _ ? contents[i++] : x; }); + } + } + + function id(x) { return x; } + + var Opx = {px: 0}; + var Odeg = {deg: 0}; + + // type: [argTypes, convertTo3D, convertTo2D] + // In the argument types string, lowercase characters represent optional arguments + var transformFunctions = { + matrix: ['NNNNNN', [_, _, 0, 0, _, _, 0, 0, 0, 0, 1, 0, _, _, 0, 1], id], + matrix3d: ['NNNNNNNNNNNNNNNN', id], + rotate: ['A'], + rotatex: ['A'], + rotatey: ['A'], + rotatez: ['A'], + rotate3d: ['NNNA'], + perspective: ['L'], + scale: ['Nn', cast([_, _, 1]), id], + scalex: ['N', cast([_, 1, 1]), cast([_, 1])], + scaley: ['N', cast([1, _, 1]), cast([1, _])], + scalez: ['N', cast([1, 1, _])], + scale3d: ['NNN', id], + skew: ['Aa', null, id], + skewx: ['A', null, cast([_, Odeg])], + skewy: ['A', null, cast([Odeg, _])], + translate: ['Tt', cast([_, _, Opx]), id], + translatex: ['T', cast([_, Opx, Opx]), cast([_, Opx])], + translatey: ['T', cast([Opx, _, Opx]), cast([Opx, _])], + translatez: ['L', cast([Opx, Opx, _])], + translate3d: ['TTL', id], + }; + + function parseTransform(string) { + string = string.toLowerCase().trim(); + if (string == 'none') + return []; + // FIXME: Using a RegExp means calcs won't work here + var transformRegExp = /\s*(\w+)\(([^)]*)\)/g; + var result = []; + var match; + var prevLastIndex = 0; + while (match = transformRegExp.exec(string)) { + if (match.index != prevLastIndex) + return; + prevLastIndex = match.index + match[0].length; + var functionName = match[1]; + var functionData = transformFunctions[functionName]; + if (!functionData) + return; + var args = match[2].split(','); + var argTypes = functionData[0]; + if (argTypes.length < args.length) + return; + + var parsedArgs = []; + for (var i = 0; i < argTypes.length; i++) { + var arg = args[i]; + var type = argTypes[i]; + var parsedArg; + if (!arg) + parsedArg = ({a: Odeg, + n: parsedArgs[0], + t: Opx})[type]; + else + parsedArg = ({A: function(s) { return s.trim() == '0' ? Odeg : scope.parseAngle(s); }, + N: scope.parseNumber, + T: scope.parseLengthOrPercent, + L: scope.parseLength})[type.toUpperCase()](arg); + if (parsedArg === undefined) + return; + parsedArgs.push(parsedArg); + } + result.push({t: functionName, d: parsedArgs}); + + if (transformRegExp.lastIndex == string.length) + return result; + } + }; + + function numberToLongString(x) { + return x.toFixed(6).replace('.000000', ''); + } + + function mergeMatrices(left, right) { + if (left.decompositionPair !== right) { + left.decompositionPair = right; + var leftArgs = scope.makeMatrixDecomposition(left); + } + if (right.decompositionPair !== left) { + right.decompositionPair = left; + var rightArgs = scope.makeMatrixDecomposition(right); + } + if (leftArgs[0] == null || rightArgs[0] == null) + return [[false], [true], function(x) { return x ? right[0].d : left[0].d; }]; + leftArgs[0].push(0); + rightArgs[0].push(1); + return [ + leftArgs, + rightArgs, + function(list) { + var quat = scope.quat(leftArgs[0][3], rightArgs[0][3], list[5]); + var mat = scope.composeMatrix(list[0], list[1], list[2], quat, list[4]); + var stringifiedArgs = mat.map(numberToLongString).join(','); + return stringifiedArgs; + } + ]; + } + + function typeTo2D(type) { + return type.replace(/[xy]/, ''); + } + + function typeTo3D(type) { + return type.replace(/(x|y|z|3d)?$/, '3d'); + } + + function mergeTransforms(left, right) { + var matrixModulesLoaded = scope.makeMatrixDecomposition && true; + + var flipResults = false; + if (!left.length || !right.length) { + if (!left.length) { + flipResults = true; + left = right; + right = []; + } + for (var i = 0; i < left.length; i++) { + var type = left[i].t; + var args = left[i].d; + var defaultValue = type.substr(0, 5) == 'scale' ? 1 : 0; + right.push({t: type, d: args.map(function(arg) { + if (typeof arg == 'number') + return defaultValue; + var result = {}; + for (var unit in arg) + result[unit] = defaultValue; + return result; + })}); + } + } + + var isMatrixOrPerspective = function(lt, rt) { + return ((lt == 'perspective') && (rt == 'perspective')) || + ((lt == 'matrix' || lt == 'matrix3d') && (rt == 'matrix' || rt == 'matrix3d')); + }; + var leftResult = []; + var rightResult = []; + var types = []; + + if (left.length != right.length) { + if (!matrixModulesLoaded) + return; + var merged = mergeMatrices(left, right); + leftResult = [merged[0]]; + rightResult = [merged[1]]; + types = [['matrix', [merged[2]]]]; + } else { + for (var i = 0; i < left.length; i++) { + var leftType = left[i].t; + var rightType = right[i].t; + var leftArgs = left[i].d; + var rightArgs = right[i].d; + + var leftFunctionData = transformFunctions[leftType]; + var rightFunctionData = transformFunctions[rightType]; + + var type; + if (isMatrixOrPerspective(leftType, rightType)) { + if (!matrixModulesLoaded) + return; + var merged = mergeMatrices([left[i]], [right[i]]); + leftResult.push(merged[0]); + rightResult.push(merged[1]); + types.push(['matrix', [merged[2]]]); + continue; + } else if (leftType == rightType) { + type = leftType; + } else if (leftFunctionData[2] && rightFunctionData[2] && typeTo2D(leftType) == typeTo2D(rightType)) { + type = typeTo2D(leftType); + leftArgs = leftFunctionData[2](leftArgs); + rightArgs = rightFunctionData[2](rightArgs); + } else if (leftFunctionData[1] && rightFunctionData[1] && typeTo3D(leftType) == typeTo3D(rightType)) { + type = typeTo3D(leftType); + leftArgs = leftFunctionData[1](leftArgs); + rightArgs = rightFunctionData[1](rightArgs); + } else { + if (!matrixModulesLoaded) + return; + var merged = mergeMatrices(left, right); + leftResult = [merged[0]]; + rightResult = [merged[1]]; + types = [['matrix', [merged[2]]]]; + break; + } + + var leftArgsCopy = []; + var rightArgsCopy = []; + var stringConversions = []; + for (var j = 0; j < leftArgs.length; j++) { + var merge = typeof leftArgs[j] == 'number' ? scope.mergeNumbers : scope.mergeDimensions; + var merged = merge(leftArgs[j], rightArgs[j]); + leftArgsCopy[j] = merged[0]; + rightArgsCopy[j] = merged[1]; + stringConversions.push(merged[2]); + } + leftResult.push(leftArgsCopy); + rightResult.push(rightArgsCopy); + types.push([type, stringConversions]); + } + } + + if (flipResults) { + var tmp = leftResult; + leftResult = rightResult; + rightResult = tmp; + } + + return [leftResult, rightResult, function(list) { + return list.map(function(args, i) { + var stringifiedArgs = args.map(function(arg, j) { + return types[i][1][j](arg); + }).join(','); + if (types[i][0] == 'matrix' && stringifiedArgs.split(',').length == 16) + types[i][0] = 'matrix3d'; + return types[i][0] + '(' + stringifiedArgs + ')'; + + }).join(' '); + }]; + } + + scope.addPropertiesHandler(parseTransform, mergeTransforms, ['transform']); + + if (WEB_ANIMATIONS_TESTING) + testing.parseTransform = parseTransform; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/src/visibility-handler.js b/scripts/resources/web-animations-js/src/visibility-handler.js new file mode 100644 index 0000000000..53f2953554 --- /dev/null +++ b/scripts/resources/web-animations-js/src/visibility-handler.js @@ -0,0 +1,29 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + function merge(left, right) { + if (left != 'visible' && right != 'visible') return; + return [0, 1, function(x) { + if (x <= 0) return left; + if (x >= 1) return right; + return 'visible'; + }]; + } + + scope.addPropertiesHandler(String, merge, ['visibility']); + +})(webAnimations1); + diff --git a/scripts/resources/web-animations-js/src/web-animations-next-animation.js b/scripts/resources/web-animations-js/src/web-animations-next-animation.js new file mode 100644 index 0000000000..552e018bc9 --- /dev/null +++ b/scripts/resources/web-animations-js/src/web-animations-next-animation.js @@ -0,0 +1,371 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + scope.animationsWithPromises = []; + + scope.Animation = function(effect, timeline) { + this.effect = effect; + if (effect) { + effect._animation = this; + } + if (!timeline) { + throw new Error('Animation with null timeline is not supported'); + } + this._timeline = timeline; + this._sequenceNumber = shared.sequenceNumber++; + this._holdTime = 0; + this._paused = false; + this._isGroup = false; + this._animation = null; + this._childAnimations = []; + this._callback = null; + this._oldPlayState = 'idle'; + this._rebuildUnderlyingAnimation(); + // Animations are constructed in the idle state. + this._animation.cancel(); + this._updatePromises(); + }; + + scope.Animation.prototype = { + _updatePromises: function() { + var oldPlayState = this._oldPlayState; + var newPlayState = this.playState; + if (this._readyPromise && newPlayState !== oldPlayState) { + if (newPlayState == 'idle') { + this._rejectReadyPromise(); + this._readyPromise = undefined; + } else if (oldPlayState == 'pending') { + this._resolveReadyPromise(); + } else if (newPlayState == 'pending') { + this._readyPromise = undefined; + } + } + if (this._finishedPromise && newPlayState !== oldPlayState) { + if (newPlayState == 'idle') { + this._rejectFinishedPromise(); + this._finishedPromise = undefined; + } else if (newPlayState == 'finished') { + this._resolveFinishedPromise(); + } else if (oldPlayState == 'finished') { + this._finishedPromise = undefined; + } + } + this._oldPlayState = this.playState; + return (this._readyPromise || this._finishedPromise); + }, + _rebuildUnderlyingAnimation: function() { + this._updatePromises(); + var oldPlaybackRate; + var oldPaused; + var oldStartTime; + var oldCurrentTime; + var hadUnderlying = this._animation ? true : false; + if (hadUnderlying) { + oldPlaybackRate = this.playbackRate; + oldPaused = this._paused; + oldStartTime = this.startTime; + oldCurrentTime = this.currentTime; + this._animation.cancel(); + this._animation._wrapper = null; + this._animation = null; + } + + if (!this.effect || this.effect instanceof window.KeyframeEffect) { + this._animation = scope.newUnderlyingAnimationForKeyframeEffect(this.effect); + scope.bindAnimationForKeyframeEffect(this); + } + if (this.effect instanceof window.SequenceEffect || this.effect instanceof window.GroupEffect) { + this._animation = scope.newUnderlyingAnimationForGroup(this.effect); + scope.bindAnimationForGroup(this); + } + if (this.effect && this.effect._onsample) { + scope.bindAnimationForCustomEffect(this); + } + if (hadUnderlying) { + if (oldPlaybackRate != 1) { + this.playbackRate = oldPlaybackRate; + } + if (oldStartTime !== null) { + this.startTime = oldStartTime; + } else if (oldCurrentTime !== null) { + this.currentTime = oldCurrentTime; + } else if (this._holdTime !== null) { + this.currentTime = this._holdTime; + } + if (oldPaused) { + this.pause(); + } + } + this._updatePromises(); + }, + _updateChildren: function() { + if (!this.effect || this.playState == 'idle') + return; + + var offset = this.effect._timing.delay; + this._childAnimations.forEach(function(childAnimation) { + this._arrangeChildren(childAnimation, offset); + if (this.effect instanceof window.SequenceEffect) + offset += scope.groupChildDuration(childAnimation.effect); + }.bind(this)); + }, + _setExternalAnimation: function(animation) { + if (!this.effect || !this._isGroup) + return; + for (var i = 0; i < this.effect.children.length; i++) { + this.effect.children[i]._animation = animation; + this._childAnimations[i]._setExternalAnimation(animation); + } + }, + _constructChildAnimations: function() { + if (!this.effect || !this._isGroup) + return; + var offset = this.effect._timing.delay; + this._removeChildAnimations(); + this.effect.children.forEach(function(child) { + var childAnimation = window.document.timeline._play(child); + this._childAnimations.push(childAnimation); + childAnimation.playbackRate = this.playbackRate; + if (this._paused) + childAnimation.pause(); + child._animation = this.effect._animation; + + this._arrangeChildren(childAnimation, offset); + + if (this.effect instanceof window.SequenceEffect) + offset += scope.groupChildDuration(child); + }.bind(this)); + }, + _arrangeChildren: function(childAnimation, offset) { + if (this.startTime === null) { + childAnimation.currentTime = this.currentTime - offset / this.playbackRate; + } else if (childAnimation.startTime !== this.startTime + offset / this.playbackRate) { + childAnimation.startTime = this.startTime + offset / this.playbackRate; + } + }, + get timeline() { + return this._timeline; + }, + get playState() { + return this._animation ? this._animation.playState : 'idle'; + }, + get finished() { + if (!window.Promise) { + console.warn('Animation Promises require JavaScript Promise constructor'); + return null; + } + if (!this._finishedPromise) { + if (scope.animationsWithPromises.indexOf(this) == -1) { + scope.animationsWithPromises.push(this); + } + this._finishedPromise = new Promise( + function(resolve, reject) { + this._resolveFinishedPromise = function() { + resolve(this); + }; + this._rejectFinishedPromise = function() { + reject({type: DOMException.ABORT_ERR, name: 'AbortError'}); + }; + }.bind(this)); + if (this.playState == 'finished') { + this._resolveFinishedPromise(); + } + } + return this._finishedPromise; + }, + get ready() { + if (!window.Promise) { + console.warn('Animation Promises require JavaScript Promise constructor'); + return null; + } + if (!this._readyPromise) { + if (scope.animationsWithPromises.indexOf(this) == -1) { + scope.animationsWithPromises.push(this); + } + this._readyPromise = new Promise( + function(resolve, reject) { + this._resolveReadyPromise = function() { + resolve(this); + }; + this._rejectReadyPromise = function() { + reject({type: DOMException.ABORT_ERR, name: 'AbortError'}); + }; + }.bind(this)); + if (this.playState !== 'pending') { + this._resolveReadyPromise(); + } + } + return this._readyPromise; + }, + get onfinish() { + return this._onfinish; + }, + set onfinish(v) { + if (typeof v == 'function') { + this._onfinish = v; + this._animation.onfinish = (function(e) { + e.target = this; + v.call(this, e); + }).bind(this); + } else { + this._animation.onfinish = v; + this.onfinish = this._animation.onfinish; + } + }, + get currentTime() { + this._updatePromises(); + var currentTime = this._animation.currentTime; + this._updatePromises(); + return currentTime; + }, + set currentTime(v) { + this._updatePromises(); + this._animation.currentTime = isFinite(v) ? v : Math.sign(v) * Number.MAX_VALUE; + this._register(); + this._forEachChild(function(child, offset) { + child.currentTime = v - offset; + }); + this._updatePromises(); + }, + get startTime() { + return this._animation.startTime; + }, + set startTime(v) { + this._updatePromises(); + this._animation.startTime = isFinite(v) ? v : Math.sign(v) * Number.MAX_VALUE; + this._register(); + this._forEachChild(function(child, offset) { + child.startTime = v + offset; + }); + this._updatePromises(); + }, + get playbackRate() { + return this._animation.playbackRate; + }, + set playbackRate(value) { + this._updatePromises(); + var oldCurrentTime = this.currentTime; + this._animation.playbackRate = value; + this._forEachChild(function(childAnimation) { + childAnimation.playbackRate = value; + }); + if (this.playState != 'paused' && this.playState != 'idle') { + this.play(); + } + if (oldCurrentTime !== null) { + this.currentTime = oldCurrentTime; + } + this._updatePromises(); + }, + play: function() { + this._updatePromises(); + this._paused = false; + this._animation.play(); + if (this._timeline._animations.indexOf(this) == -1) { + this._timeline._animations.push(this); + } + this._register(); + scope.awaitStartTime(this); + this._forEachChild(function(child) { + var time = child.currentTime; + child.play(); + child.currentTime = time; + }); + this._updatePromises(); + }, + pause: function() { + this._updatePromises(); + if (this.currentTime) { + this._holdTime = this.currentTime; + } + this._animation.pause(); + this._register(); + this._forEachChild(function(child) { + child.pause(); + }); + this._paused = true; + this._updatePromises(); + }, + finish: function() { + this._updatePromises(); + this._animation.finish(); + this._register(); + this._updatePromises(); + }, + cancel: function() { + this._updatePromises(); + this._animation.cancel(); + this._register(); + this._removeChildAnimations(); + this._updatePromises(); + }, + reverse: function() { + this._updatePromises(); + var oldCurrentTime = this.currentTime; + this._animation.reverse(); + this._forEachChild(function(childAnimation) { + childAnimation.reverse(); + }); + if (oldCurrentTime !== null) { + this.currentTime = oldCurrentTime; + } + this._updatePromises(); + }, + addEventListener: function(type, handler) { + var wrapped = handler; + if (typeof handler == 'function') { + wrapped = (function(e) { + e.target = this; + handler.call(this, e); + }).bind(this); + handler._wrapper = wrapped; + } + this._animation.addEventListener(type, wrapped); + }, + removeEventListener: function(type, handler) { + this._animation.removeEventListener(type, (handler && handler._wrapper) || handler); + }, + _removeChildAnimations: function() { + while (this._childAnimations.length) + this._childAnimations.pop().cancel(); + }, + _forEachChild: function(f) { + var offset = 0; + if (this.effect.children && this._childAnimations.length < this.effect.children.length) + this._constructChildAnimations(); + this._childAnimations.forEach(function(child) { + f.call(this, child, offset); + if (this.effect instanceof window.SequenceEffect) + offset += child.effect.activeDuration; + }.bind(this)); + + if (this.playState == 'pending') + return; + var timing = this.effect._timing; + var t = this.currentTime; + if (t !== null) + t = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), t, timing); + if (t == null || isNaN(t)) + this._removeChildAnimations(); + }, + }; + + window.Animation = scope.Animation; + + if (WEB_ANIMATIONS_TESTING) { + testing.webAnimationsNextAnimation = scope.Animation; + } + +})(webAnimationsShared, webAnimationsNext, webAnimationsTesting); diff --git a/scripts/resources/web-animations-js/target-config.js b/scripts/resources/web-animations-js/target-config.js new file mode 100644 index 0000000000..3ef9b260a5 --- /dev/null +++ b/scripts/resources/web-animations-js/target-config.js @@ -0,0 +1,138 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function() { + + var scopeSrc = [ + 'src/scope.js']; + + var webAnimations1Src = [ + 'src/keyframe-interpolations.js', + 'src/property-interpolation.js', + 'src/keyframe-effect.js', + 'src/apply-preserving-inline-style.js', + 'src/element-animatable.js', + 'src/interpolation.js', + 'src/matrix-interpolation.js', + 'src/animation.js', + 'src/tick.js', + 'src/matrix-decomposition.js', + 'src/handler-utils.js', + 'src/shadow-handler.js', + 'src/number-handler.js', + 'src/visibility-handler.js', + 'src/color-handler.js', + 'src/dimension-handler.js', + 'src/box-handler.js', + 'src/transform-handler.js', + 'src/font-weight-handler.js', + 'src/position-handler.js', + 'src/shape-handler.js', + 'src/property-names.js', + ]; + + var liteWebAnimations1Src = [ + 'src/keyframe-interpolations.js', + 'src/property-interpolation.js', + 'src/keyframe-effect.js', + 'src/apply.js', + 'src/element-animatable.js', + 'src/interpolation.js', + 'src/animation.js', + 'src/tick.js', + 'src/handler-utils.js', + 'src/shadow-handler.js', + 'src/number-handler.js', + 'src/visibility-handler.js', + 'src/color-handler.js', + 'src/dimension-handler.js', + 'src/box-handler.js', + 'src/transform-handler.js', + 'src/property-names.js', + ]; + + + var sharedSrc = [ + 'src/timing-utilities.js', + 'src/normalize-keyframes.js', + //'src/deprecation.js', + ]; + + var webAnimationsNextSrc = [ + 'src/timeline.js', + 'src/web-animations-next-animation.js', + 'src/keyframe-effect-constructor.js', + 'src/effect-callback.js', + 'src/group-constructors.js']; + + var webAnimations1Test = [ + 'test/js/animation-finish-event.js', + 'test/js/animation.js', + 'test/js/apply-preserving-inline-style.js', + 'test/js/box-handler.js', + 'test/js/color-handler.js', + 'test/js/dimension-handler.js', + 'test/js/interpolation.js', + 'test/js/keyframes.js', + 'test/js/matrix-interpolation.js', + 'test/js/number-handler.js', + 'test/js/property-interpolation.js', + 'test/js/tick.js', + 'test/js/timing-utilities.js', + 'test/js/timing.js', + 'test/js/transform-handler.js']; + + var webAnimationsNextTest = webAnimations1Test.concat( + 'test/js/effect-callback.js', + 'test/js/group-animation-finish-event.js', + 'test/js/group-animation.js', + 'test/js/group-constructors.js', + 'test/js/keyframe-effect-constructor.js', + 'test/js/timeline.js', + 'test/js/web-animations-next-animation.js'); + + // This object specifies the source and test files for different Web Animation build targets. + var targetConfig = { + 'web-animations': { + scopeSrc: scopeSrc, + sharedSrc: sharedSrc, + //webAnimations1Src: webAnimations1Src, + webAnimations1Src: liteWebAnimations1Src, + webAnimationsNextSrc: [], + src: scopeSrc.concat(sharedSrc).concat(webAnimations1Src), + test: webAnimations1Test, + }, + 'web-animations-next': { + scopeSrc: scopeSrc, + sharedSrc: sharedSrc, + webAnimations1Src: webAnimations1Src, + webAnimationsNextSrc: webAnimationsNextSrc, + src: scopeSrc.concat(sharedSrc).concat(webAnimations1Src).concat(webAnimationsNextSrc), + test: webAnimationsNextTest, + }, + 'web-animations-next-lite': { + scopeSrc: scopeSrc, + sharedSrc: sharedSrc, + webAnimations1Src: liteWebAnimations1Src, + webAnimationsNextSrc: webAnimationsNextSrc, + src: scopeSrc.concat(sharedSrc).concat(liteWebAnimations1Src).concat(webAnimationsNextSrc), + test: [], + }, + }; + + if (typeof module != 'undefined') + module.exports = targetConfig; + else + window.webAnimationsTargetConfig = targetConfig; +})(); diff --git a/scripts/resources/web-animations-js/target-loader.js b/scripts/resources/web-animations-js/target-loader.js new file mode 100644 index 0000000000..979f5c800d --- /dev/null +++ b/scripts/resources/web-animations-js/target-loader.js @@ -0,0 +1,27 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function() { + var target = webAnimationsTargetConfig.defaultTarget; + if (typeof webAnimationsSourceTarget != 'undefined') + target = webAnimationsSourceTarget; + + // Native implementation detection. + + var scripts = document.getElementsByTagName('script'); + var location = scripts[scripts.length - 1].src.replace(/[^\/]+$/, ''); + webAnimationsTargetConfig[target].src.forEach(function(sourceFile) { + document.write(''); + }); +})(); diff --git a/scripts/resources/web-animations-js/templates/boilerplate b/scripts/resources/web-animations-js/templates/boilerplate new file mode 100644 index 0000000000..5b902b59fd --- /dev/null +++ b/scripts/resources/web-animations-js/templates/boilerplate @@ -0,0 +1,13 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. diff --git a/scripts/resources/web-animations-js/templates/runner.html b/scripts/resources/web-animations-js/templates/runner.html new file mode 100644 index 0000000000..48d5d4c5e3 --- /dev/null +++ b/scripts/resources/web-animations-js/templates/runner.html @@ -0,0 +1,26 @@ + + + + + + + + + +
diff --git a/scripts/resources/web-animations-js/templates/web-animations.html b/scripts/resources/web-animations-js/templates/web-animations.html new file mode 100644 index 0000000000..4af996eac6 --- /dev/null +++ b/scripts/resources/web-animations-js/templates/web-animations.html @@ -0,0 +1,18 @@ + + +<% _.forEach(src, function(src) { %> +<% }); %> diff --git a/scripts/resources/web-animations-js/templates/web-animations.js b/scripts/resources/web-animations-js/templates/web-animations.js new file mode 100644 index 0000000000..4a81d9936f --- /dev/null +++ b/scripts/resources/web-animations-js/templates/web-animations.js @@ -0,0 +1,21 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var webAnimationsSourceTarget = '<%= target %>'; +var WEB_ANIMATIONS_TESTING = false; +(function() { + var scripts = document.getElementsByTagName('script'); + var location = scripts[scripts.length - 1].src.replace(/[^\/]+$/, ''); + document.write(''); + document.write(''); +})(); diff --git a/scripts/resources/web-animations-js/web-animations-next-lite.dev.html b/scripts/resources/web-animations-js/web-animations-next-lite.dev.html new file mode 100644 index 0000000000..27207da10e --- /dev/null +++ b/scripts/resources/web-animations-js/web-animations-next-lite.dev.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/resources/web-animations-js/web-animations-next-lite.dev.js b/scripts/resources/web-animations-js/web-animations-next-lite.dev.js new file mode 100644 index 0000000000..8cc77540a2 --- /dev/null +++ b/scripts/resources/web-animations-js/web-animations-next-lite.dev.js @@ -0,0 +1,21 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var webAnimationsSourceTarget = 'web-animations-next-lite'; +var WEB_ANIMATIONS_TESTING = false; +(function() { + var scripts = document.getElementsByTagName('script'); + var location = scripts[scripts.length - 1].src.replace(/[^\/]+$/, ''); + document.write(''); + document.write(''); +})(); diff --git a/scripts/resources/web-animations-js/web-animations-next-lite.min.js b/scripts/resources/web-animations-js/web-animations-next-lite.min.js new file mode 100644 index 0000000000..1e23be3435 --- /dev/null +++ b/scripts/resources/web-animations-js/web-animations-next-lite.min.js @@ -0,0 +1,17 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +!function(a,b){b["true"]=a;var c={},d={},e={},f=null;!function(a,b){function c(a){if("number"==typeof a)return a;var b={};for(var c in a)b[c]=a[c];return b}function d(){this._delay=0,this._endDelay=0,this._fill="none",this._iterationStart=0,this._iterations=1,this._duration=0,this._playbackRate=1,this._direction="normal",this._easing="linear"}function e(b,c,e){var f=new d;return c&&(f.fill="both",f.duration="auto"),"number"!=typeof b||isNaN(b)?void 0!==b&&Object.getOwnPropertyNames(b).forEach(function(c){if("auto"!=b[c]){if(("number"==typeof f[c]||"duration"==c)&&("number"!=typeof b[c]||isNaN(b[c])))return;if("fill"==c&&-1==t.indexOf(b[c]))return;if("direction"==c&&-1==u.indexOf(b[c]))return;if("playbackRate"==c&&1!==b[c]&&a.isDeprecated("AnimationEffectTiming.playbackRate","2014-11-28","Use Animation.playbackRate instead."))return;f[c]=b[c]}}):f.duration=b,f}function f(a){return"number"==typeof a&&(a=isNaN(a)?{duration:0}:{duration:a}),a}function g(b,c){b=a.numericTimingToObject(b);var d=e(b,c);return d._easing=j(d.easing),d}function h(a,b,c,d){return 0>a||a>1||0>c||c>1?C:function(e){function f(a,b,c){return 3*a*(1-c)*(1-c)*c+3*b*(1-c)*c*c+c*c*c}if(0==e||1==e)return e;for(var g=0,h=1;;){var i=(g+h)/2,j=f(a,c,i);if(Math.abs(e-j)<.001)return f(b,d,i);e>j?g=i:h=i}}}function i(a,b){return function(c){if(c>=1)return 1;var d=1/a;return c+=b*d,c-c%d}}function j(a){var b=A.exec(a);if(b)return h.apply(this,b.slice(1).map(Number));var c=B.exec(a);if(c)return i(Number(c[1]),{start:v,middle:w,end:x}[c[2]]);var d=y[a];return d?d:C}function k(a){return Math.abs(l(a)/a.playbackRate)}function l(a){return a.duration*a.iterations}function m(a,b,c){return null==b?D:b=c.delay+a?F:G}function n(a,b,c,d,e){switch(d){case E:return"backwards"==b||"both"==b?0:null;case G:return c-e;case F:return"forwards"==b||"both"==b?a:null;case D:return null}}function o(a,b,c,d){return(d.playbackRate<0?b-a:b)*d.playbackRate+c}function p(a,b,c,d,e){return c===1/0||c===-(1/0)||c-d==b&&e.iterations&&(e.iterations+e.iterationStart)%1==0?a:c%a}function q(a,b,c,d){return 0===c?0:b==a?d.iterationStart+d.iterations-1:Math.floor(c/a)}function r(a,b,c,d){var e=a%2>=1,f="normal"==d.direction||d.direction==(e?"alternate-reverse":"alternate"),g=f?c:b-c,h=g/b;return b*d.easing(h)}function s(a,b,c){var d=m(a,b,c),e=n(a,c.fill,b,d,c.delay);if(null===e)return null;if(0===a)return d===E?0:1;var f=c.iterationStart*c.duration,g=o(a,e,f,c),h=p(c.duration,l(c),g,f,c),i=q(c.duration,h,g,c);return r(i,c.duration,h,c)/c.duration}var t="backwards|forwards|both|none".split("|"),u="reverse|alternate|alternate-reverse".split("|");d.prototype={_setMember:function(b,c){this["_"+b]=c,this._effect&&(this._effect._timingInput[b]=c,this._effect._timing=a.normalizeTimingInput(a.normalizeTimingInput(this._effect._timingInput)),this._effect.activeDuration=a.calculateActiveDuration(this._effect._timing),this._effect._animation&&this._effect._animation._rebuildUnderlyingAnimation())},get playbackRate(){return this._playbackRate},set delay(a){this._setMember("delay",a)},get delay(){return this._delay},set endDelay(a){this._setMember("endDelay",a)},get endDelay(){return this._endDelay},set fill(a){this._setMember("fill",a)},get fill(){return this._fill},set iterationStart(a){this._setMember("iterationStart",a)},get iterationStart(){return this._iterationStart},set duration(a){this._setMember("duration",a)},get duration(){return this._duration},set direction(a){this._setMember("direction",a)},get direction(){return this._direction},set easing(a){this._setMember("easing",a)},get easing(){return this._easing},set iterations(a){this._setMember("iterations",a)},get iterations(){return this._iterations}};var v=1,w=.5,x=0,y={ease:h(.25,.1,.25,1),"ease-in":h(.42,0,1,1),"ease-out":h(0,0,.58,1),"ease-in-out":h(.42,0,.58,1),"step-start":i(1,v),"step-middle":i(1,w),"step-end":i(1,x)},z="\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*",A=new RegExp("cubic-bezier\\("+z+","+z+","+z+","+z+"\\)"),B=/steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/,C=function(a){return a},D=0,E=1,F=2,G=3;a.cloneTimingInput=c,a.makeTiming=e,a.numericTimingToObject=f,a.normalizeTimingInput=g,a.calculateActiveDuration=k,a.calculateTimeFraction=s,a.calculatePhase=m,a.toTimingFunction=j}(c,f),function(a,b){function c(a,b){return a in i?i[a][b]||b:b}function d(a,b,d){var e=f[a];if(e){g.style[a]=b;for(var h in e){var i=e[h],j=g.style[i];d[i]=c(i,j)}}else d[a]=c(a,b)}function e(b){function c(){var a=e.length;null==e[a-1].offset&&(e[a-1].offset=1),a>1&&null==e[0].offset&&(e[0].offset=0);for(var b=0,c=e[0].offset,d=1;a>d;d++){var f=e[d].offset;if(null!=f){for(var g=1;d-b>g;g++)e[b+g].offset=c+(f-c)*g/(d-b);b=d,c=f}}}if(!Array.isArray(b)&&null!==b)throw new TypeError("Keyframes must be null or an array of keyframes");if(null==b)return[];for(var e=b.map(function(b){var c={};for(var e in b){var f=b[e];if("offset"==e){if(null!=f&&(f=Number(f),!isFinite(f)))throw new TypeError("keyframe offsets must be numbers.")}else{if("composite"==e)throw{type:DOMException.NOT_SUPPORTED_ERR,name:"NotSupportedError",message:"add compositing is not supported"};f="easing"==e?a.toTimingFunction(f):""+f}d(e,f,c)}return void 0==c.offset&&(c.offset=null),void 0==c.easing&&(c.easing=a.toTimingFunction("linear")),c}),f=!0,g=-(1/0),h=0;hi)throw{code:DOMException.INVALID_MODIFICATION_ERR,name:"InvalidModificationError",message:"Keyframes are not loosely sorted by offset. Sort or specify offsets."};g=i}else f=!1}return e=e.filter(function(a){return a.offset>=0&&a.offset<=1}),f||c(),e}var f={background:["backgroundImage","backgroundPosition","backgroundSize","backgroundRepeat","backgroundAttachment","backgroundOrigin","backgroundClip","backgroundColor"],border:["borderTopColor","borderTopStyle","borderTopWidth","borderRightColor","borderRightStyle","borderRightWidth","borderBottomColor","borderBottomStyle","borderBottomWidth","borderLeftColor","borderLeftStyle","borderLeftWidth"],borderBottom:["borderBottomWidth","borderBottomStyle","borderBottomColor"],borderColor:["borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"],borderLeft:["borderLeftWidth","borderLeftStyle","borderLeftColor"],borderRadius:["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],borderRight:["borderRightWidth","borderRightStyle","borderRightColor"],borderTop:["borderTopWidth","borderTopStyle","borderTopColor"],borderWidth:["borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth"],flex:["flexGrow","flexShrink","flexBasis"],font:["fontFamily","fontSize","fontStyle","fontVariant","fontWeight","lineHeight"],margin:["marginTop","marginRight","marginBottom","marginLeft"],outline:["outlineColor","outlineStyle","outlineWidth"],padding:["paddingTop","paddingRight","paddingBottom","paddingLeft"]},g=document.createElementNS("http://www.w3.org/1999/xhtml","div"),h={thin:"1px",medium:"3px",thick:"5px"},i={borderBottomWidth:h,borderLeftWidth:h,borderRightWidth:h,borderTopWidth:h,fontSize:{"xx-small":"60%","x-small":"75%",small:"89%",medium:"100%",large:"120%","x-large":"150%","xx-large":"200%"},fontWeight:{normal:"400",bold:"700"},outlineWidth:h,textShadow:{none:"0px 0px 0px transparent"},boxShadow:{none:"0px 0px 0px 0px transparent"}};a.normalizeKeyframes=e}(c,f),function(){if(document.documentElement.animate){var a=document.documentElement.animate([],0),b=!0;if(a&&(b=!1,"play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(c){void 0===a[c]&&(b=!0)})),!b)return}!function(a,b,c){function d(a){for(var b={},c=0;c=c&&0==a.startTime||c>=1&&1==a.endTime||c>=a.startTime&&c<=a.endTime}).forEach(function(d){var e=c-d.startTime,f=d.endTime-d.startTime,g=0==f?0:d.easing(e/f);b.apply(a,d.property,d.interpolation(g))});else for(var d in g)"offset"!=d&&"easing"!=d&&"composite"!=d&&b.clear(a,d)}}}(c,d,f),function(a,b){function c(a,b,c){f[c]=f[c]||[],f[c].push([a,b])}function d(a,b,d){for(var e=0;ed?a:b;if(a.length==b.length){for(var e=[],f=0;f0?this._totalDuration:0),this._ensureAlive())},get currentTime(){return this._idle||this._currentTimePending?null:this._currentTime},set currentTime(a){a=+a,isNaN(a)||(b.restart(),this._paused||null==this._startTime||(this._startTime=this._timeline.currentTime-a/this._playbackRate),this._currentTimePending=!1,this._currentTime!=a&&(this._tickCurrentTime(a,!0),b.invalidateEffects()))},get startTime(){return this._startTime},set startTime(a){a=+a,isNaN(a)||this._paused||this._idle||(this._startTime=a,this._tickCurrentTime((this._timeline.currentTime-this._startTime)*this.playbackRate),b.invalidateEffects())},get playbackRate(){return this._playbackRate},set playbackRate(a){if(a!=this._playbackRate){var b=this.currentTime;this._playbackRate=a,this._startTime=null,"paused"!=this.playState&&"idle"!=this.playState&&this.play(),null!=b&&(this.currentTime=b)}},get _isFinished(){return!this._idle&&(this._playbackRate>0&&this._currentTime>=this._totalDuration||this._playbackRate<0&&this._currentTime<=0)},get _totalDuration(){return this._effect._totalDuration},get playState(){return this._idle?"idle":null==this._startTime&&!this._paused&&0!=this.playbackRate||this._currentTimePending?"pending":this._paused?"paused":this._isFinished?"finished":"running"},play:function(){this._paused=!1,(this._isFinished||this._idle)&&(this._currentTime=this._playbackRate>0?0:this._totalDuration,this._startTime=null,b.invalidateEffects()),this._finishedFlag=!1,b.restart(),this._idle=!1,this._ensureAlive()},pause:function(){this._isFinished||this._paused||this._idle||(this._currentTimePending=!0),this._startTime=null,this._paused=!0},finish:function(){this._idle||(this.currentTime=this._playbackRate>0?this._totalDuration:0,this._startTime=this._totalDuration-this.currentTime,this._currentTimePending=!1)},cancel:function(){this._inEffect&&(this._inEffect=!1,this._idle=!0,this.currentTime=0,this._startTime=null,this._effect._update(null),b.invalidateEffects(),b.restart())},reverse:function(){this.playbackRate*=-1,this.play()},addEventListener:function(a,b){"function"==typeof b&&"finish"==a&&this._finishHandlers.push(b)},removeEventListener:function(a,b){if("finish"==a){var c=this._finishHandlers.indexOf(b);c>=0&&this._finishHandlers.splice(c,1)}},_fireEvents:function(a){var b=this._isFinished;if((b||this._idle)&&!this._finishedFlag){var c=new d(this,this._currentTime,a),e=this._finishHandlers.concat(this.onfinish?[this.onfinish]:[]);e.forEach(function(a){a.call(c.target,c)})}this._finishedFlag=b},_tick:function(a){return this._idle||this._paused||(null==this._startTime?this.startTime=a-this._currentTime/this.playbackRate:this._isFinished||this._tickCurrentTime((a-this._startTime)*this.playbackRate)),this._currentTimePending=!1,this._fireEvents(a),!this._idle&&(this._inEffect||!this._finishedFlag)}}}(c,d,f),function(a,b,c){function d(a){var b=j;j=[],a0&&(t.currentTime+=r*(Math.floor((a-t.currentTime)/r)+1)),h(t.currentTime)}return g(),s.apply(this,arguments)}});var t=new f;b.timeline=t}(c,d,f),function(a){function b(a,b){var c=a.exec(b);return c?(c=a.ignoreCase?c[0].toLowerCase():c[0],[c,b.substr(c.length)]):void 0}function c(a,b){b=b.replace(/^\s*/,"");var c=a(b);return c?[c[0],c[1].replace(/^\s*/,"")]:void 0}function d(a,d,e){a=c.bind(null,a);for(var f=[];;){var g=a(e);if(!g)return[f,e];if(f.push(g[0]),e=g[1],g=b(d,e),!g||""==g[1])return[f,e];e=g[1]}}function e(a,b){for(var c=0,d=0;d=c))break;var e=a(b.substr(0,d));return void 0==e?void 0:[e,b.substr(d)]}function f(a,b){for(var c=a,d=b;c&&d;)c>d?c%=d:d%=c;return c=a*b/(c+d)}function g(a){return function(b){var c=a(b);return c&&(c[0]=void 0),c}}function h(a,b){return function(c){var d=a(c);return d?d:[b,c]}}function i(b,c){for(var d=[],e=0;ek;k++){var l=b(d[k%d.length],e[k%e.length]);if(!l)return;g.push(l[0]),h.push(l[1]),i.push(l[2])}return[g,h,function(b){var d=b.map(function(a,b){return i[b](a)}).join(c);return a?a(d):d}]}function k(a,b,c){for(var d=[],e=[],f=[],g=0,h=0;h=c?a:c>=1?b:"visible"}]:void 0}a.addPropertiesHandler(String,c,["visibility"])}(d),function(a,b){function c(a){a=a.trim(),f.fillStyle="#000",f.fillStyle=a;var b=f.fillStyle;if(f.fillStyle="#fff",f.fillStyle=a,b==f.fillStyle){f.fillRect(0,0,1,1);var c=f.getImageData(0,0,1,1).data;f.clearRect(0,0,1,1);var d=c[3]/255;return[c[0]*d,c[1]*d,c[2]*d,d]}}function d(b,c){return[b,c,function(b){function c(a){return Math.max(0,Math.min(255,a))}if(b[3])for(var d=0;3>d;d++)b[d]=Math.round(c(b[d]/b[3]));return b[3]=a.numberToString(a.clamp(0,1,b[3])),"rgba("+b.join(",")+")"}]}var e=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");e.width=e.height=1;var f=e.getContext("2d");a.addPropertiesHandler(c,d,["background-color","border-bottom-color","border-left-color","border-right-color","border-top-color","color","outline-color","text-decoration-color"]),a.consumeColor=a.consumeParenthesised.bind(null,c),a.mergeColors=d}(d,f),function(a,b){function c(a,b){if(b=b.trim().toLowerCase(),"0"==b&&"px".search(a)>=0)return{px:0};if(/^[^(]*$|^calc/.test(b)){b=b.replace(/calc\(/g,"(");var c={};b=b.replace(a,function(a){return c[a]=null,"U"+a});for(var d="U("+a.source+")",e=b.replace(/[-+]?(\d*\.)?\d+/g,"N").replace(new RegExp("N"+d,"g"),"D").replace(/\s[+-]\s/g,"O").replace(/\s/g,""),f=[/N\*(D)/g,/(N|D)[*/]N/g,/(N|D)O\1/g,/\((N|D)\)/g],g=0;g1?"calc("+c+")":c}]}var f="px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc",g=c.bind(null,new RegExp(f,"g")),h=c.bind(null,new RegExp(f+"|%","g")),i=c.bind(null,/deg|rad|grad|turn/g);a.parseLength=g,a.parseLengthOrPercent=h,a.consumeLengthOrPercent=a.consumeParenthesised.bind(null,h),a.parseAngle=i,a.mergeDimensions=e;var j=a.consumeParenthesised.bind(null,g),k=a.consumeRepeated.bind(void 0,j,/^/),l=a.consumeRepeated.bind(void 0,k,/^,/);a.consumeSizePairList=l;var m=function(a){var b=l(a);return b&&""==b[1]?b[0]:void 0},n=a.mergeNestedRepeated.bind(void 0,d," "),o=a.mergeNestedRepeated.bind(void 0,n,",");a.mergeNonNegativeSizePair=n,a.addPropertiesHandler(m,o,["background-size"]),a.addPropertiesHandler(h,d,["border-bottom-width","border-image-width","border-left-width","border-right-width","border-top-width","flex-basis","font-size","height","line-height","max-height","max-width","outline-width","width"]),a.addPropertiesHandler(h,e,["border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","bottom","left","letter-spacing","margin-bottom","margin-left","margin-right","margin-top","min-height","min-width","outline-offset","padding-bottom","padding-left","padding-right","padding-top","perspective","right","shape-margin","text-indent","top","vertical-align","word-spacing"])}(d,f),function(a,b){function c(b){return a.consumeLengthOrPercent(b)||a.consumeToken(/^auto/,b)}function d(b){var d=a.consumeList([a.ignore(a.consumeToken.bind(null,/^rect/)),a.ignore(a.consumeToken.bind(null,/^\(/)),a.consumeRepeated.bind(null,c,/^,/),a.ignore(a.consumeToken.bind(null,/^\)/))],b);return d&&4==d[0].length?d[0]:void 0}function e(b,c){return"auto"==b||"auto"==c?[!0,!1,function(d){var e=d?b:c;if("auto"==e)return"auto";var f=a.mergeDimensions(e,e);return f[2](f[0])}]:a.mergeDimensions(b,c)}function f(a){return"rect("+a+")"}var g=a.mergeWrappedNestedRepeated.bind(null,f,e,", ");a.parseBox=d,a.mergeBoxes=g,a.addPropertiesHandler(d,g,["clip"])}(d,f),function(a,b){function c(a){return function(b){var c=0;return a.map(function(a){return a===k?b[c++]:a})}}function d(a){return a}function e(b){if(b=b.toLowerCase().trim(),"none"==b)return[];for(var c,d=/\s*(\w+)\(([^)]*)\)/g,e=[],f=0;c=d.exec(b);){if(c.index!=f)return;f=c.index+c[0].length;var g=c[1],h=n[g];if(!h)return;var i=c[2].split(","),j=h[0];if(j.length + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/resources/web-animations-js/web-animations-next.dev.js b/scripts/resources/web-animations-js/web-animations-next.dev.js new file mode 100644 index 0000000000..8f2a4e2971 --- /dev/null +++ b/scripts/resources/web-animations-js/web-animations-next.dev.js @@ -0,0 +1,21 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var webAnimationsSourceTarget = 'web-animations-next'; +var WEB_ANIMATIONS_TESTING = false; +(function() { + var scripts = document.getElementsByTagName('script'); + var location = scripts[scripts.length - 1].src.replace(/[^\/]+$/, ''); + document.write(''); + document.write(''); +})(); diff --git a/scripts/resources/web-animations-js/web-animations-next.min.js b/scripts/resources/web-animations-js/web-animations-next.min.js new file mode 100644 index 0000000000..6e64033cf4 --- /dev/null +++ b/scripts/resources/web-animations-js/web-animations-next.min.js @@ -0,0 +1,17 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +!function(a,b){b["true"]=a;var c={},d={},e={},f=null;!function(a,b){function c(a){if("number"==typeof a)return a;var b={};for(var c in a)b[c]=a[c];return b}function d(){this._delay=0,this._endDelay=0,this._fill="none",this._iterationStart=0,this._iterations=1,this._duration=0,this._playbackRate=1,this._direction="normal",this._easing="linear"}function e(b,c,e){var f=new d;return c&&(f.fill="both",f.duration="auto"),"number"!=typeof b||isNaN(b)?void 0!==b&&Object.getOwnPropertyNames(b).forEach(function(c){if("auto"!=b[c]){if(("number"==typeof f[c]||"duration"==c)&&("number"!=typeof b[c]||isNaN(b[c])))return;if("fill"==c&&-1==t.indexOf(b[c]))return;if("direction"==c&&-1==u.indexOf(b[c]))return;if("playbackRate"==c&&1!==b[c]&&a.isDeprecated("AnimationEffectTiming.playbackRate","2014-11-28","Use Animation.playbackRate instead."))return;f[c]=b[c]}}):f.duration=b,f}function f(a){return"number"==typeof a&&(a=isNaN(a)?{duration:0}:{duration:a}),a}function g(b,c){b=a.numericTimingToObject(b);var d=e(b,c);return d._easing=j(d.easing),d}function h(a,b,c,d){return 0>a||a>1||0>c||c>1?C:function(e){function f(a,b,c){return 3*a*(1-c)*(1-c)*c+3*b*(1-c)*c*c+c*c*c}if(0==e||1==e)return e;for(var g=0,h=1;;){var i=(g+h)/2,j=f(a,c,i);if(Math.abs(e-j)<.001)return f(b,d,i);e>j?g=i:h=i}}}function i(a,b){return function(c){if(c>=1)return 1;var d=1/a;return c+=b*d,c-c%d}}function j(a){var b=A.exec(a);if(b)return h.apply(this,b.slice(1).map(Number));var c=B.exec(a);if(c)return i(Number(c[1]),{start:v,middle:w,end:x}[c[2]]);var d=y[a];return d?d:C}function k(a){return Math.abs(l(a)/a.playbackRate)}function l(a){return a.duration*a.iterations}function m(a,b,c){return null==b?D:b=c.delay+a?F:G}function n(a,b,c,d,e){switch(d){case E:return"backwards"==b||"both"==b?0:null;case G:return c-e;case F:return"forwards"==b||"both"==b?a:null;case D:return null}}function o(a,b,c,d){return(d.playbackRate<0?b-a:b)*d.playbackRate+c}function p(a,b,c,d,e){return c===1/0||c===-(1/0)||c-d==b&&e.iterations&&(e.iterations+e.iterationStart)%1==0?a:c%a}function q(a,b,c,d){return 0===c?0:b==a?d.iterationStart+d.iterations-1:Math.floor(c/a)}function r(a,b,c,d){var e=a%2>=1,f="normal"==d.direction||d.direction==(e?"alternate-reverse":"alternate"),g=f?c:b-c,h=g/b;return b*d.easing(h)}function s(a,b,c){var d=m(a,b,c),e=n(a,c.fill,b,d,c.delay);if(null===e)return null;if(0===a)return d===E?0:1;var f=c.iterationStart*c.duration,g=o(a,e,f,c),h=p(c.duration,l(c),g,f,c),i=q(c.duration,h,g,c);return r(i,c.duration,h,c)/c.duration}var t="backwards|forwards|both|none".split("|"),u="reverse|alternate|alternate-reverse".split("|");d.prototype={_setMember:function(b,c){this["_"+b]=c,this._effect&&(this._effect._timingInput[b]=c,this._effect._timing=a.normalizeTimingInput(a.normalizeTimingInput(this._effect._timingInput)),this._effect.activeDuration=a.calculateActiveDuration(this._effect._timing),this._effect._animation&&this._effect._animation._rebuildUnderlyingAnimation())},get playbackRate(){return this._playbackRate},set delay(a){this._setMember("delay",a)},get delay(){return this._delay},set endDelay(a){this._setMember("endDelay",a)},get endDelay(){return this._endDelay},set fill(a){this._setMember("fill",a)},get fill(){return this._fill},set iterationStart(a){this._setMember("iterationStart",a)},get iterationStart(){return this._iterationStart},set duration(a){this._setMember("duration",a)},get duration(){return this._duration},set direction(a){this._setMember("direction",a)},get direction(){return this._direction},set easing(a){this._setMember("easing",a)},get easing(){return this._easing},set iterations(a){this._setMember("iterations",a)},get iterations(){return this._iterations}};var v=1,w=.5,x=0,y={ease:h(.25,.1,.25,1),"ease-in":h(.42,0,1,1),"ease-out":h(0,0,.58,1),"ease-in-out":h(.42,0,.58,1),"step-start":i(1,v),"step-middle":i(1,w),"step-end":i(1,x)},z="\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*",A=new RegExp("cubic-bezier\\("+z+","+z+","+z+","+z+"\\)"),B=/steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/,C=function(a){return a},D=0,E=1,F=2,G=3;a.cloneTimingInput=c,a.makeTiming=e,a.numericTimingToObject=f,a.normalizeTimingInput=g,a.calculateActiveDuration=k,a.calculateTimeFraction=s,a.calculatePhase=m,a.toTimingFunction=j}(c,f),function(a,b){function c(a,b){return a in i?i[a][b]||b:b}function d(a,b,d){var e=f[a];if(e){g.style[a]=b;for(var h in e){var i=e[h],j=g.style[i];d[i]=c(i,j)}}else d[a]=c(a,b)}function e(b){function c(){var a=e.length;null==e[a-1].offset&&(e[a-1].offset=1),a>1&&null==e[0].offset&&(e[0].offset=0);for(var b=0,c=e[0].offset,d=1;a>d;d++){var f=e[d].offset;if(null!=f){for(var g=1;d-b>g;g++)e[b+g].offset=c+(f-c)*g/(d-b);b=d,c=f}}}if(!Array.isArray(b)&&null!==b)throw new TypeError("Keyframes must be null or an array of keyframes");if(null==b)return[];for(var e=b.map(function(b){var c={};for(var e in b){var f=b[e];if("offset"==e){if(null!=f&&(f=Number(f),!isFinite(f)))throw new TypeError("keyframe offsets must be numbers.")}else{if("composite"==e)throw{type:DOMException.NOT_SUPPORTED_ERR,name:"NotSupportedError",message:"add compositing is not supported"};f="easing"==e?a.toTimingFunction(f):""+f}d(e,f,c)}return void 0==c.offset&&(c.offset=null),void 0==c.easing&&(c.easing=a.toTimingFunction("linear")),c}),f=!0,g=-(1/0),h=0;hi)throw{code:DOMException.INVALID_MODIFICATION_ERR,name:"InvalidModificationError",message:"Keyframes are not loosely sorted by offset. Sort or specify offsets."};g=i}else f=!1}return e=e.filter(function(a){return a.offset>=0&&a.offset<=1}),f||c(),e}var f={background:["backgroundImage","backgroundPosition","backgroundSize","backgroundRepeat","backgroundAttachment","backgroundOrigin","backgroundClip","backgroundColor"],border:["borderTopColor","borderTopStyle","borderTopWidth","borderRightColor","borderRightStyle","borderRightWidth","borderBottomColor","borderBottomStyle","borderBottomWidth","borderLeftColor","borderLeftStyle","borderLeftWidth"],borderBottom:["borderBottomWidth","borderBottomStyle","borderBottomColor"],borderColor:["borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"],borderLeft:["borderLeftWidth","borderLeftStyle","borderLeftColor"],borderRadius:["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],borderRight:["borderRightWidth","borderRightStyle","borderRightColor"],borderTop:["borderTopWidth","borderTopStyle","borderTopColor"],borderWidth:["borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth"],flex:["flexGrow","flexShrink","flexBasis"],font:["fontFamily","fontSize","fontStyle","fontVariant","fontWeight","lineHeight"],margin:["marginTop","marginRight","marginBottom","marginLeft"],outline:["outlineColor","outlineStyle","outlineWidth"],padding:["paddingTop","paddingRight","paddingBottom","paddingLeft"]},g=document.createElementNS("http://www.w3.org/1999/xhtml","div"),h={thin:"1px",medium:"3px",thick:"5px"},i={borderBottomWidth:h,borderLeftWidth:h,borderRightWidth:h,borderTopWidth:h,fontSize:{"xx-small":"60%","x-small":"75%",small:"89%",medium:"100%",large:"120%","x-large":"150%","xx-large":"200%"},fontWeight:{normal:"400",bold:"700"},outlineWidth:h,textShadow:{none:"0px 0px 0px transparent"},boxShadow:{none:"0px 0px 0px 0px transparent"}};a.normalizeKeyframes=e}(c,f),function(){if(document.documentElement.animate){var a=document.documentElement.animate([],0),b=!0;if(a&&(b=!1,"play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(c){void 0===a[c]&&(b=!0)})),!b)return}!function(a,b,c){function d(a){for(var b={},c=0;c=c&&0==a.startTime||c>=1&&1==a.endTime||c>=a.startTime&&c<=a.endTime}).forEach(function(d){var e=c-d.startTime,f=d.endTime-d.startTime,g=0==f?0:d.easing(e/f);b.apply(a,d.property,d.interpolation(g))});else for(var d in g)"offset"!=d&&"easing"!=d&&"composite"!=d&&b.clear(a,d)}}}(c,d,f),function(a,b){function c(a,b,c){f[c]=f[c]||[],f[c].push([a,b])}function d(a,b,d){for(var e=0;ethis._surrogateStyle.length;)this._length--,Object.defineProperty(this,this._length,{configurable:!0,enumerable:!1,value:void 0})},_set:function(a,b){this._style[a]=b,this._isAnimatedProperty[a]=!0},_clear:function(a){this._style[a]=this._surrogateStyle[a],delete this._isAnimatedProperty[a]}};for(var i in g)d.prototype[i]=function(a,b){return function(){var c=this._surrogateStyle[a].apply(this._surrogateStyle,arguments);return b&&(this._isAnimatedProperty[arguments[0]]||this._style[a].apply(this._style,arguments),this._updateIndices()),c}}(i,i in h);for(var j in document.documentElement.style)j in f||j in g||!function(a){c(d.prototype,a,{get:function(){return this._surrogateStyle[a]},set:function(b){this._surrogateStyle[a]=b,this._updateIndices(),this._isAnimatedProperty[a]||(this._style[a]=b)}})}(j);a.apply=function(b,c,d){e(b),b.style._set(a.propertyName(c),d)},a.clear=function(b,c){b._webAnimationsPatchedStyle&&b.style._clear(a.propertyName(c))}}(d,f),function(a){window.Element.prototype.animate=function(b,c){return a.timeline._play(a.KeyframeEffect(this,b,c))}}(d),function(a,b){function c(a,b,d){if("number"==typeof a&&"number"==typeof b)return a*(1-d)+b*d;if("boolean"==typeof a&&"boolean"==typeof b)return.5>d?a:b;if(a.length==b.length){for(var e=[],f=0;fj;j++)g.push(b[j]*(Math.cos(e*h)-f*i)+d[j]*i);return g}var e=function(){function a(a,b){for(var c=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],d=0;4>d;d++)for(var e=0;4>e;e++)for(var f=0;4>f;f++)c[d][e]+=b[d][f]*a[f][e];return c}function b(a){return 0==a[0][2]&&0==a[0][3]&&0==a[1][2]&&0==a[1][3]&&0==a[2][0]&&0==a[2][1]&&1==a[2][2]&&0==a[2][3]&&0==a[3][2]&&1==a[3][3]}function c(c,d,e,f,g){for(var h=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],i=0;4>i;i++)h[i][3]=g[i];for(var i=0;3>i;i++)for(var j=0;3>j;j++)h[3][i]+=c[j]*h[j][i];var k=f[0],l=f[1],m=f[2],n=f[3],o=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];o[0][0]=1-2*(l*l+m*m),o[0][1]=2*(k*l-m*n),o[0][2]=2*(k*m+l*n),o[1][0]=2*(k*l+m*n),o[1][1]=1-2*(k*k+m*m),o[1][2]=2*(l*m-k*n),o[2][0]=2*(k*m-l*n),o[2][1]=2*(l*m+k*n),o[2][2]=1-2*(k*k+l*l),h=a(h,o);var p=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];e[2]&&(p[2][1]=e[2],h=a(h,p)),e[1]&&(p[2][1]=0,p[2][0]=e[0],h=a(h,p)),e[0]&&(p[2][0]=0,p[1][0]=e[0],h=a(h,p));for(var i=0;3>i;i++)for(var j=0;3>j;j++)h[i][j]*=d[i];return b(h)?[h[0][0],h[0][1],h[1][0],h[1][1],h[3][0],h[3][1]]:h[0].concat(h[1],h[2],h[3])}return c}();a.composeMatrix=e,a.quat=d}(d,f),function(a,b,c){a.sequenceNumber=0;var d=function(a,b,c){this.target=a,this.currentTime=b,this.timelineTime=c,this.type="finish",this.bubbles=!1,this.cancelable=!1,this.currentTarget=a,this.defaultPrevented=!1,this.eventPhase=Event.AT_TARGET,this.timeStamp=Date.now()};b.Animation=function(b){this._sequenceNumber=a.sequenceNumber++,this._currentTime=0,this._startTime=null,this._paused=!1,this._playbackRate=1,this._inTimeline=!0,this._finishedFlag=!1,this.onfinish=null,this._finishHandlers=[],this._effect=b,this._inEffect=this._effect._update(0),this._idle=!0,this._currentTimePending=!1},b.Animation.prototype={_ensureAlive:function(){this.playbackRate<0&&0===this.currentTime?this._inEffect=this._effect._update(-1):this._inEffect=this._effect._update(this.currentTime),this._inTimeline||!this._inEffect&&this._finishedFlag||(this._inTimeline=!0,b.timeline._animations.push(this))},_tickCurrentTime:function(a,b){a!=this._currentTime&&(this._currentTime=a,this._isFinished&&!b&&(this._currentTime=this._playbackRate>0?this._totalDuration:0),this._ensureAlive())},get currentTime(){return this._idle||this._currentTimePending?null:this._currentTime},set currentTime(a){a=+a,isNaN(a)||(b.restart(),this._paused||null==this._startTime||(this._startTime=this._timeline.currentTime-a/this._playbackRate),this._currentTimePending=!1,this._currentTime!=a&&(this._tickCurrentTime(a,!0),b.invalidateEffects()))},get startTime(){return this._startTime},set startTime(a){a=+a,isNaN(a)||this._paused||this._idle||(this._startTime=a,this._tickCurrentTime((this._timeline.currentTime-this._startTime)*this.playbackRate),b.invalidateEffects())},get playbackRate(){return this._playbackRate},set playbackRate(a){if(a!=this._playbackRate){var b=this.currentTime;this._playbackRate=a,this._startTime=null,"paused"!=this.playState&&"idle"!=this.playState&&this.play(),null!=b&&(this.currentTime=b)}},get _isFinished(){return!this._idle&&(this._playbackRate>0&&this._currentTime>=this._totalDuration||this._playbackRate<0&&this._currentTime<=0)},get _totalDuration(){return this._effect._totalDuration},get playState(){return this._idle?"idle":null==this._startTime&&!this._paused&&0!=this.playbackRate||this._currentTimePending?"pending":this._paused?"paused":this._isFinished?"finished":"running"},play:function(){this._paused=!1,(this._isFinished||this._idle)&&(this._currentTime=this._playbackRate>0?0:this._totalDuration,this._startTime=null,b.invalidateEffects()),this._finishedFlag=!1,b.restart(),this._idle=!1,this._ensureAlive()},pause:function(){this._isFinished||this._paused||this._idle||(this._currentTimePending=!0),this._startTime=null,this._paused=!0},finish:function(){this._idle||(this.currentTime=this._playbackRate>0?this._totalDuration:0,this._startTime=this._totalDuration-this.currentTime,this._currentTimePending=!1)},cancel:function(){this._inEffect&&(this._inEffect=!1,this._idle=!0,this.currentTime=0,this._startTime=null,this._effect._update(null),b.invalidateEffects(),b.restart())},reverse:function(){this.playbackRate*=-1,this.play()},addEventListener:function(a,b){"function"==typeof b&&"finish"==a&&this._finishHandlers.push(b)},removeEventListener:function(a,b){if("finish"==a){var c=this._finishHandlers.indexOf(b);c>=0&&this._finishHandlers.splice(c,1)}},_fireEvents:function(a){var b=this._isFinished;if((b||this._idle)&&!this._finishedFlag){var c=new d(this,this._currentTime,a),e=this._finishHandlers.concat(this.onfinish?[this.onfinish]:[]);e.forEach(function(a){a.call(c.target,c)})}this._finishedFlag=b},_tick:function(a){return this._idle||this._paused||(null==this._startTime?this.startTime=a-this._currentTime/this.playbackRate:this._isFinished||this._tickCurrentTime((a-this._startTime)*this.playbackRate)),this._currentTimePending=!1,this._fireEvents(a),!this._idle&&(this._inEffect||!this._finishedFlag)}}}(c,d,f),function(a,b,c){function d(a){var b=j;j=[],a0&&(t.currentTime+=r*(Math.floor((a-t.currentTime)/r)+1)),h(t.currentTime)}return g(),s.apply(this,arguments)}});var t=new f;b.timeline=t}(c,d,f),function(a,b){function c(a,b){for(var c=0,d=0;do;o++){for(var p=0,q=0;3>q;q++)p+=b[3][q]*m[q][o];n.push(p)}return n.push(1),m.push(n),m}function d(a){return[[a[0][0],a[1][0],a[2][0],a[3][0]],[a[0][1],a[1][1],a[2][1],a[3][1]],[a[0][2],a[1][2],a[2][2],a[3][2]],[a[0][3],a[1][3],a[2][3],a[3][3]]]}function e(a,b){for(var c=[],d=0;4>d;d++){for(var e=0,f=0;4>f;f++)e+=a[f]*b[f][d];c.push(e)}return c}function f(a){var b=g(a);return[a[0]/b,a[1]/b,a[2]/b]}function g(a){return Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2])}function h(a,b,c,d){return[c*a[0]+d*b[0],c*a[1]+d*b[1],c*a[2]+d*b[2]]}function i(a,b){return[a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]]}function j(j){var k=[j.slice(0,4),j.slice(4,8),j.slice(8,12),j.slice(12,16)];if(1!==k[3][3])return null;for(var l=[],m=0;4>m;m++)l.push(k[m].slice());for(var m=0;3>m;m++)l[m][3]=0;if(0===a(l))return!1;var n,o=[];if(k[0][3]||k[1][3]||k[2][3]){o.push(k[0][3]),o.push(k[1][3]),o.push(k[2][3]),o.push(k[3][3]);var p=b(l),q=d(p);n=e(o,q)}else n=[0,0,0,1];var r=k[3].slice(0,3),s=[];s.push(k[0].slice(0,3));var t=[];t.push(g(s[0])),s[0]=f(s[0]);var u=[];s.push(k[1].slice(0,3)),u.push(c(s[0],s[1])),s[1]=h(s[1],s[0],1,-u[0]),t.push(g(s[1])),s[1]=f(s[1]),u[0]/=t[1],s.push(k[2].slice(0,3)),u.push(c(s[0],s[2])),s[2]=h(s[2],s[0],1,-u[1]),u.push(c(s[1],s[2])),s[2]=h(s[2],s[1],1,-u[2]),t.push(g(s[2])),s[2]=f(s[2]),u[1]/=t[2],u[2]/=t[2];var v=i(s[1],s[2]);if(c(s[0],v)<0)for(var m=0;3>m;m++)t[m]*=-1,s[m][0]*=-1,s[m][1]*=-1,s[m][2]*=-1;var w,x,y=s[0][0]+s[1][1]+s[2][2]+1;return y>1e-4?(w=.5/Math.sqrt(y),x=[(s[2][1]-s[1][2])*w,(s[0][2]-s[2][0])*w,(s[1][0]-s[0][1])*w,.25/w]):s[0][0]>s[1][1]&&s[0][0]>s[2][2]?(w=2*Math.sqrt(1+s[0][0]-s[1][1]-s[2][2]),x=[.25*w,(s[0][1]+s[1][0])/w,(s[0][2]+s[2][0])/w,(s[2][1]-s[1][2])/w]):s[1][1]>s[2][2]?(w=2*Math.sqrt(1+s[1][1]-s[0][0]-s[2][2]),x=[(s[0][1]+s[1][0])/w,.25*w,(s[1][2]+s[2][1])/w,(s[0][2]-s[2][0])/w]):(w=2*Math.sqrt(1+s[2][2]-s[0][0]-s[1][1]),x=[(s[0][2]+s[2][0])/w,(s[1][2]+s[2][1])/w,.25*w,(s[1][0]-s[0][1])/w]),[r,t,u,x,n]}return j}();a.dot=c,a.makeMatrixDecomposition=g}(d,f),function(a){function b(a,b){var c=a.exec(b);return c?(c=a.ignoreCase?c[0].toLowerCase():c[0],[c,b.substr(c.length)]):void 0}function c(a,b){b=b.replace(/^\s*/,"");var c=a(b);return c?[c[0],c[1].replace(/^\s*/,"")]:void 0}function d(a,d,e){a=c.bind(null,a);for(var f=[];;){var g=a(e);if(!g)return[f,e];if(f.push(g[0]),e=g[1],g=b(d,e),!g||""==g[1])return[f,e];e=g[1]}}function e(a,b){for(var c=0,d=0;d=c))break;var e=a(b.substr(0,d));return void 0==e?void 0:[e,b.substr(d)]}function f(a,b){for(var c=a,d=b;c&&d;)c>d?c%=d:d%=c;return c=a*b/(c+d)}function g(a){return function(b){var c=a(b);return c&&(c[0]=void 0),c}}function h(a,b){return function(c){var d=a(c);return d?d:[b,c]}}function i(b,c){for(var d=[],e=0;ek;k++){var l=b(d[k%d.length],e[k%e.length]);if(!l)return;g.push(l[0]),h.push(l[1]),i.push(l[2])}return[g,h,function(b){var d=b.map(function(a,b){return i[b](a)}).join(c);return a?a(d):d}]}function k(a,b,c){for(var d=[],e=[],f=[],g=0,h=0;h=c?a:c>=1?b:"visible"}]:void 0}a.addPropertiesHandler(String,c,["visibility"])}(d),function(a,b){function c(a){a=a.trim(),f.fillStyle="#000",f.fillStyle=a;var b=f.fillStyle;if(f.fillStyle="#fff",f.fillStyle=a,b==f.fillStyle){f.fillRect(0,0,1,1);var c=f.getImageData(0,0,1,1).data;f.clearRect(0,0,1,1);var d=c[3]/255;return[c[0]*d,c[1]*d,c[2]*d,d]}}function d(b,c){return[b,c,function(b){function c(a){return Math.max(0,Math.min(255,a))}if(b[3])for(var d=0;3>d;d++)b[d]=Math.round(c(b[d]/b[3]));return b[3]=a.numberToString(a.clamp(0,1,b[3])),"rgba("+b.join(",")+")"}]}var e=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");e.width=e.height=1;var f=e.getContext("2d");a.addPropertiesHandler(c,d,["background-color","border-bottom-color","border-left-color","border-right-color","border-top-color","color","outline-color","text-decoration-color"]),a.consumeColor=a.consumeParenthesised.bind(null,c),a.mergeColors=d}(d,f),function(a,b){function c(a,b){if(b=b.trim().toLowerCase(),"0"==b&&"px".search(a)>=0)return{px:0};if(/^[^(]*$|^calc/.test(b)){b=b.replace(/calc\(/g,"(");var c={};b=b.replace(a,function(a){return c[a]=null,"U"+a});for(var d="U("+a.source+")",e=b.replace(/[-+]?(\d*\.)?\d+/g,"N").replace(new RegExp("N"+d,"g"),"D").replace(/\s[+-]\s/g,"O").replace(/\s/g,""),f=[/N\*(D)/g,/(N|D)[*/]N/g,/(N|D)O\1/g,/\((N|D)\)/g],g=0;g1?"calc("+c+")":c}]}var f="px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc",g=c.bind(null,new RegExp(f,"g")),h=c.bind(null,new RegExp(f+"|%","g")),i=c.bind(null,/deg|rad|grad|turn/g);a.parseLength=g,a.parseLengthOrPercent=h,a.consumeLengthOrPercent=a.consumeParenthesised.bind(null,h),a.parseAngle=i,a.mergeDimensions=e;var j=a.consumeParenthesised.bind(null,g),k=a.consumeRepeated.bind(void 0,j,/^/),l=a.consumeRepeated.bind(void 0,k,/^,/);a.consumeSizePairList=l;var m=function(a){var b=l(a);return b&&""==b[1]?b[0]:void 0},n=a.mergeNestedRepeated.bind(void 0,d," "),o=a.mergeNestedRepeated.bind(void 0,n,",");a.mergeNonNegativeSizePair=n,a.addPropertiesHandler(m,o,["background-size"]),a.addPropertiesHandler(h,d,["border-bottom-width","border-image-width","border-left-width","border-right-width","border-top-width","flex-basis","font-size","height","line-height","max-height","max-width","outline-width","width"]),a.addPropertiesHandler(h,e,["border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","bottom","left","letter-spacing","margin-bottom","margin-left","margin-right","margin-top","min-height","min-width","outline-offset","padding-bottom","padding-left","padding-right","padding-top","perspective","right","shape-margin","text-indent","top","vertical-align","word-spacing"])}(d,f),function(a,b){function c(b){return a.consumeLengthOrPercent(b)||a.consumeToken(/^auto/,b)}function d(b){var d=a.consumeList([a.ignore(a.consumeToken.bind(null,/^rect/)),a.ignore(a.consumeToken.bind(null,/^\(/)),a.consumeRepeated.bind(null,c,/^,/),a.ignore(a.consumeToken.bind(null,/^\)/))],b);return d&&4==d[0].length?d[0]:void 0}function e(b,c){return"auto"==b||"auto"==c?[!0,!1,function(d){var e=d?b:c;if("auto"==e)return"auto";var f=a.mergeDimensions(e,e);return f[2](f[0])}]:a.mergeDimensions(b,c)}function f(a){return"rect("+a+")"}var g=a.mergeWrappedNestedRepeated.bind(null,f,e,", ");a.parseBox=d,a.mergeBoxes=g,a.addPropertiesHandler(d,g,["clip"])}(d,f),function(a,b){function c(a){return function(b){var c=0;return a.map(function(a){return a===k?b[c++]:a})}}function d(a){return a}function e(b){if(b=b.toLowerCase().trim(),"none"==b)return[];for(var c,d=/\s*(\w+)\(([^)]*)\)/g,e=[],f=0;c=d.exec(b);){if(c.index!=f)return;f=c.index+c[0].length;var g=c[1],h=n[g];if(!h)return;var i=c[2].split(","),j=h[0];if(j.lengthb||b>900||b%100!==0?void 0:b}function c(b){return b=100*Math.round(b/100),b=a.clamp(100,900,b),400===b?"normal":700===b?"bold":String(b)}function d(a,b){return[a,b,c]}a.addPropertiesHandler(b,d,["font-weight"])}(d),function(a){function b(a){var b={};for(var c in a)b[c]=-a[c];return b}function c(b){return a.consumeToken(/^(left|center|right|top|bottom)\b/i,b)||a.consumeLengthOrPercent(b)}function d(b,d){var e=a.consumeRepeated(c,/^/,d);if(e&&""==e[1]){var f=e[0];if(f[0]=f[0]||"center",f[1]=f[1]||"center",3==b&&(f[2]=f[2]||{px:0}),f.length==b){if(/top|bottom/.test(f[0])||/left|right/.test(f[1])){var h=f[0];f[0]=f[1],f[1]=h}if(/left|right|center|Object/.test(f[0])&&/top|bottom|center|Object/.test(f[1]))return f.map(function(a){return"object"==typeof a?a:g[a]})}}}function e(d){var e=a.consumeRepeated(c,/^/,d);if(e){for(var f=e[0],h=[{"%":50},{"%":50}],i=0,j=!1,k=0;k + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/resources/web-animations-js/web-animations.dev.js b/scripts/resources/web-animations-js/web-animations.dev.js new file mode 100644 index 0000000000..7f2b4571eb --- /dev/null +++ b/scripts/resources/web-animations-js/web-animations.dev.js @@ -0,0 +1,21 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var webAnimationsSourceTarget = 'web-animations'; +var WEB_ANIMATIONS_TESTING = false; +(function() { + var scripts = document.getElementsByTagName('script'); + var location = scripts[scripts.length - 1].src.replace(/[^\/]+$/, ''); + document.write(''); + document.write(''); +})(); diff --git a/scripts/resources/web-animations-js/web-animations.html b/scripts/resources/web-animations-js/web-animations.html new file mode 100644 index 0000000000..b5de36c855 --- /dev/null +++ b/scripts/resources/web-animations-js/web-animations.html @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/resources/web-animations-js/web-animations.min.js b/scripts/resources/web-animations-js/web-animations.min.js new file mode 100644 index 0000000000..4c00001a69 --- /dev/null +++ b/scripts/resources/web-animations-js/web-animations.min.js @@ -0,0 +1,16 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +!function(a,b){b["true"]=a,function(){if(document.documentElement.animate){var a=document.documentElement.animate([],0),b=!0;if(a&&(b=!1,"play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(c){void 0===a[c]&&(b=!0)})),!b)return}var c={},d={},e={},f=null;!function(a,b){function c(a){if("number"==typeof a)return a;var b={};for(var c in a)b[c]=a[c];return b}function d(){this._delay=0,this._endDelay=0,this._fill="none",this._iterationStart=0,this._iterations=1,this._duration=0,this._playbackRate=1,this._direction="normal",this._easing="linear"}function e(b,c,e){var f=new d;return c&&(f.fill="both",f.duration="auto"),"number"!=typeof b||isNaN(b)?void 0!==b&&Object.getOwnPropertyNames(b).forEach(function(c){if("auto"!=b[c]){if(("number"==typeof f[c]||"duration"==c)&&("number"!=typeof b[c]||isNaN(b[c])))return;if("fill"==c&&-1==t.indexOf(b[c]))return;if("direction"==c&&-1==u.indexOf(b[c]))return;if("playbackRate"==c&&1!==b[c]&&a.isDeprecated("AnimationEffectTiming.playbackRate","2014-11-28","Use Animation.playbackRate instead."))return;f[c]=b[c]}}):f.duration=b,f}function f(a){return"number"==typeof a&&(a=isNaN(a)?{duration:0}:{duration:a}),a}function g(b,c){b=a.numericTimingToObject(b);var d=e(b,c);return d._easing=j(d.easing),d}function h(a,b,c,d){return 0>a||a>1||0>c||c>1?C:function(e){function f(a,b,c){return 3*a*(1-c)*(1-c)*c+3*b*(1-c)*c*c+c*c*c}if(0==e||1==e)return e;for(var g=0,h=1;;){var i=(g+h)/2,j=f(a,c,i);if(Math.abs(e-j)<.001)return f(b,d,i);e>j?g=i:h=i}}}function i(a,b){return function(c){if(c>=1)return 1;var d=1/a;return c+=b*d,c-c%d}}function j(a){var b=A.exec(a);if(b)return h.apply(this,b.slice(1).map(Number));var c=B.exec(a);if(c)return i(Number(c[1]),{start:v,middle:w,end:x}[c[2]]);var d=y[a];return d?d:C}function k(a){return Math.abs(l(a)/a.playbackRate)}function l(a){return a.duration*a.iterations}function m(a,b,c){return null==b?D:b=c.delay+a?F:G}function n(a,b,c,d,e){switch(d){case E:return"backwards"==b||"both"==b?0:null;case G:return c-e;case F:return"forwards"==b||"both"==b?a:null;case D:return null}}function o(a,b,c,d){return(d.playbackRate<0?b-a:b)*d.playbackRate+c}function p(a,b,c,d,e){return c===1/0||c===-(1/0)||c-d==b&&e.iterations&&(e.iterations+e.iterationStart)%1==0?a:c%a}function q(a,b,c,d){return 0===c?0:b==a?d.iterationStart+d.iterations-1:Math.floor(c/a)}function r(a,b,c,d){var e=a%2>=1,f="normal"==d.direction||d.direction==(e?"alternate-reverse":"alternate"),g=f?c:b-c,h=g/b;return b*d.easing(h)}function s(a,b,c){var d=m(a,b,c),e=n(a,c.fill,b,d,c.delay);if(null===e)return null;if(0===a)return d===E?0:1;var f=c.iterationStart*c.duration,g=o(a,e,f,c),h=p(c.duration,l(c),g,f,c),i=q(c.duration,h,g,c);return r(i,c.duration,h,c)/c.duration}var t="backwards|forwards|both|none".split("|"),u="reverse|alternate|alternate-reverse".split("|");d.prototype={_setMember:function(b,c){this["_"+b]=c,this._effect&&(this._effect._timingInput[b]=c,this._effect._timing=a.normalizeTimingInput(a.normalizeTimingInput(this._effect._timingInput)),this._effect.activeDuration=a.calculateActiveDuration(this._effect._timing),this._effect._animation&&this._effect._animation._rebuildUnderlyingAnimation())},get playbackRate(){return this._playbackRate},set delay(a){this._setMember("delay",a)},get delay(){return this._delay},set endDelay(a){this._setMember("endDelay",a)},get endDelay(){return this._endDelay},set fill(a){this._setMember("fill",a)},get fill(){return this._fill},set iterationStart(a){this._setMember("iterationStart",a)},get iterationStart(){return this._iterationStart},set duration(a){this._setMember("duration",a)},get duration(){return this._duration},set direction(a){this._setMember("direction",a)},get direction(){return this._direction},set easing(a){this._setMember("easing",a)},get easing(){return this._easing},set iterations(a){this._setMember("iterations",a)},get iterations(){return this._iterations}};var v=1,w=.5,x=0,y={ease:h(.25,.1,.25,1),"ease-in":h(.42,0,1,1),"ease-out":h(0,0,.58,1),"ease-in-out":h(.42,0,.58,1),"step-start":i(1,v),"step-middle":i(1,w),"step-end":i(1,x)},z="\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*",A=new RegExp("cubic-bezier\\("+z+","+z+","+z+","+z+"\\)"),B=/steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/,C=function(a){return a},D=0,E=1,F=2,G=3;a.cloneTimingInput=c,a.makeTiming=e,a.numericTimingToObject=f,a.normalizeTimingInput=g,a.calculateActiveDuration=k,a.calculateTimeFraction=s,a.calculatePhase=m,a.toTimingFunction=j}(c,f),function(a,b){function c(a,b){return a in i?i[a][b]||b:b}function d(a,b,d){var e=f[a];if(e){g.style[a]=b;for(var h in e){var i=e[h],j=g.style[i];d[i]=c(i,j)}}else d[a]=c(a,b)}function e(b){function c(){var a=e.length;null==e[a-1].offset&&(e[a-1].offset=1),a>1&&null==e[0].offset&&(e[0].offset=0);for(var b=0,c=e[0].offset,d=1;a>d;d++){var f=e[d].offset;if(null!=f){for(var g=1;d-b>g;g++)e[b+g].offset=c+(f-c)*g/(d-b);b=d,c=f}}}if(!Array.isArray(b)&&null!==b)throw new TypeError("Keyframes must be null or an array of keyframes");if(null==b)return[];for(var e=b.map(function(b){var c={};for(var e in b){var f=b[e];if("offset"==e){if(null!=f&&(f=Number(f),!isFinite(f)))throw new TypeError("keyframe offsets must be numbers.")}else{if("composite"==e)throw{type:DOMException.NOT_SUPPORTED_ERR,name:"NotSupportedError",message:"add compositing is not supported"};f="easing"==e?a.toTimingFunction(f):""+f}d(e,f,c)}return void 0==c.offset&&(c.offset=null),void 0==c.easing&&(c.easing=a.toTimingFunction("linear")),c}),f=!0,g=-(1/0),h=0;hi)throw{code:DOMException.INVALID_MODIFICATION_ERR,name:"InvalidModificationError",message:"Keyframes are not loosely sorted by offset. Sort or specify offsets."};g=i}else f=!1}return e=e.filter(function(a){return a.offset>=0&&a.offset<=1}),f||c(),e}var f={background:["backgroundImage","backgroundPosition","backgroundSize","backgroundRepeat","backgroundAttachment","backgroundOrigin","backgroundClip","backgroundColor"],border:["borderTopColor","borderTopStyle","borderTopWidth","borderRightColor","borderRightStyle","borderRightWidth","borderBottomColor","borderBottomStyle","borderBottomWidth","borderLeftColor","borderLeftStyle","borderLeftWidth"],borderBottom:["borderBottomWidth","borderBottomStyle","borderBottomColor"],borderColor:["borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"],borderLeft:["borderLeftWidth","borderLeftStyle","borderLeftColor"],borderRadius:["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],borderRight:["borderRightWidth","borderRightStyle","borderRightColor"],borderTop:["borderTopWidth","borderTopStyle","borderTopColor"],borderWidth:["borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth"],flex:["flexGrow","flexShrink","flexBasis"],font:["fontFamily","fontSize","fontStyle","fontVariant","fontWeight","lineHeight"],margin:["marginTop","marginRight","marginBottom","marginLeft"],outline:["outlineColor","outlineStyle","outlineWidth"],padding:["paddingTop","paddingRight","paddingBottom","paddingLeft"]},g=document.createElementNS("http://www.w3.org/1999/xhtml","div"),h={thin:"1px",medium:"3px",thick:"5px"},i={borderBottomWidth:h,borderLeftWidth:h,borderRightWidth:h,borderTopWidth:h,fontSize:{"xx-small":"60%","x-small":"75%",small:"89%",medium:"100%",large:"120%","x-large":"150%","xx-large":"200%"},fontWeight:{normal:"400",bold:"700"},outlineWidth:h,textShadow:{none:"0px 0px 0px transparent"},boxShadow:{none:"0px 0px 0px 0px transparent"}};a.normalizeKeyframes=e}(c,f),function(a,b,c){function d(a){for(var b={},c=0;c=c&&0==a.startTime||c>=1&&1==a.endTime||c>=a.startTime&&c<=a.endTime}).forEach(function(d){var e=c-d.startTime,f=d.endTime-d.startTime,g=0==f?0:d.easing(e/f);b.apply(a,d.property,d.interpolation(g))});else for(var d in g)"offset"!=d&&"easing"!=d&&"composite"!=d&&b.clear(a,d)}}}(c,d,f),function(a,b){function c(a,b,c){f[c]=f[c]||[],f[c].push([a,b])}function d(a,b,d){for(var e=0;ed?a:b;if(a.length==b.length){for(var e=[],f=0;f0?this._totalDuration:0),this._ensureAlive())},get currentTime(){return this._idle||this._currentTimePending?null:this._currentTime},set currentTime(a){a=+a,isNaN(a)||(b.restart(),this._paused||null==this._startTime||(this._startTime=this._timeline.currentTime-a/this._playbackRate),this._currentTimePending=!1,this._currentTime!=a&&(this._tickCurrentTime(a,!0),b.invalidateEffects()))},get startTime(){return this._startTime},set startTime(a){a=+a,isNaN(a)||this._paused||this._idle||(this._startTime=a,this._tickCurrentTime((this._timeline.currentTime-this._startTime)*this.playbackRate),b.invalidateEffects())},get playbackRate(){return this._playbackRate},set playbackRate(a){if(a!=this._playbackRate){var b=this.currentTime;this._playbackRate=a,this._startTime=null,"paused"!=this.playState&&"idle"!=this.playState&&this.play(),null!=b&&(this.currentTime=b)}},get _isFinished(){return!this._idle&&(this._playbackRate>0&&this._currentTime>=this._totalDuration||this._playbackRate<0&&this._currentTime<=0)},get _totalDuration(){return this._effect._totalDuration},get playState(){return this._idle?"idle":null==this._startTime&&!this._paused&&0!=this.playbackRate||this._currentTimePending?"pending":this._paused?"paused":this._isFinished?"finished":"running"},play:function(){this._paused=!1,(this._isFinished||this._idle)&&(this._currentTime=this._playbackRate>0?0:this._totalDuration,this._startTime=null,b.invalidateEffects()),this._finishedFlag=!1,b.restart(),this._idle=!1,this._ensureAlive()},pause:function(){this._isFinished||this._paused||this._idle||(this._currentTimePending=!0),this._startTime=null,this._paused=!0},finish:function(){this._idle||(this.currentTime=this._playbackRate>0?this._totalDuration:0,this._startTime=this._totalDuration-this.currentTime,this._currentTimePending=!1)},cancel:function(){this._inEffect&&(this._inEffect=!1,this._idle=!0,this.currentTime=0,this._startTime=null,this._effect._update(null),b.invalidateEffects(),b.restart())},reverse:function(){this.playbackRate*=-1,this.play()},addEventListener:function(a,b){"function"==typeof b&&"finish"==a&&this._finishHandlers.push(b)},removeEventListener:function(a,b){if("finish"==a){var c=this._finishHandlers.indexOf(b);c>=0&&this._finishHandlers.splice(c,1)}},_fireEvents:function(a){var b=this._isFinished;if((b||this._idle)&&!this._finishedFlag){var c=new d(this,this._currentTime,a),e=this._finishHandlers.concat(this.onfinish?[this.onfinish]:[]);e.forEach(function(a){a.call(c.target,c)})}this._finishedFlag=b},_tick:function(a){return this._idle||this._paused||(null==this._startTime?this.startTime=a-this._currentTime/this.playbackRate:this._isFinished||this._tickCurrentTime((a-this._startTime)*this.playbackRate)),this._currentTimePending=!1,this._fireEvents(a),!this._idle&&(this._inEffect||!this._finishedFlag)}}}(c,d,f),function(a,b,c){function d(a){var b=j;j=[],a0&&(t.currentTime+=r*(Math.floor((a-t.currentTime)/r)+1)),h(t.currentTime)}return g(),s.apply(this,arguments)}});var t=new f;b.timeline=t}(c,d,f),function(a){function b(a,b){var c=a.exec(b);return c?(c=a.ignoreCase?c[0].toLowerCase():c[0],[c,b.substr(c.length)]):void 0}function c(a,b){b=b.replace(/^\s*/,"");var c=a(b);return c?[c[0],c[1].replace(/^\s*/,"")]:void 0}function d(a,d,e){a=c.bind(null,a);for(var f=[];;){var g=a(e);if(!g)return[f,e];if(f.push(g[0]),e=g[1],g=b(d,e),!g||""==g[1])return[f,e];e=g[1]}}function e(a,b){for(var c=0,d=0;d=c))break;var e=a(b.substr(0,d));return void 0==e?void 0:[e,b.substr(d)]}function f(a,b){for(var c=a,d=b;c&&d;)c>d?c%=d:d%=c;return c=a*b/(c+d)}function g(a){return function(b){var c=a(b);return c&&(c[0]=void 0),c}}function h(a,b){return function(c){var d=a(c);return d?d:[b,c]}}function i(b,c){for(var d=[],e=0;ek;k++){var l=b(d[k%d.length],e[k%e.length]);if(!l)return;g.push(l[0]),h.push(l[1]),i.push(l[2])}return[g,h,function(b){var d=b.map(function(a,b){return i[b](a)}).join(c);return a?a(d):d}]}function k(a,b,c){for(var d=[],e=[],f=[],g=0,h=0;h=c?a:c>=1?b:"visible"}]:void 0}a.addPropertiesHandler(String,c,["visibility"])}(d),function(a,b){function c(a){a=a.trim(),f.fillStyle="#000",f.fillStyle=a;var b=f.fillStyle;if(f.fillStyle="#fff",f.fillStyle=a,b==f.fillStyle){f.fillRect(0,0,1,1);var c=f.getImageData(0,0,1,1).data;f.clearRect(0,0,1,1);var d=c[3]/255;return[c[0]*d,c[1]*d,c[2]*d,d]}}function d(b,c){return[b,c,function(b){function c(a){return Math.max(0,Math.min(255,a))}if(b[3])for(var d=0;3>d;d++)b[d]=Math.round(c(b[d]/b[3]));return b[3]=a.numberToString(a.clamp(0,1,b[3])),"rgba("+b.join(",")+")"}]}var e=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");e.width=e.height=1;var f=e.getContext("2d");a.addPropertiesHandler(c,d,["background-color","border-bottom-color","border-left-color","border-right-color","border-top-color","color","outline-color","text-decoration-color"]),a.consumeColor=a.consumeParenthesised.bind(null,c),a.mergeColors=d}(d,f),function(a,b){function c(a,b){if(b=b.trim().toLowerCase(),"0"==b&&"px".search(a)>=0)return{px:0};if(/^[^(]*$|^calc/.test(b)){b=b.replace(/calc\(/g,"(");var c={};b=b.replace(a,function(a){return c[a]=null,"U"+a});for(var d="U("+a.source+")",e=b.replace(/[-+]?(\d*\.)?\d+/g,"N").replace(new RegExp("N"+d,"g"),"D").replace(/\s[+-]\s/g,"O").replace(/\s/g,""),f=[/N\*(D)/g,/(N|D)[*/]N/g,/(N|D)O\1/g,/\((N|D)\)/g],g=0;g1?"calc("+c+")":c}]}var f="px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc",g=c.bind(null,new RegExp(f,"g")),h=c.bind(null,new RegExp(f+"|%","g")),i=c.bind(null,/deg|rad|grad|turn/g);a.parseLength=g,a.parseLengthOrPercent=h,a.consumeLengthOrPercent=a.consumeParenthesised.bind(null,h),a.parseAngle=i,a.mergeDimensions=e;var j=a.consumeParenthesised.bind(null,g),k=a.consumeRepeated.bind(void 0,j,/^/),l=a.consumeRepeated.bind(void 0,k,/^,/);a.consumeSizePairList=l;var m=function(a){var b=l(a);return b&&""==b[1]?b[0]:void 0},n=a.mergeNestedRepeated.bind(void 0,d," "),o=a.mergeNestedRepeated.bind(void 0,n,",");a.mergeNonNegativeSizePair=n,a.addPropertiesHandler(m,o,["background-size"]),a.addPropertiesHandler(h,d,["border-bottom-width","border-image-width","border-left-width","border-right-width","border-top-width","flex-basis","font-size","height","line-height","max-height","max-width","outline-width","width"]),a.addPropertiesHandler(h,e,["border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","bottom","left","letter-spacing","margin-bottom","margin-left","margin-right","margin-top","min-height","min-width","outline-offset","padding-bottom","padding-left","padding-right","padding-top","perspective","right","shape-margin","text-indent","top","vertical-align","word-spacing"])}(d,f),function(a,b){function c(b){return a.consumeLengthOrPercent(b)||a.consumeToken(/^auto/,b)}function d(b){var d=a.consumeList([a.ignore(a.consumeToken.bind(null,/^rect/)),a.ignore(a.consumeToken.bind(null,/^\(/)),a.consumeRepeated.bind(null,c,/^,/),a.ignore(a.consumeToken.bind(null,/^\)/))],b);return d&&4==d[0].length?d[0]:void 0}function e(b,c){return"auto"==b||"auto"==c?[!0,!1,function(d){var e=d?b:c;if("auto"==e)return"auto";var f=a.mergeDimensions(e,e);return f[2](f[0])}]:a.mergeDimensions(b,c)}function f(a){return"rect("+a+")"}var g=a.mergeWrappedNestedRepeated.bind(null,f,e,", ");a.parseBox=d,a.mergeBoxes=g,a.addPropertiesHandler(d,g,["clip"])}(d,f),function(a,b){function c(a){return function(b){var c=0;return a.map(function(a){return a===k?b[c++]:a})}}function d(a){return a}function e(b){if(b=b.toLowerCase().trim(),"none"==b)return[];for(var c,d=/\s*(\w+)\(([^)]*)\)/g,e=[],f=0;c=d.exec(b);){if(c.index!=f)return;f=c.index+c[0].length;var g=c[1],h=n[g];if(!h)return;var i=c[2].split(","),j=h[0];if(j.length