Index: third_party/polymer/components/web-animations-js/src/web-animations-next-animation.js |
diff --git a/third_party/polymer/components/web-animations-js/src/web-animations-next-animation.js b/third_party/polymer/components/web-animations-js/src/web-animations-next-animation.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..698532cd972ba42dae9f4c1ecec0fcefc4115462 |
--- /dev/null |
+++ b/third_party/polymer/components/web-animations-js/src/web-animations-next-animation.js |
@@ -0,0 +1,383 @@ |
+// 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.id = ''; |
+ if (effect && effect._id) { |
+ this.id = effect._id; |
+ } |
+ 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 = scope.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._animation.onfinish; |
+ }, |
+ set onfinish(v) { |
+ if (typeof v == 'function') { |
+ this._animation.onfinish = (function(e) { |
+ e.target = this; |
+ v.call(this, e); |
+ }).bind(this); |
+ } else { |
+ this._animation.onfinish = v; |
+ } |
+ }, |
+ get oncancel() { |
+ return this._animation.oncancel; |
+ }, |
+ set oncancel(v) { |
+ if (typeof v == 'function') { |
+ this._animation.oncancel = (function(e) { |
+ e.target = this; |
+ v.call(this, e); |
+ }).bind(this); |
+ } else { |
+ this._animation.oncancel = v; |
+ } |
+ }, |
+ 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 (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.calculateIterationProgress(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); |