// FX! Effects_class = function () { this.namedQueues = { }; this.globalQueue = [ ]; } Effects_class.prototype.enqueue = function (effectList, params) { if (!params) { params = { }; } var global = params.global || false; var qName = params.global ? null : (params.shared || 'r'+Math.random()); if (qName && !this.namedQueues[qName]) { this.namedQueues[qName] = [ ]; this.namedQueues[qName].name = qName; } var queue = qName ? this.namedQueues[qName] : this.globalQueue; if (params.onComplete) { if (params.context) { queue.onComplete = function () { params.onComplete.apply(params.context, [ ]); } } else { queue.onComplete = params.onComplete; } } for (var i = 0; i < effectList.length; i++) { queue.push(effectList[i]); } this._runQueue(queue); } Effects_class.prototype.createParallel = function (effectList, params) { var onComplete = null; if (params) { if (params.onComplete) { if (params.context) { onComplete = function () { params.onComplete.apply(params.context, [ ]); } } else { onComplete = params.onComplete; } } } var InitClosure = function(context) { return function() { context._initParallel(effectList, onComplete); }; }; effectList.animate = InitClosure(this); return effectList; } Effects_class.prototype.runParallel = function (effectList, params) { var ef = this.createParallel(effectList, params); ef.animate(); return ef; } Effects_class.prototype.create = function (element, type, params) { var ef = new Effect(element, type, params); return ef; } Effects_class.prototype.run = function (element, type, params) { var ef = this.create(element, type, params); ef.animate(); return ef; } Effects_class.prototype._runQueue = function (queue) { if (queue.length) { var ef = queue.shift(); ef.runningQueue = queue; ef.animate(); } else { if (queue.onComplete) { queue.onComplete(); queue.onComplete = null; } if (queue.name) { // this doesn't get called when queueing a parallel effect?? delete this.namedQueues[queue.name]; } } } Effects_class.prototype._initParallel = function (effectList, onComplete) { for (var i = 0; i < effectList.length; i++) { effectList[i].animateParallel(); } this._animateParallel(effectList, onComplete); } Effects_class.prototype._animateParallel = function (effectList, onComplete) { var isAnimating = false; for (var i = 0; i < effectList.length; i++) { effectList[i].nextFrame(); isAnimating = isAnimating || effectList[i].isAnimating; } if (isAnimating) { var ParaClosure = function(context) { return function() { context._animateParallel(effectList, onComplete); }; }; setTimeout(ParaClosure(this), 0); } else { if (effectList.runningQueue) { this._runQueue(effectList.runningQueue); effectList.runningQueue = null; } if (onComplete) { onComplete(); } } } Effects = new Effects_class(); /*----------------------------------------------------------------------------------- Effect: var effect = new Effect([oDomElement|sID],{type:sType,to:int},iDuration(in seconds)); effect.animate(); Borrowed from: TERMS OF USE - EASING EQUATIONS Open source under the BSD License. Copyright (c) 2001 Robert Penner JavaScript version copyright (C) 2006 by Philippe Maegerman All rights reserved. -------------------------------------------------------------------------------------*/ var Effect = function(oEl,sType,oParams) { //Default argument values oParams = oParams || false; if(!oParams) { return; } //Constants this.oEl = Element.get(oEl); this._animType = sType || false; this.valueGetter = this.getValueGetterSetters().getter; this.valueSetter = this.getValueGetterSetters().setter; this._rawTo = oParams.to; this._rawFrom = oParams.from !== undefined ? oParams.from : this.valueGetter(); this._easing = Easing; this._easeMethod = oParams.easing && this._easing[oParams.easing] && this._easing[oParams.easing] !== undefined ? this._easing[oParams.easing] : this._easing.easeNone; this._duration = oParams.duration; this.isAnimating = false; this.setOnCompleteHandler(oParams.onComplete, oParams.context); //Time this._startTime = 0; this._prevTime = 0; this._time = 0; } Effect.prototype.animate = function(){ this.animateParallel(); this.onEnterFrame(); } Effect.prototype.animateParallel = function(){ this._to = (typeof this._rawTo == 'function') ? this._rawTo() : this._rawTo; this._from = (typeof this._rawFrom == 'function') ? this._rawFrom() : this._rawFrom; // So far backgorund is the only array // may have to figure out a more generic way to do this in the future. if (this._animType == 'background') { if (!(this._to instanceof Array)) { this._to = this.toRGB(this._to); } if (!(this._from instanceof Array)) { this._from = this.toRGB(this._from); } } this._delta = this.getDelta(); this._startTime = new Date().getTime(); this.isAnimating = true; // parallel animation calls nextFrame() explicitly //this.onEnterFrame(); } Effect.prototype.onEnterFrame = function() { if(this.isAnimating) { this.nextFrame(); var AnimClosure = function(context) { return function() { context.onEnterFrame() }; }; setTimeout(AnimClosure(this), 0); } } Effect.prototype.nextFrame = function() { this.setTime((this.getTimer() - this._startTime) / 1000); } Effect.prototype.getTimer = function() { return new Date().getTime() - this._time; } Effect.prototype.setTime = function(t){ this._prevTime = this._time; if (t > this._duration) { this._time = this._duration; this.update(); this.stop(); } else { this._time = t; this.update(); } } Effect.prototype.update = function(value) { if (this._from instanceof Array) { this.valueSetter([ this._easeMethod(this._time,this._from[0],this._delta[0],this._duration), this._easeMethod(this._time,this._from[1],this._delta[1],this._duration), this._easeMethod(this._time,this._from[2],this._delta[2],this._duration) ]); } else { this.valueSetter(this._easeMethod(this._time,this._from,this._delta,this._duration)); } } Effect.prototype.stop = function() { this.isAnimating = false; if (this.runningQueue) { Effects._runQueue(this.runningQueue); this.runningQueue = null; } this.update(); this.onComplete(); } Effect.prototype.getDelta = function(){ return (this._to instanceof Array) ? [ this._to[0] - this._from[0],this._to[1] - this._from[1], this._to[2] - this._from[2] ] : this._to - this._from; } Effect.prototype.setOnCompleteHandler = function(f,c){ if (c && f) { this.onComplete = function () { f.apply(c, arguments) }; } else { this.onComplete = f || function(){return false;}; } } /* return a setter/getter function for oEl: if you pass it a value, it will set that value for this.oEl and return it, if you dont, it will just return the current value for oEl */ Effect.prototype.getValueGetterSetters = function() { var oGS; //{getter:,setter:,object} switch(this._animType) { case "width": return { getter:function() { return Element.getSize(this.oEl).width }, setter:function(iWidth) { iWidth = iWidth >= 0 ? iWidth : 0; Element.setWidth(this.oEl,iWidth); } } break; case "height": return { getter:function() { return Element.getSize(this.oEl).height }, setter:function(iHeight) { iHeight = iHeight >= 0 ? iHeight : 0; Element.setHeight(this.oEl,Math.round(iHeight)); } } break; case "x": return { getter:function() { return this.oEl.offsetLeft; }, setter:function(iX) { this.oEl.style.left = iX + "px"; } } break; case "y": return { getter:function() { return this.oEl.offsetTop; }, setter:function(iY) { this.oEl.style.top = Math.round(iY) + "px"; } } break; case "opacity": return { getter:function() { var iOpac = this.oEl.style.opacity; return iOpac == "" || isNaN(iOpac) ? 100 : iOpac * 100; }, setter:function(iOpacity) { Element.setOpacity(this.oEl,iOpacity); } } break; case "scrollLeft": return { getter:function() { return this.oEl.scrollLeft; }, setter:function(iScrollLeft) { this.oEl.scrollLeft = iScrollLeft; } } break; case "scrollTop": return { getter:function() { return this.oEl.scrollTop; }, setter:function(iScrollTop) { return this.oEl.scrollTop = iScrollTop; } } case "background": return { getter:function() { return this.toRGB(this.oEl.style.backgroundColor); }, setter:function(aRGB) { this.oEl.style.backgroundColor = this.toHex(aRGB); return aRGB } } break; default: return false; break } } Effect.prototype.toRGB = function (hex) { hexInt = parseInt(hex.substr(1), 16); return [ hexInt >> 16, hexInt >> 8 & 255, hexInt & 255 ]; } Effect.prototype.toHex = function (rgb) { var hex = '#'; for (var i = 0; i < 3; i++) { rgb[i] = Math.min(255, Math.max(0, Math.round(rgb[i]))).toString(16); while (rgb[i].length < 2) { rgb[i] = '0' + rgb[i]; } hex += rgb[i]; } return hex; } /*------------------------------------------------------------------- Easing -------------------------------------------------------------------*/ var Easing = {}; Easing.easeNone = function (t, b, c, d) { return c*t/d + b; } Easing.backEaseIn = function(t,b,c,d,a,p){ if (s == undefined) var s = 1.70158; return c*(t/=d)*t*((s+1)*t - s) + b; } Easing.backEaseOut = function(t,b,c,d,a,p){ if (s == undefined) var s = 1.70158; return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; } Easing.backEaseInOut = function(t,b,c,d,a,p){ if (s == undefined) var s = 1.70158; if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; } Easing.elasticEaseIn = function(t,b,c,d,a,p){ if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (!a || a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; } Easing.elasticEaseOut = function (t,b,c,d,a,p){ if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (!a || a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b); } Easing.elasticEaseInOut = function (t,b,c,d,a,p){ if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) var p=d*(.3*1.5); if (!a || a < Math.abs(c)) {var a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; } Easing.bounceEaseOut = function(t,b,c,d){ if ((t/=d) < (1/2.75)) { return c*(7.5625*t*t) + b; } else if (t < (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; } else if (t < (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; } else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; } } Easing.bounceEaseIn = function(t,b,c,d){ return c - Easing.bounceEaseOut (d-t, 0, c, d) + b; } Easing.bounceEaseInOut = function(t,b,c,d){ if (t < d/2) return Easing.bounceEaseIn (t*2, 0, c, d) * .5 + b; else return Easing.bounceEaseOut (t*2-d, 0, c, d) * .5 + c*.5 + b; } Easing.strongEaseInOut = function(t,b,c,d){ return c*(t/=d)*t*t*t*t + b; } Easing.regularEaseIn = function(t,b,c,d){ return c*(t/=d)*t + b; } Easing.regularEaseOut = function(t,b,c,d){ return -c *(t/=d)*(t-2) + b; } Easing.regularEaseInOut = function(t,b,c,d){ if ((t/=d/2) < 1) return c/2*t*t + b; return -c/2 * ((--t)*(t-2) - 1) + b; } Easing.strongEaseIn = function(t,b,c,d){ return c*(t/=d)*t*t*t*t + b; } Easing.strongEaseOut = function(t,b,c,d){ return c*((t=t/d-1)*t*t*t*t + 1) + b; } Easing.strongEaseInOut = function(t,b,c,d){ if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; return c/2*((t-=2)*t*t*t*t + 2) + b; }