Extend(
	$E.prototype
	,{
		//f = callback function at each step
		//d = duration = how long (1000 = 1 second)
		//s = optional step interval
		step : function(f, d, s){
			var p
					,t = this	//bind this
					,i = (new Date).getTime()
					,n = setInterval(
						function(){
							f.apply(t, [p = ((new Date).getTime() - i) / d]);
							if(p >= 1){
								clearInterval(n);
								(t.onstepend || $X).call(t, i);
								n = t = null;
							}
						}
						,s
					);
			//return the step id
			return i;
		}
		,linear : function(Y, X, d, s){
			var t = this	//bind this
					,dx = this.X() - X
					,dy = this.Y() - Y;
			t.step(
				function(i){
					var y = i * dy + Y
							x = i * dx + X;
					(t.onlinear || $X).call(t, i, y, x);
					t.move(y, x);
				}
				,d
				,s
			);
		}
		,wipe : function(d, s, y, f){
			var t = this	//bind this
					,X = t.X()
					,Y = t.Y()
					,W = t.W()
					,H = t.H();
			//return the step id
			//y = type (0 = horizontal, 1 = vertical)
			//if f=true then wipe off
			//if f = false or null then wipe on
			return this.step(
				function(i){
					if(f)i = 1 - i;
					(t.onwipe || $X).call(t, i);
					t.crop(0, y ? W : W * i, y ? H * i : H, 0);
				}
				,d
				,s
			);
		}
		,fade : function(d, s, f){
			var t = this;	//bind this
			//return the step id
			//if f=true then fade out
			//if f = false or null then fade in
			return this.step(
				function(i){
					if(f)i = 1 - i;
					(t.onfade || $X).call(t, i);
					t.O(i *= 100);
				}
				,d
				,s
			);
		}
	}
);

