﻿/**
	Tweener.
	
	@author Nicholas Almeida
	@version 17:47 8/1/2008
	@example
		<code>
			var t = new Tweener();
			t.onInit = function(obj, initValue){
				alert(obj + ' -- ' + initValue);
			}
			t.onUpdate = function(obj, currentValue){
				console.info(currentValue);
			}
			t.onComplete = function(obj, end){
				alert(obj + ' -- ' + end);
			}
			t.run($('elm'), -200, 'left', 'px');
		</code>
*/
var _arrTweener = [];
var Tweener = function(){
	/**
		Private variables
	*/
	var obj = null;
	var end = null;
	var prop = null;
	var unit = null;
	var _interval = 0;
	
	/**
		Public handlers
	*/
	this.onComplete = undefined;
	this.onInit = undefined;
	this.onUpdate = undefined;
	
	/**
		Public variables
	*/
	this.isRunning = false; // return if Tweener is running or not.
	this.speed =  2.9; // default speed. higher is slower.
	
	/**
		Moves an element changing the style.left.
		
		@param: $obj:String or Object - html element.
		@param: $end:Number - final value.
		@param: $prop:String - CSS property.
	*/
	this.run = function($obj, $end, $prop, $unit){
		if(this.isRunning) return;
		obj = typeof($obj) == 'string' ? $($obj) : $obj; // TODO: typeof($obj) != 'string' ? ($obj.nodeName ? $obj : false) : ($($obj) ? $($obj) : false);
		end = $end;
		prop = $prop;
		unit = $unit;
		if(!obj) return alert('ERROR Slider.run: $obj not defined');
		if(end == undefined || isNaN(end)) return alert('ERROR Slider.run: $end not defined');
		if(!prop) return alert('ERROR Slider.run: $prop not defined');
		if(!unit) return alert('ERROR Slider.run: $unit not defined');
		var _this = this;
		if(this.onInit) this.onInit(obj, parseInt(obj.style[prop]) || 0);
		_arrTweener.push(this);
		_interval = setInterval(function(){
			_this.isRunning = true;
			var current = parseInt(obj.style[prop]) || 0;
			var v = _easing(current, end, _this.speed);
			if(v === false){
				v = end;
				_posObj(v);
				_this.stop();
				if(_this.onComplete) _this.onComplete(obj, end);
			}
			_posObj(v);
		}, 100);
	};
	
	/**
		Clear all Tweens.
		
	*/
	this.stopAllTweens = function(){
		for(var i=0; i<_arrTweener.length; i++){
			_arrTweener[i].stop();
		}
	};
	
	/**
		Clear the interval and set isRunning to false.
		
	*/
	this.stop = function(){
		this.isRunning = false;
		clearInterval(_interval);
		_removemeFrom_arrTweener(this);
	};
	
	
	/**
		Removes the flash from _arrTweener
		
		@param: $$me:Object - object to be removed.
	*/
	function _removemeFrom_arrTweener($me){
		for(i=0; i<_arrTweener.length; i++){
			if($me == _arrTweener[i]) _arrTweener.splice(i, 1);
		}
	}
	
	/**
		Changes the left style using the new $v value.
		
		@param: $v:Number - new left value.
	*/
	function _posObj($v){
		obj.style[prop] =  $v + unit;
		if(this.onUpdate) this.onUpdate(obj, $v);
	}
	/**
		Easing calc
		
		@param: $ini:Number - initial value.
		@param: $end:Number - final value.
		@param: $speed:Number - easing speed. Higher is slower.
		@return: c:Number - new left position or false when it is finished.
	*/
	function _easing($ini,$end,$speed){
		var c = Math.round($ini+=($end-$ini)/$speed);
		if(Math.abs(c - end) <= 2.5) return false;
		return c;
	}
};

var SpeedTest = {
	speed: undefined,
	run: function(){
		var startTime = new Date() ;
		createElm(false,['div', {id: 'divSpeedTest', 'style':'position:absolute;top:-10000px;left:-10000px;'},'']);
		for( var i = 0; i <= 2000; i++ ) {
			$('divSpeedTest').style.left = (-i) + 'px';
			$('divSpeedTest').style.top = (-i) + 'px';
		}
		delElm('divSpeedTest');
		var endTime = new Date();
		return this.speed = (endTime - startTime);
	},
	runOnce: function(){
		if(this.speed) return this.speed;
		else return this.run();
	}
};