Path: blob/trunk/third_party/closure/goog/fx/animationqueue.js
2868 views
// Copyright 2007 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview A class which automatically plays through a queue of16* animations. AnimationParallelQueue and AnimationSerialQueue provide17* specific implementations of the abstract class AnimationQueue.18*19* @see ../demos/animationqueue.html20*/2122goog.provide('goog.fx.AnimationParallelQueue');23goog.provide('goog.fx.AnimationQueue');24goog.provide('goog.fx.AnimationSerialQueue');2526goog.require('goog.array');27goog.require('goog.asserts');28goog.require('goog.events');29goog.require('goog.fx.Animation');30goog.require('goog.fx.Transition');31goog.require('goog.fx.TransitionBase');32333435/**36* Constructor for AnimationQueue object.37*38* @constructor39* @struct40* @extends {goog.fx.TransitionBase}41*/42goog.fx.AnimationQueue = function() {43goog.fx.AnimationQueue.base(this, 'constructor');4445/**46* An array holding all animations in the queue.47* @type {Array<goog.fx.TransitionBase>}48* @protected49*/50this.queue = [];51};52goog.inherits(goog.fx.AnimationQueue, goog.fx.TransitionBase);535455/**56* Pushes an Animation to the end of the queue.57* @param {goog.fx.TransitionBase} animation The animation to add to the queue.58*/59goog.fx.AnimationQueue.prototype.add = function(animation) {60goog.asserts.assert(61this.isStopped(),62'Not allowed to add animations to a running animation queue.');6364if (goog.array.contains(this.queue, animation)) {65return;66}6768this.queue.push(animation);69goog.events.listen(70animation, goog.fx.Transition.EventType.FINISH, this.onAnimationFinish,71false, this);72};737475/**76* Removes an Animation from the queue.77* @param {goog.fx.Animation} animation The animation to remove.78*/79goog.fx.AnimationQueue.prototype.remove = function(animation) {80goog.asserts.assert(81this.isStopped(),82'Not allowed to remove animations from a running animation queue.');8384if (goog.array.remove(this.queue, animation)) {85goog.events.unlisten(86animation, goog.fx.Transition.EventType.FINISH, this.onAnimationFinish,87false, this);88}89};909192/**93* Handles the event that an animation has finished.94* @param {goog.events.Event} e The finishing event.95* @protected96*/97goog.fx.AnimationQueue.prototype.onAnimationFinish = goog.abstractMethod;9899100/**101* Disposes of the animations.102* @override103*/104goog.fx.AnimationQueue.prototype.disposeInternal = function() {105goog.array.forEach(this.queue, function(animation) { animation.dispose(); });106this.queue.length = 0;107108goog.fx.AnimationQueue.base(this, 'disposeInternal');109};110111112113/**114* Constructor for AnimationParallelQueue object.115* @constructor116* @struct117* @extends {goog.fx.AnimationQueue}118*/119goog.fx.AnimationParallelQueue = function() {120goog.fx.AnimationParallelQueue.base(this, 'constructor');121122/**123* Number of finished animations.124* @type {number}125* @private126*/127this.finishedCounter_ = 0;128};129goog.inherits(goog.fx.AnimationParallelQueue, goog.fx.AnimationQueue);130131132/** @override */133goog.fx.AnimationParallelQueue.prototype.play = function(opt_restart) {134if (this.queue.length == 0) {135return false;136}137138if (opt_restart || this.isStopped()) {139this.finishedCounter_ = 0;140this.onBegin();141} else if (this.isPlaying()) {142return false;143}144145this.onPlay();146if (this.isPaused()) {147this.onResume();148}149var resuming = this.isPaused() && !opt_restart;150151this.startTime = goog.now();152this.endTime = null;153this.setStatePlaying();154155goog.array.forEach(this.queue, function(anim) {156if (!resuming || anim.isPaused()) {157anim.play(opt_restart);158}159});160161return true;162};163164165/** @override */166goog.fx.AnimationParallelQueue.prototype.pause = function() {167if (this.isPlaying()) {168goog.array.forEach(this.queue, function(anim) {169if (anim.isPlaying()) {170anim.pause();171}172});173174this.setStatePaused();175this.onPause();176}177};178179180/** @override */181goog.fx.AnimationParallelQueue.prototype.stop = function(opt_gotoEnd) {182goog.array.forEach(this.queue, function(anim) {183if (!anim.isStopped()) {184anim.stop(opt_gotoEnd);185}186});187188this.setStateStopped();189this.endTime = goog.now();190191this.onStop();192this.onEnd();193};194195196/** @override */197goog.fx.AnimationParallelQueue.prototype.onAnimationFinish = function(e) {198this.finishedCounter_++;199if (this.finishedCounter_ == this.queue.length) {200this.endTime = goog.now();201202this.setStateStopped();203204this.onFinish();205this.onEnd();206}207};208209210211/**212* Constructor for AnimationSerialQueue object.213* @constructor214* @struct215* @extends {goog.fx.AnimationQueue}216*/217goog.fx.AnimationSerialQueue = function() {218goog.fx.AnimationSerialQueue.base(this, 'constructor');219220/**221* Current animation in queue currently active.222* @type {number}223* @private224*/225this.current_ = 0;226};227goog.inherits(goog.fx.AnimationSerialQueue, goog.fx.AnimationQueue);228229230/** @override */231goog.fx.AnimationSerialQueue.prototype.play = function(opt_restart) {232if (this.queue.length == 0) {233return false;234}235236if (opt_restart || this.isStopped()) {237if (this.current_ < this.queue.length &&238!this.queue[this.current_].isStopped()) {239this.queue[this.current_].stop(false);240}241242this.current_ = 0;243this.onBegin();244} else if (this.isPlaying()) {245return false;246}247248this.onPlay();249if (this.isPaused()) {250this.onResume();251}252253this.startTime = goog.now();254this.endTime = null;255this.setStatePlaying();256257this.queue[this.current_].play(opt_restart);258259return true;260};261262263/** @override */264goog.fx.AnimationSerialQueue.prototype.pause = function() {265if (this.isPlaying()) {266this.queue[this.current_].pause();267this.setStatePaused();268this.onPause();269}270};271272273/** @override */274goog.fx.AnimationSerialQueue.prototype.stop = function(opt_gotoEnd) {275this.setStateStopped();276this.endTime = goog.now();277278if (opt_gotoEnd) {279for (var i = this.current_; i < this.queue.length; ++i) {280var anim = this.queue[i];281// If the animation is stopped, start it to initiate rendering. This282// might be needed to make the next line work.283if (anim.isStopped()) anim.play();284// If the animation is not done, stop it and go to the end state of the285// animation.286if (!anim.isStopped()) anim.stop(true);287}288} else if (this.current_ < this.queue.length) {289this.queue[this.current_].stop(false);290}291292this.onStop();293this.onEnd();294};295296297/** @override */298goog.fx.AnimationSerialQueue.prototype.onAnimationFinish = function(e) {299if (this.isPlaying()) {300this.current_++;301if (this.current_ < this.queue.length) {302this.queue[this.current_].play();303} else {304this.endTime = goog.now();305this.setStateStopped();306307this.onFinish();308this.onEnd();309}310}311};312313314