var Effect = {
	Transitions: {
		
		// scriptaculous
		linear: function(pos){
			return pos;
		},
		sinoidal: function(pos) {
			return (-Math.cos(pos * Math.PI) / 2) + .5;
		},
		reverse: function(pos) {
			return 1-pos;
		},
		flicker: function(pos) {
			var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
			return pos > 1 ? 1 : pos;
		},
		wobble: function(pos) {
		return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
		},
		pulse: function(pos) {	// Zusatz-Option 'pulses', Standardwert 5
			return (-Math.cos((pos*((this.pulses||5)-.5)*2)*Math.PI)/2) + .5;
		},
		spring: function(pos) {
			return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
		},
		none: function(pos) {
			return 0;
		},
		full: function(pos) {
			return 1;
		},
		
		// mootools
		Pow: function(pos){	// Zusatzoption 'factor', Standardwert 6
			return Math.pow(pos, this.factor || 6);
		},
	
		Expo: function(pos){
			return Math.pow(2, 8 * (pos - 1));
		},
	
		Circ: function(pos){
			return 1 - Math.sin(Math.acos(pos));
		},
	
		Sine: function(pos){
			return 1 - Math.sin((1 - pos) * Math.PI / 2);
		},
	
		Back: function(pos){	// Zusatzoption 'factor', Standardwert 1.618
			x = this.factor || 1.618;
			return Math.pow(pos, 2) * ((x + 1) * pos - x);
		},
	
		Bounce: function(pos){
			var value;
			for (var a = 0, b = 1; 1; a += b, b /= 2){
				if (pos >= (7 - 4 * a) / 11){
					value = b * b - Math.pow((11 - 6 * a - 11 * pos) / 4, 2);
					break;
				}
			}
			return value;
		},
	
		Elastic: function(pos){	// Zusatzoption 'factor', Standardwert 1
			return Math.pow(2, 10 * --pos) * Math.cos(20 * pos * Math.PI * (this.factor || 1) / 3);
		},
	
		// eigene
		pow: function(pos) {													// erst langsam, dann immer schneller
			return Math.pow(pos, 4);
		},
		sqrt: function(pos) {													// erst schnell, dann immer langsamer
			return Math.sqrt(pos);
		},
		sin: function(pos) {													// zuerst linear, dann verlangsamt
			return Math.sin(pos * Math.PI / 2);
		},
		cosin: function(pos) {													// zuerst beschleunigt, dann linear
			return - Math.cos(pos * Math.PI / 2) + 1;
		},
		tan: function(pos) {													// zuerst langsame, dann steile Beschleunigung
			return Math.tan(pos * 1.4711275) / 10;
		},
		cotan: function(pos) {													// zuerst starke Beschleunigung, dann Verlangsamung
			return (Math.tan(pos * 1.4711275 - 1.4711275) + 10) / 10;
		},
		log: function(pos) {													// stetige Beschleunigung und Verlangsamung
			return Math.log(pos * 10 + 1) / 2.397895;
		}
	},
	
	DefaultOptions : {
		duration:   1.0,   	// seconds
		fps:        60,   	// 100= assume 66fps max.
		from:       0.0,	// 0.0-1.0
		to:         1.0,	// 0.0-1.0
		delay:      0.0,	// seconds
		transition:	'sinoidal',
		dir:		'Normal'	// Normal/Reverse/InOut
	},

	Class : function (options) {
		
		for (var opt_name in Effect.DefaultOptions) {
			this[opt_name] = Effect.DefaultOptions[opt_name];
		}
		for (var opt_name in options) {
			this[opt_name] = options[opt_name];
		}
		
		this.transition = Effect.Transitions[this.transition];
		
		this.currentFrame 	= 0;
		this.interval		= null;
		this.state        	= 'idle';
		this.start	      	= this.delay * 1000;
		this.finish	     	= this.start + (this.duration * 1000);
		this.fromToDelta  	= this.to - this.from;
		this.totalTime    	= this.finish - this.start;
		this.totalFrames  	= this.fps * this.duration;
	
		this.init = function() {
			var timestamp = new Date().getTime();
		
			this.startOn  = this.start + timestamp;
			this.finishOn = this.finish + timestamp;
		
			if (this.state == 'idle') {
				var self = this;
				this.interval = setInterval(function(){self.loop()}, 15);
			}
		}
		
		this.loop = function() {
			var timePos = new Date().getTime();
			if (this.state == 'finished') this.remove();
			else this.timer(timePos);
		}
		
		this.timer = function(timePos) {
			if (timePos >= this.startOn) {
				if (timePos >= this.finishOn) {
					this.render(1.0);
					this.cancel();
					return;
				}
				var pos   = (timePos - this.startOn) / this.totalTime,
					frame = Math.round(pos * this.totalFrames);
				if (frame > this.currentFrame) {
					this.render(pos);
					this.currentFrame = frame;
				}
			}
		}
	  
		this.render = function(pos) {
			if (this.state === "idle") {
			  this.state = "running";
			}
			if (this.state === "running") {
			  switch(this.dir) {
			  	case 'Normal': 	pos = this.transition(pos); break;
				case 'Reverse':	pos = 1 - this.transition(1 - pos); break;
				case 'InOut':	pos = (pos <= 0.5) ? this.transition(2 * pos) / 2 : (2 - this.transition(2 * (1 - pos))) / 2;
			  }
			  pos = pos * this.fromToDelta + this.from;
			  this.transform(pos);
			}
		}
		
		this.transform = function () {}
		
		this.cancel = function() {
			this.state = 'finished';
		}
	
		this.remove = function() {
			  clearInterval(this.interval);
			  this.interval = null;
		}
	
	}
	
}

/* 

------------------------------------------ EINBINDUNG ---------------------------------------------- 

var effect1 = new Effect.Class({duration:2.0, transition:'log', dir: 'Out'});
effect1.transform = function(pos) {
	document.getElementById('box').style.height = Math.round(pos * 400 + 100) + 'px';
}

var effect2 = new Effect.Class({delay:2.0, transition:'sin'});
effect2.transform = function(pos) {
	document.getElementById('box').style.height = Math.round(pos * 140 + 500) + 'px';
}

effect1.init();
effect2.init();

----------------------------------------------------------------------------------------------------

*/