diff options
Diffstat (limited to 'catapult/third_party/polymer/components/web-animations-js/src/group-constructors.js')
-rw-r--r-- | catapult/third_party/polymer/components/web-animations-js/src/group-constructors.js | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/catapult/third_party/polymer/components/web-animations-js/src/group-constructors.js b/catapult/third_party/polymer/components/web-animations-js/src/group-constructors.js new file mode 100644 index 00000000..e5c0a102 --- /dev/null +++ b/catapult/third_party/polymer/components/web-animations-js/src/group-constructors.js @@ -0,0 +1,204 @@ +// 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, id) { + this._id = id; + 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. calculateIterationProgress 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.calculateIterationProgress(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, group._id); + 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); |