blob: 5ce89b73c36340798f5dbfdf78dc50c045ef5940 [file] [log] [blame]
/*
Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
dojo.provide("dojo.lfx.Animation");
dojo.require("dojo.lang.func");
dojo.lfx.Line = function (start, end) {
this.start = start;
this.end = end;
if (dojo.lang.isArray(start)) {
var diff = [];
dojo.lang.forEach(this.start, function (s, i) {
diff[i] = this.end[i] - s;
}, this);
this.getValue = function (n) {
var res = [];
dojo.lang.forEach(this.start, function (s, i) {
res[i] = (diff[i] * n) + s;
}, this);
return res;
};
} else {
var diff = end - start;
this.getValue = function (n) {
return (diff * n) + this.start;
};
}
};
if ((dojo.render.html.khtml) && (!dojo.render.html.safari)) {
dojo.lfx.easeDefault = function (n) {
return (parseFloat("0.5") + ((Math.sin((n + parseFloat("1.5")) * Math.PI)) / 2));
};
} else {
dojo.lfx.easeDefault = function (n) {
return (0.5 + ((Math.sin((n + 1.5) * Math.PI)) / 2));
};
}
dojo.lfx.easeIn = function (n) {
return Math.pow(n, 3);
};
dojo.lfx.easeOut = function (n) {
return (1 - Math.pow(1 - n, 3));
};
dojo.lfx.easeInOut = function (n) {
return ((3 * Math.pow(n, 2)) - (2 * Math.pow(n, 3)));
};
dojo.lfx.IAnimation = function () {
};
dojo.lang.extend(dojo.lfx.IAnimation, {curve:null, duration:1000, easing:null, repeatCount:0, rate:10, handler:null, beforeBegin:null, onBegin:null, onAnimate:null, onEnd:null, onPlay:null, onPause:null, onStop:null, play:null, pause:null, stop:null, connect:function (evt, scope, newFunc) {
if (!newFunc) {
newFunc = scope;
scope = this;
}
newFunc = dojo.lang.hitch(scope, newFunc);
var oldFunc = this[evt] || function () {
};
this[evt] = function () {
var ret = oldFunc.apply(this, arguments);
newFunc.apply(this, arguments);
return ret;
};
return this;
}, fire:function (evt, args) {
if (this[evt]) {
this[evt].apply(this, (args || []));
}
return this;
}, repeat:function (count) {
this.repeatCount = count;
return this;
}, _active:false, _paused:false});
dojo.lfx.Animation = function (handlers, duration, curve, easing, repeatCount, rate) {
dojo.lfx.IAnimation.call(this);
if (dojo.lang.isNumber(handlers) || (!handlers && duration.getValue)) {
rate = repeatCount;
repeatCount = easing;
easing = curve;
curve = duration;
duration = handlers;
handlers = null;
} else {
if (handlers.getValue || dojo.lang.isArray(handlers)) {
rate = easing;
repeatCount = curve;
easing = duration;
curve = handlers;
duration = null;
handlers = null;
}
}
if (dojo.lang.isArray(curve)) {
this.curve = new dojo.lfx.Line(curve[0], curve[1]);
} else {
this.curve = curve;
}
if (duration != null && duration > 0) {
this.duration = duration;
}
if (repeatCount) {
this.repeatCount = repeatCount;
}
if (rate) {
this.rate = rate;
}
if (handlers) {
dojo.lang.forEach(["handler", "beforeBegin", "onBegin", "onEnd", "onPlay", "onStop", "onAnimate"], function (item) {
if (handlers[item]) {
this.connect(item, handlers[item]);
}
}, this);
}
if (easing && dojo.lang.isFunction(easing)) {
this.easing = easing;
}
};
dojo.inherits(dojo.lfx.Animation, dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Animation, {_startTime:null, _endTime:null, _timer:null, _percent:0, _startRepeatCount:0, play:function (delay, gotoStart) {
if (gotoStart) {
clearTimeout(this._timer);
this._active = false;
this._paused = false;
this._percent = 0;
} else {
if (this._active && !this._paused) {
return this;
}
}
this.fire("handler", ["beforeBegin"]);
this.fire("beforeBegin");
if (delay > 0) {
setTimeout(dojo.lang.hitch(this, function () {
this.play(null, gotoStart);
}), delay);
return this;
}
this._startTime = new Date().valueOf();
if (this._paused) {
this._startTime -= (this.duration * this._percent / 100);
}
this._endTime = this._startTime + this.duration;
this._active = true;
this._paused = false;
var step = this._percent / 100;
var value = this.curve.getValue(step);
if (this._percent == 0) {
if (!this._startRepeatCount) {
this._startRepeatCount = this.repeatCount;
}
this.fire("handler", ["begin", value]);
this.fire("onBegin", [value]);
}
this.fire("handler", ["play", value]);
this.fire("onPlay", [value]);
this._cycle();
return this;
}, pause:function () {
clearTimeout(this._timer);
if (!this._active) {
return this;
}
this._paused = true;
var value = this.curve.getValue(this._percent / 100);
this.fire("handler", ["pause", value]);
this.fire("onPause", [value]);
return this;
}, gotoPercent:function (pct, andPlay) {
clearTimeout(this._timer);
this._active = true;
this._paused = true;
this._percent = pct;
if (andPlay) {
this.play();
}
return this;
}, stop:function (gotoEnd) {
clearTimeout(this._timer);
var step = this._percent / 100;
if (gotoEnd) {
step = 1;
}
var value = this.curve.getValue(step);
this.fire("handler", ["stop", value]);
this.fire("onStop", [value]);
this._active = false;
this._paused = false;
return this;
}, status:function () {
if (this._active) {
return this._paused ? "paused" : "playing";
} else {
return "stopped";
}
return this;
}, _cycle:function () {
clearTimeout(this._timer);
if (this._active) {
var curr = new Date().valueOf();
var step = (curr - this._startTime) / (this._endTime - this._startTime);
if (step >= 1) {
step = 1;
this._percent = 100;
} else {
this._percent = step * 100;
}
if ((this.easing) && (dojo.lang.isFunction(this.easing))) {
step = this.easing(step);
}
var value = this.curve.getValue(step);
this.fire("handler", ["animate", value]);
this.fire("onAnimate", [value]);
if (step < 1) {
this._timer = setTimeout(dojo.lang.hitch(this, "_cycle"), this.rate);
} else {
this._active = false;
this.fire("handler", ["end"]);
this.fire("onEnd");
if (this.repeatCount > 0) {
this.repeatCount--;
this.play(null, true);
} else {
if (this.repeatCount == -1) {
this.play(null, true);
} else {
if (this._startRepeatCount) {
this.repeatCount = this._startRepeatCount;
this._startRepeatCount = 0;
}
}
}
}
}
return this;
}});
dojo.lfx.Combine = function (animations) {
dojo.lfx.IAnimation.call(this);
this._anims = [];
this._animsEnded = 0;
var anims = arguments;
if (anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))) {
anims = anims[0];
}
dojo.lang.forEach(anims, function (anim) {
this._anims.push(anim);
anim.connect("onEnd", dojo.lang.hitch(this, "_onAnimsEnded"));
}, this);
};
dojo.inherits(dojo.lfx.Combine, dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Combine, {_animsEnded:0, play:function (delay, gotoStart) {
if (!this._anims.length) {
return this;
}
this.fire("beforeBegin");
if (delay > 0) {
setTimeout(dojo.lang.hitch(this, function () {
this.play(null, gotoStart);
}), delay);
return this;
}
if (gotoStart || this._anims[0].percent == 0) {
this.fire("onBegin");
}
this.fire("onPlay");
this._animsCall("play", null, gotoStart);
return this;
}, pause:function () {
this.fire("onPause");
this._animsCall("pause");
return this;
}, stop:function (gotoEnd) {
this.fire("onStop");
this._animsCall("stop", gotoEnd);
return this;
}, _onAnimsEnded:function () {
this._animsEnded++;
if (this._animsEnded >= this._anims.length) {
this.fire("onEnd");
}
return this;
}, _animsCall:function (funcName) {
var args = [];
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
}
var _this = this;
dojo.lang.forEach(this._anims, function (anim) {
anim[funcName](args);
}, _this);
return this;
}});
dojo.lfx.Chain = function (animations) {
dojo.lfx.IAnimation.call(this);
this._anims = [];
this._currAnim = -1;
var anims = arguments;
if (anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))) {
anims = anims[0];
}
var _this = this;
dojo.lang.forEach(anims, function (anim, i, anims_arr) {
this._anims.push(anim);
if (i < anims_arr.length - 1) {
anim.connect("onEnd", dojo.lang.hitch(this, "_playNext"));
} else {
anim.connect("onEnd", dojo.lang.hitch(this, function () {
this.fire("onEnd");
}));
}
}, this);
};
dojo.inherits(dojo.lfx.Chain, dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Chain, {_currAnim:-1, play:function (delay, gotoStart) {
if (!this._anims.length) {
return this;
}
if (gotoStart || !this._anims[this._currAnim]) {
this._currAnim = 0;
}
var currentAnimation = this._anims[this._currAnim];
this.fire("beforeBegin");
if (delay > 0) {
setTimeout(dojo.lang.hitch(this, function () {
this.play(null, gotoStart);
}), delay);
return this;
}
if (currentAnimation) {
if (this._currAnim == 0) {
this.fire("handler", ["begin", this._currAnim]);
this.fire("onBegin", [this._currAnim]);
}
this.fire("onPlay", [this._currAnim]);
currentAnimation.play(null, gotoStart);
}
return this;
}, pause:function () {
if (this._anims[this._currAnim]) {
this._anims[this._currAnim].pause();
this.fire("onPause", [this._currAnim]);
}
return this;
}, playPause:function () {
if (this._anims.length == 0) {
return this;
}
if (this._currAnim == -1) {
this._currAnim = 0;
}
var currAnim = this._anims[this._currAnim];
if (currAnim) {
if (!currAnim._active || currAnim._paused) {
this.play();
} else {
this.pause();
}
}
return this;
}, stop:function () {
var currAnim = this._anims[this._currAnim];
if (currAnim) {
currAnim.stop();
this.fire("onStop", [this._currAnim]);
}
return currAnim;
}, _playNext:function () {
if (this._currAnim == -1 || this._anims.length == 0) {
return this;
}
this._currAnim++;
if (this._anims[this._currAnim]) {
this._anims[this._currAnim].play(null, true);
}
return this;
}});
dojo.lfx.combine = function (animations) {
var anims = arguments;
if (dojo.lang.isArray(arguments[0])) {
anims = arguments[0];
}
if (anims.length == 1) {
return anims[0];
}
return new dojo.lfx.Combine(anims);
};
dojo.lfx.chain = function (animations) {
var anims = arguments;
if (dojo.lang.isArray(arguments[0])) {
anims = arguments[0];
}
if (anims.length == 1) {
return anims[0];
}
return new dojo.lfx.Chain(anims);
};