var Effect = {
	Transitions: {
		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) {
			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;
		},
		
		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:        30,   // 100= assume 66fps max.
		from:       0.0,
		to:         1.0,
		delay:      0.0,
		transition:	'sinoidal'
	},

	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() {
			if (this.state == 'idle') {
				var timestamp = new Date().getTime();
			
				this.startOn  = this.start + timestamp;
				this.finishOn = this.finish + timestamp;
		
				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") {
			  pos = (this.transition(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;
		}
	
	},
	
	Appear : function (id, options_alt) {
		this.options = {duration: 0.8, transition: 'linear'};
		if (options_alt) {
			for (var opt_name in options_alt) {
				this.options[opt_name] = options_alt[opt_name];
			}
		}
		
		this.effect = new Effect.Class(this.options);
		this.effect.transform = function(pos) {
			$(id).style.opacity = pos;
			$(id).style.filter = 'Alpha(opacity=' + pos * 100 + ')';
		}
		this.init = function() {
			$(id).style.opacity	= 0.0;
			$(id).style.filter	= 'Alpha(opacity=0)';
			this.effect.init();
		}
	},
	
	Disappear : function (id, options_alt) {
		this.options = {duration: 0.8, from: 1.0, to: 0.0, transition: 'linear'};
		if (options_alt) {
			for (var opt_name in options_alt) {
				this.options[opt_name] = options_alt[opt_name];
			}
		}
		
		this.effect = new Effect.Class(this.options);
		this.effect.transform = function(pos) {
			$(id).style.opacity = pos;
			$(id).style.filter = 'Alpha(opacity=' + pos * 100 + ')';
			if (pos == 1) {
				$(id).style.display = 'none';	
			}
		}
		this.init = function() {
			this.effect.init();
		}
	},
	
	Slider : function (id, orig_width, ext_width, options_alt) {
		var self = this;
		this.options = {duration: 0.8};
		if (options_alt) {
			for (var opt_name in options_alt) {
				this.options[opt_name] = options_alt[opt_name];
			}
		}
		this.orig_width = orig_width;
		this.ext_width = ext_width;
		this.cur_width;
		this.target_width;
		this.slider_ext = false;
		
		this.effect = new Effect.Class(this.options);
		this.effect.transform = function(pos) {
			$(id).style.width = self.cur_width + Math.round(self.target_width * pos) + 'px'; 
		}
		this.init = function() {
			if(this.effect.state == 'idle') {
				this.cur_width = parseInt($(id).style.width);
				var delta_width = this.ext_width - this.orig_width; 
				if (this.cur_width <= this.orig_width + delta_width / 2) {
					this.target_width = this.ext_width - this.cur_width; 
					this.slider_ext = true;
				}
				else {
					this.target_width = - this.cur_width + this.orig_width; 
					this.slider_ext = false;
				}
				this.effect.init();
			}
		}
	}
	
}

/* 

------------------------------------------ EINBINDUNG ---------------------------------------------- 

var effect1 = new Effect.Class({duration:2.0, transition:'log'});
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();

----------------------------------------------------------------------------------------------------

*/
