// --------------------------------------------------------------------------
// Objeto:      AjaxFX
// Comentario:  Este componente permite cambiar de tamaños o mover objetos
//              de manera automática y además permite ejecutar varios
//              eventos a la vez.
// Programador: Ivan Mattoni (ENE-2009)
// Version:     2
// --------------------------------------------------------------------------


var AjaxFX={

	// PROPERTIES PUBLIC
	working: false,

	// METHODS PUBLIC
	Expand: function(action, object, options){
		if( this.working || this._opacity.working ) return;
		if( typeof(action)!="object" ) return;			
		if( !object ){
			this._reset_variables();
			return;
		}
		
		this.working=true;
		
		options = this._valid_var( options, this._default_options.get_param('Expand'), 'Expand' );
		
		if( !this._initialize(options, object) ) {
			this.working=false;
			return;
		}
		
					
		for( var i=0; i<=action.length-1; i++ ){				
			if( action[i].toLowerCase()!="expand_right" && action[i].toLowerCase()!="expand_down" && action[i].toLowerCase()!="expand_left" && action[i].toLowerCase()!="expand_up" ){
				action = [this._default_options.Expand_Default];
			}
		}			
		
		this._movement = action;			
		this._tempID = setInterval("AjaxFX._movements()", options.duration);
	},

	Move: function(action, object, options){
		if( this.working || this._opacity.working ) return;
		if( typeof(action)!="object" ) return;			
		if( !object ){
			this._reset_variables();
			return;
		}

		this.working=true;

		options = this._valid_var( options, this._default_options.get_param('Move'), 'Move' );		
		
		if( !this._initialize(options, object) ) {
			this.working=false;
			return;
		}
		
		for( var i=0; i<=action.length-1; i++ ){
			if( action[i].toLowerCase()!="move_left" && action[i].toLowerCase()!="move_right" && action[i].toLowerCase()!="move_up" && action[i].toLowerCase()!="move_down" ){
				action = [this._default_options.Move_Default];
			}
		}

		this._movement = action;			
		this._opacity.add();
		this._tempID = setInterval("AjaxFX._movements()", options.duration);
	},
	
	multiple_actions: function(){				
		if( this.working || this._opacity.working ) return;
		if( arguments.length > 0 ){
			this._indexArray=0;
			for( var i=0; i<=arguments.length-1; i++ ){
				if( typeof(arguments[i])=="string" ){
					this._fxArray[i] = arguments[i];
				}else{
					alert("Error en la función multiple_actions\nEl parametro numero "+i+"debe ser de tipo string.");
					return;	
				}
			}
			eval( this._fxArray[0] );
		}
	},
	
	morph: function(id1, id2, options){
		if( this.working ) return;
		
		this.working=true;

		var obj1 = this._$(id1);
		var obj2 = this._$(id2);

		if( !obj1 || !obj2 ) return;

		this._options = this._valid_var( options, this._default_options.get_param('Morph'), 'Morph' );
				
		obj1.style.position="absolute";
		obj2.style.position="absolute";

		obj2.style.left = isNaN(parseInt(obj1.style.left)) ? "0px" : parseInt(obj1.style.left)+"px";
		obj2.style.top  = isNaN(parseInt(obj1.style.top)) ? "0px" : parseInt(obj1.style.top)+"px";
		
		this._set_opacity(obj2, 0);
		obj2.style.display="";
		
		this._morph_transition.start(obj1, obj2);
	},
	
	opacity:{
		inc1:0,
		inc2:0,
		tempID1: false,
		tempID2: false,
		options1: {},
		options2: {},
		object1: false,
		object2: false,
		
		show: function(object, options){
			if( !object || AjaxFX._working1 ) return;
			AjaxFX.working=true;
			AjaxFX._working1=true;
			options = AjaxFX._valid_var( options, AjaxFX._default_options.get_param('Opacity'), 'Opacity' );
			AjaxFX._set_opacity(object, options.initial);
			
			this.inc1 = options.initial;
			this.options1 = options;
			this.object1 = object;
			this.tempID1 = setInterval("AjaxFX.opacity.to_opacity_add()", options.duration);
		},
		hidden: function(object, options){
			if( !object || AjaxFX._working2 ) return;			
			AjaxFX.working=true;			
			AjaxFX._working2=true;			
			options = AjaxFX._valid_var( options, AjaxFX._default_options.get_param('Opacity'), 'Opacity' );			
			AjaxFX._set_opacity(object, options.initial);
			
			this.inc2 = options.initial;
			this.options2 = options;
			this.object2 = object;
			this.tempID2 = setInterval("AjaxFX.opacity.to_opacity_remove()", options.duration);			
		},
		
		to_opacity_add: function(){			
			if( this.inc1 < this.options1.max ){
				this.inc1++;
				AjaxFX._set_opacity(this.object1, this.inc1);
			}else{
				clearInterval(this.tempID1);	
				this.options1.on_finalizer();
				
				AjaxFX._working1=false;								
				if( !AjaxFX._working2 ) AjaxFX.working=false;
			}
		},
		to_opacity_remove: function(){
			if( this.inc2 > this.options2.min ){
				this.inc2--;
				AjaxFX._set_opacity(this.object2, this.inc2);
			}else{
				clearInterval(this.tempID2);
				this.options2.on_finalizer();
				
				AjaxFX._working2=false;
				if( !AjaxFX._working1 ) AjaxFX.working=false;
			}
		}
		
	},		
		
		




//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------



	
	
	// PROPERTIES PRIVATE
	_object: false,
	_options: {},
	_tempID: false,
	_incX: 0,
	_incY: 0,
	_movement: false,
	_working1: false,
	_working2: false,
	_working3: false,
	_working4: false,
	_working5: false,
	_working6: false,
	_working7: false,
	_working8: false,
	_flag: false,
	_fxArray: [],
	_indexArray: 0,
	_default_options:{
		Expand:{
			toY: 100,
			toX: 100,
			duration: 25,
			speed: 0.2,
			acel_initial: 0.5,
			acel_end: 5,
			progressive_speed: true,
			position_relative: true
		},
		
		Move:{
			toX: 250,
			toY: 250,
			duration: 25,
			speed: 0.2,
			acel_initial: 0.5,
			acel_end: 5,
			progressive_speed: true,
			position_relative: false
		},
		
		Morph:{
			duration: 80,
			duration_transition: 200,		
			minOpacity: 0
		},
		
		Opacity:{
			duration: 80,
			min: 0,
			max: 10,
			initial: 0,
			on_finalizer: function(){}
		},
		
		Move_Default: 'move_right',
		Expand_Default: 'expand_down',
		
		//-
		get_param: function(p){
			eval("var prop = this."+p+";");
			var strReturn = "var returnProp = {";
			var typedata;
			for( o in prop ){
				eval("typedata = typeof( this."+p+"."+o+" );");
				strReturn += o+": '"+typedata+"',";
			}
						
			eval( strReturn.substr(0, strReturn.length-1)+"}" );
			return returnProp;
		}
	},
	
	// METHODS PRIVATE
	_initialize: function(options, object){
		this._object = object;
		if( this._object ){
			this._object.style.position = ( options.position_relative ) ? 'relative' : 'absolute';
			//this._object.style.overflow = "hidden";
			this._options = options;
			this._incX = ( options.progressive_speed ) ? options.acel_initial : options.speed;		
			this._incY = ( options.progressive_speed ) ? options.acel_initial : options.speed;		
			return true;
			
		}else return false;
	},
		
	_movements: function(){

		for( var i=0; i<=this._movement.length-1; i++ ){		
			
			switch( this._movement[i] ){
			case "expand_down":
				this._working1 = true;
				var y = parseInt(this._object.style.height);
				if( y < this._options.toY ){
					
					if( this._options.progressive_speed ){
						if( y < (this._options.toY-50) )
							this._incY = this._get_speed_aceleration(this._incY);
						else
							this._incY = this._get_speed_desaceleration(this._incY);					
					}
									
					y+=this._incY;
					this._object.style.height = y+"px";
				}else{
					this._working1 = false;
					this._movement[i] = "";
				}
			break;
	
			case "expand_up":
				this._working2 = true;
				var y = parseInt(this._object.style.height);
				if( y > this._options.toY ){
					
					if( this._options.progressive_speed ){
						if( y > (this._options.toY+50) )
							this._incY = this._get_speed_aceleration(this._incY);
						else
							this._incY = this._get_speed_desaceleration(this._incY);					
					}
									
					y-=this._incY;
					this._object.style.height = y+"px";
				}else{
					this._working2 = false;
					this._movement[i] = "";
				}
			break;	
	
			case "expand_right":
				this._working3 = true;
				var x = parseInt(this._object.style.width);
				if( x < this._options.toX ){
					if( this._options.progressive_speed ){
						if( x < (this._options.toX-50) )
							this._incX = this._get_speed_aceleration(this._incX);
						else
							this._incX = this._get_speed_desaceleration(this._incX);					
					}
									
					x+=this._incX;
					this._object.style.width = x+"px";
				}else{
					this._working3 = false;
					this._movement[i] = "";
				}
			break;

			case "expand_left":
				this._working4 = true;
				var x = parseInt(this._object.style.width);
				if( x > this._options.toX ){
					if( this._options.progressive_speed ){
						if( x > (this._options.toX-50) )
							this._incX = this._get_speed_aceleration(this._incX);
						else
							this._incX = this._get_speed_desaceleration(this._incX);
					}
									
					x-=this._incX;
					this._object.style.width = x+"px";
				}else{
					this._working4 = false;
					this._movement[i] = "";
				}
			break;

			case "move_down":
				this._working5 = true;
				var y = parseInt(this._object.style.top);
				if( y < this._options.toY ){
					
					if( this._options.progressive_speed ){
						if( y < (this._options.toY-50) )
							this._incY = this._get_speed_aceleration(this._incY);
						else
							this._incY = this._get_speed_desaceleration(this._incY);
					}
									
					y+=this._incY;
					this._object.style.top = y+"px";
				}else{
					this._working5 = false;
					this._movement[i] = "";
					this._flag=true;
				}
			break;
	
			case "move_up":
				this._working6 = true;
				var y = parseInt(this._object.style.top);
				if( y > this._options.toY ){
					
					if( this._options.progressive_speed ){
						if( y > (this._options.toY+50) )
							this._incY = this._get_speed_aceleration(this._incY);
						else
							this._incY = this._get_speed_desaceleration(this._incY);					
					}
									
					y-=this._incY;
					this._object.style.top = y+"px";
				}else{
					this._working6 = false;
					this._movement[i] = "";
					this._flag=true;
				}			
			break;
	
			case "move_left":
				this._working7 = true;
				var x = parseInt(this._object.style.left);
				if( x > this._options.toX ){
					
					if( this._options.progressive_speed ){
						if( x > (this._options.toX-50) )
							this._incX = this._get_speed_aceleration(this._incX);
						else
							this._incX = this._get_speed_desaceleration(this._incX);
					}
									
					x-=this._incX;
					this._object.style.left = x+"px";
				}else{
					this._working7 = false;
					this._movement[i] = "";
					this._flag=true;
				}				
			break;
	
			case "move_right":
				this._working8 = true;
				var x = parseInt(this._object.style.left);
				if( x < this._options.toX ){
					
					if( this._options.progressive_speed ){
						if( x < (this._options.toX-50) )
							this._incX = this._get_speed_aceleration(this._incX);
						else
							this._incX = this._get_speed_desaceleration(this._incX);
					}
									
					x+=this._incX;
					this._object.style.left = x+"px";
				}else{
					this._working8 = false;
					this._movement[i] = "";
					this._flag=true;
				}						
			break;
			}	// END SWITCH
		
		} // END FOR
		
		if( !this._working1 && !this._working2 && !this._working3 && !this._working4 && !this._working5 && !this._working6 && !this._working7 && !this._working8  ){
				clearInterval(this._tempID);
				if( this._flag ){ 
					this._opacity.remove();
					this._reset_variables();
				}else{				
					this._reset_variables();

					if( this._fxArray.length >0 && !this._flag ){
						this._execute_next_fx();
					}
				}
		}
	},
	
	_get_speed_aceleration: function(inc){
		if( inc < this._options.acel_end ){
			inc += this._options.speed;
		}else{
			inc = this._options.acel_end;
		}
		return inc;
	},
	
	_get_speed_desaceleration: function(inc){
		if( inc > this._options.acel_initial ){
			inc -= this._options.speed;
		}else{
			inc = this._options.acel_initial;
		}
		return inc;
	},

	_opacity:{
		tempID: false,
		opacity: null,
		working: false,
		
		add: function(){
			this.opacity = 10;
			this.working=true;
			this.tempID = setInterval("AjaxFX._opacity.to_increase()", 20);
		},

		remove: function(){
			this.opacity = 5;			
			this.working=true;
			this.tempID = setInterval("AjaxFX._opacity.to_fall()", 20);
		},
		
		to_increase: function(){
			if( this.opacity>5 ){
				this.opacity--;
				AjaxFX._set_opacity(AjaxFX._object, this.opacity);
			}else{
				clearInterval(this.tempID);
				this.working=false;
			}
		},
		
		to_fall: function(){		
			if( this.opacity<10 ){
				this.opacity++;
				AjaxFX._set_opacity(AjaxFX._object, this.opacity);
			}else{
				clearInterval(this.tempID);
				this.working=false;
				AjaxFX._execute_next_fx();
			}			
		}		
	},
	
	_set_opacity: function(o, val){
		if( o.filters ) {  //For IE
			val = parseInt(val)*10;
			if( val>100 ) val=100;
			
			try {
				o.filters.item("DXImageTransform.Microsoft.Alpha").opacity = val;
			} catch (e) { 
				// If it is not set initially, the browser will throw an error.  This will set it if it is not set yet.
				if( val==100 ) o.style.filter="";
				else o.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+val+')';
			}
		} else {
			val = parseInt(val)*0.1;
			if( val >1 ) val=1;
			
			o.style.opacity = val;
			o.style.MozOpacity = val;  //This is for older Mozilla Browsers
		}			
	},
	
	_valid_var: function(optionsSource, options, nameprop){
		if( !optionsSource ) optionsSource={};		
		var strReturn = "var newOptions = {";
		var value, typedata, valuedata;
		for( option in options ){
			eval("value = options."+option+";");			
			eval("v = optionsSource."+option+";");
			
			if( typeof(v)!="undefined" )
			{				
				eval("typedata = typeof(optionsSource."+option+");");
				eval("valuedata = optionsSource."+option+";");								
	
				if( typedata!=value ){
					strReturn+=option+": AjaxFX._default_options."+nameprop+"."+option+",";
				}else{
					strReturn+=option+": "+String(valuedata)+",";
				}
				
			}else{
				strReturn+=option+": AjaxFX._default_options."+nameprop+"."+option+",";
			}
		}
				
		eval( strReturn.substr(0, strReturn.length-1)+"}" );
		return newOptions;
	},
	
	_reset_variables: function(){
		this.options = {};
		this.working=false;
		this._flag=false;
	},
	
	_execute_next_fx: function(){
		this._indexArray++;
		eval( this._fxArray[this._indexArray] );
		if( this._indexArray==this._fxArray.length-1 ){
			this._fxArray=[];				
		}
	},
	
	_$: function(id){
		return document.getElementById(id);	
	},
	
	_morph_transition: {
		opacity1: 0,
		opacity2: 0,
		object1: false,
		object2: false,
		tempID1: false,
		tempID2: false,
		
		start: function(o1, o2){
			this.object1 = o1;
			this.object2 = o2;
			this.opacity1 = 10;
			this.opacity2 = AjaxFX._options.minOpacity;
			
			this.tempID1 = setInterval("AjaxFX._morph_transition.to_vanish()", AjaxFX._options.duration);			
			setTimeout("AjaxFX._morph_transition.tempID2 = setInterval('AjaxFX._morph_transition.to_appear()', AjaxFX._options.duration)", AjaxFX._options.duration_transition);
			
		},
		
		
		
		to_vanish: function(){  //Desvanecer
			if( this.opacity1 > AjaxFX._options.minOpacity ){
				this.opacity1--;
				AjaxFX._set_opacity( this.object1, this.opacity1 );
			}else{
				clearInterval(this.tempID1);
			}
		},
		
		to_appear: function(){  //Aparecer
			if( this.opacity2 < 10 ){
				this.opacity2++;
				AjaxFX._set_opacity( this.object2, this.opacity2 );
			}else{
				clearInterval(this.tempID2);
				AjaxFX.working=false;
			}			
		}
	}
		
}