function Animation(el, io){
	var This = this;
	this.element = new Element(el, io);
	var next = function(){ };
	var args = false;  
	this.cancel = function(){ this.time.reset(); this.time.stop(); }
  
	this.update = function() { 
		var t = This.trans( This.time.getTime() / This.dur );
		if(isNum(da)){
			var na  = oa + (t * da);
			This.element.setOpacity(na);
		}
		if(isNum(dx) || isNum(dy)){
			var nx  = ox + t * dx;  	     
			var ny  = oy + t * dy;
			This.element.setPosition(nx, ny);
		}
		if(isNum(dw) || isNum(dh)){
			var nw  =  ow + (t * dw);  	     
			var nh  =  oh + (t * dh);
			if(This.element.center){
				var cx = (This.element.width - nw) * This.element.center.x;
				var cy = (This.element.height - nh) * This.element.center.y;
				This.element.setPosition( This.element.x + cx, This.element.y + cy);
			}
			This.element.setDimensions(nw, nh);
		}
		if(observer) observer();
		if(t == 1){
			if(_effect.y && isNum(_effect.y)) This.element.element.style.top = _effect.y + 'px';
			if(_effect.x && isNum(_effect.x)) This.element.element.style.left = _effect.x + 'px';
			This.complete = true;
			try{ 
				 next(args);
				 next = new function(){};
			}catch(e){ }
		}
	}
	var _effect;
	var oa; var ox; var oy; var ow; var oh; 
	var da; var dx; var dy; var dw; var dh;
	this.effect = function(fect, after, afterArgs){

		if(this.complete){
			_effect = fect;
			if(fect.duration) This.dur = fect.duration;
			if(fect.fps) This.fps = fect.fps;
			if(fect.trans) This.trans = fect.trans;
			if(after) next = after;
			if(afterArgs) args = afterArgs;
			if(isNum(fect.alpha)){   oa = This.element.alpha;     da = fect.alpha - oa; }
			if(isNum(fect.width)){  ow = This.element.width;   dw = fect.width - ow;  }
			if(isNum(fect.height)){  oh = This.element.height;  dh = fect.height - oh; }
			if(isNum(fect.x)){	 ox = This.element.x;       dx = fect.x - ox;  }
			if(isNum(fect.y)){	  oy = This.element.y;	    dy = fect.y - oy; }
			this.complete = false;
			this.time.reset();
			this.time.start(This.dur, This.fps);  
		}
	}
	
	var observer = false
	this.setUpdateObserver= function(obj){ observer = obj; }
	this.linear = function(x){ return x; }
	if(!io) io = { };
	this.time = new Timer(this.dur, this.fps, this.update);
	this.trans = (!io.trans) ? this.linear : io.trans;
	this.fps = (io.fps) ? io.fps : (1/24);
	this.dur = (io.duration) ? io.duration : 1;
	this.complete = true;
	function isNum(val) { 
		if(val==0) 
			return true; 
		else if(typeof(val) == 'number');
		 	return true;
		return false; }
}  

function Timer(duration, updateInterval, listener){
  	this.update = (updateInterval) ? updateInterval : (1/24);
	this.duration = (duration) ? duration : 1;
	this.listeners = new Array();
	if(listener) this.listeners.push(listener);
	var time = 0;  var timer = null;
	var self = this; var check;
	
	this.addListener = function(listenerObj){
		this.listeners.push(listenerObj);
	}
	
	this.start = function(duration, interval){
		if(duration) this.duration = duration;
		if(interval) this.update = interval;
		check = this.update;
		run();
	}
	
	this.stop = function(nocall){ 
		window.clearTimeout(timer);
		time = this.duration; 
		for(var l=0; l < self.listeners.length; l++)
			self.listeners[l].call(this, self); 
		
	}
							 
	this.getTime = function(){ return time; }
	this.reset = function() {  window.clearTimeout(timer); 
									   time = 0; 
									   check = 0; 
										timer = null; 
									}
    function run(){
		if(time <= self.duration){
			if(time >= check){
				for(var l=0; l < self.listeners.length; l++)
						self.listeners[l].call(this, self);
				check += self.update;	
			}
			time+= 0.01;			
			loop();
			return;	
		}
	  self.stop();
	}
	
	function loop(){
		timer = window.setTimeout(run, 10);
	}
};


function Physics(){
	
	
	this.linear = function(x){ return x; }
	
 
	this.easeIn = function(x){ return Math.pow(x,2); }
	this.easeOut = function(x){ return 1 - Math.pow((x-1), 2); }

	
	
	this.sineWave = function(x){ return Math.sin(x*Math.PI/2); }
	
   
	this.spring = function(x){
		if(x < 0.65)
			return 1.1 * Math.sin(x * (Math.PI/1.5666) ); 
		else if(x < 1)
			return 1 + 0.1 * Math.sin(3.3 * (x +0.21) * Math.PI);	
		else
			return 1;
		
	}
	
	this.snap = function(x){ 
		if(x < 1)
			return 1.1 * Math.sin(x * (Math.PI/1.5666) );  
		else
			return 1;
	}
}
var physics = new Physics();