//
//  This script was created
//  by Mircho Mirev
//  mo /mo@momche.net/
//
//	:: feel free to use it BUT
//	:: if you want to use this code PLEASE send me a note
//	:: and please keep this disclaimer intact
//

var cMoEffects;
if( !cMoEffects )
{
	cMoEffects = {};
}
if( !cMoEffects.cEffect )
{
	cMoEffects.cEffect = {};
}

if( !Function.prototype.andThen )
{
	Function.prototype.andThen = function( g )
	{
		var f = this;
		return function()
		{
			f();
			g();
		}
	}
}

cMoEffects.cEffect = function( hOptions )
{
	this.hTimer = null;
	this.nCurrentStep = 0;
	this.nInterval = 0;
	
	this.hOptions = {
		nSteps : 10,
		nFPS : 0,
		nDuration : 500,
		onStart : function(){},
		onStop : function(){},
		onFinish : function(){}
	};
	this.setOptions( hOptions );
	
	if( this.hOptions.nFPS > 0 )
	{
		this.nInterval = Math.floor( 1000 / this.hOptions.nFPS );
		this.hOptions.nSteps = Math.round( this.nDuration / this.nInterval ) + 1;
	}
	else
	{
		this.nInterval = Math.round( this.hOptions.nDuration / this.hOptions.nSteps );
	}
	
	return this;
}

cMoEffects.cEffect.prototype.setOptions = function( hOptions )
{
	for( var hKey in hOptions )
	{
		this.hOptions[ hKey ] = hOptions[ hKey ];
	}
}

cMoEffects.cEffect.prototype.calculate = function()
{
}

cMoEffects.cEffect.prototype.playAgain = function()
{
}


cMoEffects.cEffect.prototype.start = function()
{
	this.hOptions.onStart();
	this.play();
}

cMoEffects.cEffect.prototype.stop = function()
{
	this.hOptions.onStop()
}

cMoEffects.cEffect.prototype.doFrame = function()
{
}

cMoEffects.cEffect.prototype.play = function()
{
	this.nCurrentStep++;

	this.doFrame()
	
	if( this.nCurrentStep < this.hOptions.nSteps - 1 ) 
	{
		var hSelf = this;
		window.setTimeout( function() { hSelf.play() }, this.nInterval );
	}
	else
	{
		(this.hOptions.onStop).andThen( this.hOptions.onFinish.call( this ) );
	}
}

/* Fader effect */
cMoEffects.cFade = function( hElement, nStartOpacity, nEndOpacity, hOptions )
{
	cMoEffects.cEffect.call( this, hOptions );

	if( typeof hElement == 'string' )
	{
		hElement = document.getElementById( hElement );
	}

	this.sId = hElement.id;
	
	this.aOpacities = new Array();
	this.playAgain( nStartOpacity, nEndOpacity );
}

cMoEffects.cFade.prototype = new cMoEffects.cEffect();
cMoEffects.cFade.prototype.constructor = cMoEffects.cFade;

cMoEffects.cFade.prototype.calculate = function()
{
	var nOpacityStep = ( this.nStartOpacity - this.nEndOpacity ) / this.hOptions.nSteps;
	for( var nI = 0; nI < this.hOptions.nSteps - 1; nI++ )
	{
		this.aOpacities[ nI ] = this.nStartOpacity - nI * nOpacityStep;
	}
	this.aOpacities[ nI ] = this.nEndOpacity;
}

cMoEffects.cFade.prototype.playAgain = function( nStartOpacity, nEndOpacity )
{
	this.nStartOpacity = nStartOpacity;
	this.nEndOpacity = nEndOpacity;
	this.calculate();
	this.start();
}

cMoEffects.cFade.prototype.doFrame = function()
{
	cMoEffects.cFade.setOpacity( this.sId, this.aOpacities[ this.nCurrentStep ] );
}

cMoEffects.cFade.setOpacity = function( sId, nValue )
{
	var hElement = document.getElementById( sId );
	if( hElement )
	{
		try
		{
			nValue = Math.floor( nValue );
			//if( hElement.filters != null && hElement.filters.alpha != null )
			if( hElement.filters != null && hElement.filters.alpha != null )
			{
				hElement.filters.alpha.opacity = nValue;
			}
			else if( typeof hElement.style.opacity != 'undefined' )
			{
				hElement.style.opacity = nValue/100;
			}
			else if( typeof hElement.style.MozOpacity != 'undefined'  )
			{
				hElement.style.MozOpacity = nValue/100;
			}
		}
		catch( hE )
		{
			return;
		}
	}
}

/* Fader effect */

/* Color effect */
cMoEffects.cColor = function( hElement, nStartColor, nEndColor, bBGColor, hOptions )
{
	cMoEffects.cEffect.call( this, hOptions );

	if( typeof hElement == 'string' )
	{
		hElement = document.getElementById( hElement );
	}

	this.sId = hElement.id;
	
	this.aColors = new Array();
	if( typeof( nStartColor ) == 'string' )
	{
		nStartColor = cMoEffects.cColor.colorToNumber( nStartColor );
	}

	if( typeof( nEndColor ) == 'string' )
	{
		nEndColor = cMoEffects.cColor.colorToNumber( nEndColor );
	}
	
	this.playAgain( nStartColor, nEndColor, bBGColor );
}

cMoEffects.cColor.prototype = new cMoEffects.cEffect();
cMoEffects.cColor.prototype.constructor = cMoEffects.cColor;

cMoEffects.cColor.prototype.calculate = function()
{
	var nColorStep = Math.round( ( this.nStartColor - this.nEndColor ) ) / this.hOptions.nSteps;

	var nStartR = ( this.nStartColor & 0xff0000 ) >>> 16;
	var nStartG = ( this.nStartColor & 0x00ff00 ) >>> 8;
	var nStartB = ( this.nStartColor & 0x0000ff );
	
	var nEndR = ( this.nEndColor & 0xff0000 ) >>> 16;
	var nEndG = ( this.nEndColor & 0x00ff00 ) >>> 8;
	var nEndB = ( this.nEndColor & 0x0000ff );

	var nColor;
	for( var nI = 0; nI < this.hOptions.nSteps - 1; nI++ )
	{
		nColor = nStartR * ( ( this.hOptions.nSteps - nI ) / this.hOptions.nSteps ) + nEndR * ( nI / this.hOptions.nSteps ) << 16 | nStartG * ( ( this.hOptions.nSteps - nI ) / this.hOptions.nSteps ) + nEndG * ( nI / this.hOptions.nSteps ) << 8 | nStartB * ( ( this.hOptions.nSteps - nI ) / this.hOptions.nSteps ) + nEndB * ( nI / this.hOptions.nSteps );
		this.aColors[ nI ] = nColor;
	}
	this.aColors[ nI ] = this.nEndColor;
}

cMoEffects.cColor.prototype.playAgain = function( nStartColor, nEndColor, bBGColor )
{
	this.bBGColor = bBGColor;
	this.nStartColor = nStartColor;
	this.nEndColor = nEndColor;
	this.calculate();
	this.start();
}

cMoEffects.cColor.prototype.doFrame = function()
{
	if( !this.bBGColor )
	{
		cMoEffects.cColor.setColor( this.sId, this.aColors[ this.nCurrentStep ] );
	}
	else
	{
		cMoEffects.cColor.setBGColor( this.sId, this.aColors[ this.nCurrentStep ] );
	}
}

cMoEffects.cColor.setColor = function( sId, nValue )
{
	var hElement = document.getElementById( sId );
	if( hElement )
	{
		hElement.style.color = cMoEffects.cColor.numberToColor( nValue );
	}
}

cMoEffects.cColor.setBGColor = function( sId, nValue )
{
	var hElement = document.getElementById( sId );
	if( hElement )
	{
		hElement.style.backgroundColor = cMoEffects.cColor.numberToColor( nValue );
	}
}



cMoEffects.cColor.colorToNumber = function( sColor )
{
	var sRCol = /^#/;
	return parseInt( '0x' + sColor.replace( sRCol, '' ) );
}

cMoEffects.cColor.numberToColor = function( nColor )
{
	nColor |= 1<<24;
	return '#' + nColor.toString( 16 ).substr( 1 );
}


/* Color effect */


/* Resizer effect */
cMoEffects.cResizer = function( hElement, nStartWidth, nStartHeight, nEndWidth, nEndHeight, nType, hOptions )
{
	cMoEffects.cEffect.call( this, hOptions );

	if( typeof hElement == 'string' )
	{
		hElement = document.getElementById( hElement );
	}

	hElement.style.overflow = 'hidden';
	this.sId = hElement.id;
	this.aSizes = new Array();

	this.playAgain( nStartWidth, nStartHeight, nEndWidth, nEndHeight, nType );
}

cMoEffects.cResizer.CN_RESIZE_GLIDE = 0x01;
cMoEffects.cResizer.CN_RESIZE_SLIDE = 0x02;
cMoEffects.cResizer.CN_RESIZE_GLIDEFAST = 0x03;

cMoEffects.cResizer.prototype = new cMoEffects.cEffect();
cMoEffects.cResizer.prototype.constructor = cMoEffects.cResizer;


cMoEffects.cResizer.prototype.calculate = function()
{
	//clean the sizes
	var hKey;
	while( hKey in this.aSizes )
	{
		delete( this.aSizes[ hKey ] );
	}
	
	var nI;
	var dX = this.nEndWidth - this.nStartWidth;
	var dY = this.nEndHeight - this.nStartHeight;
	
	if( this.nType == cMoEffects.cResizer.CN_RESIZE_GLIDE )
	{
		var nAngleInc = 90 / ( this.hOptions.nSteps + 1 );
		var nAngle = nAngleInc;
		var nC;
		nI = 0;

		var sX = this.nStartWidth;
		var sY = this.nStartHeight;

		while( nAngle < 90 )
		{
			nC = Math.sin( nAngle * Math.PI / 180 );
			this.aSizes[ nI ] = { w:Math.floor( sX + dX * nC ), h:Math.floor( sY + dY * nC ) };
			nAngle += nAngleInc;
			nI++;
		}
	}
	if( this.nType == cMoEffects.cResizer.CN_RESIZE_GLIDEFAST )
	{
		var nAngleInc = 90 / ( this.hOptions.nSteps );
		var nAngle = 90 - nAngleInc;
		var nC;
		nI = 0;

		var sX = this.nStartWidth;
		var sY = this.nStartHeight;

		while( nAngle >= 0 )
		{
			nC = Math.sin( nAngle * Math.PI / 180 );
			this.aSizes[ nI ] = { w:Math.floor( sX + dX * ( 1 - nC ) ), h:Math.floor( sY + dY * ( 1 - nC ) ) };
			
			nAngle -= nAngleInc;
			nI++;
		}
	}	else if( this.nType == cMoEffects.cResizer.CN_RESIZE_SLIDE )
	{
		var nDeltaX = dX / this.hOptions.nSteps;
		var nDeltaY = dY / this.hOptions.nSteps;

		var sX = this.nStartWidth;
		var sY = this.nStartHeight;
		for( nI = 0; nI < this.hOptions.nSteps - 1; nI ++ )
		{
			sX += nDeltaX;
			sY += nDeltaY;
			this.aSizes[nI] = { w:Math.round( sX ), h:Math.round( sY ) };
		}
	}
	
	this.aSizes[ nI ] = { w:this.nEndWidth, h:this.nEndHeight };
}

cMoEffects.cResizer.prototype.playAgain = function( nStartWidth, nStartHeight, nEndWidth, nEndHeight, nType )
{
	this.nStartWidth = nStartWidth != null ? nStartWidth : cDomObject.getWidth( this.sId );
	this.nStartHeight = nStartHeight != null ? nStartHeight :  cDomObject.getHeight( this.sId );
	this.nEndWidth = nEndWidth != null ? nEndWidth : cDomObject.getWidth( this.sId );
	this.nEndHeight = nEndHeight != null ? nEndHeight :  cDomObject.getHeight( this.sId );

	
	if( nType )
	{
		this.nType = nType;
	}
	this.calculate();
	this.start();
}

cMoEffects.cResizer.prototype.doFrame = function()
{
	cMoEffects.cResizer.setSize( this.sId, this.aSizes[ this.nCurrentStep ] );
}

cMoEffects.cResizer.setSize = function( sId, hSize )
{
	var hElement = document.getElementById( sId );
	try
	{
		hElement.style.width = hSize.w + 'px';
		hElement.style.height = hSize.h + 'px';
	}
	catch( hE )
	{
	}
}
/* Resizer effect */

/* Move effect */
cMoEffects.cMover = function( hElement, nStartX, nStartY, nEndX, nEndY, nType, bRelative, hOptions )
{
	cMoEffects.cEffect.call( this, hOptions );

	if( typeof hElement == 'string' )
	{
		hElement = document.getElementById( hElement );
	}

	//hElement.style.overflow = 'hidden'
	this.sId = hElement.id;
	this.aPositions = new Array();

	this.playAgain( nStartX, nStartY, nEndX, nEndY, nType, bRelative );
}

cMoEffects.cMover.CN_MOVE_GLIDE = 0x01;
cMoEffects.cMover.CN_MOVE_SLIDE = 0x02;
cMoEffects.cMover.CN_MOVE_GLIDEFAST = 0x03;

cMoEffects.cMover.prototype = new cMoEffects.cEffect();
cMoEffects.cMover.prototype.constructor = cMoEffects.cMover;

cMoEffects.cMover.prototype.calculate = function()
{
	//clean the sizes
	var hKey;
	while( hKey in this.aPositions )
	{
		delete( this.aPositions[ hKey ] );
	}
	
	var nI;
	var dX = this.nEndX - this.nStartX;
	var dY = this.nEndY - this.nStartY;
	
	if( this.nType == cMoEffects.cMover.CN_MOVE_GLIDE )
	{
		var nAngleInc = 90 / ( this.hOptions.nSteps );
		var nAngle = nAngleInc;
		var nC;
		nI = 0;

		var sX = this.nStartX;
		var sY = this.nStartY;

		while( nAngle < 90 )
		{
			nC = Math.sin( nAngle * Math.PI / 180 );
			this.aPositions[ nI ] = { left:Math.floor( sX + dX * nC ), top:Math.floor( sY + dY * nC ) };
			nAngle += nAngleInc;
			nI++;
		}
	}
	else if( this.nType == cMoEffects.cMover.CN_MOVE_GLIDEFAST )
	{
		var nAngleInc = 90 / ( this.hOptions.nSteps );
		var nAngle = 90 - nAngleInc;
		var nC;
		nI = 0;

		var sX = this.nStartX;
		var sY = this.nStartY;

		while( nAngle >= 0 )
		{
			nC = Math.sin( nAngle * Math.PI / 180 );
			this.aPositions[ nI ] = { left:Math.floor( sX + dX * ( 1 - nC ) ), top:Math.floor( sY + dY * ( 1 - nC ) ) };
			
			nAngle -= nAngleInc;
			nI++;
		}
	}	
	else if( this.nType == cMoEffects.cMover.CN_MOVE_SLIDE )
	{
		var nDeltaX = dX / this.hOptions.nSteps;
		var nDeltaY = dY / this.hOptions.nSteps;
		
		var sX = this.nStartX;
		var sY = this.nStartY;
		for( nI = 0; nI < this.hOptions.nSteps - 1; nI ++ )
		{
			sX += ( dX == 0 ) ? 0 : nDeltaX;
			sY += ( dY == 0 ) ? 0 : nDeltaY;
			this.aPositions[nI] = { left:Math.round( sX ), top:Math.round( sY ) };
		}
	}
	
	this.aPositions[ nI ] = { left:this.nEndX, top:this.nEndY };
}

cMoEffects.cMover.prototype.playAgain = function( nStartX, nStartY, nEndX, nEndY, nType, bRelative )
{
	if( bRelative == null )
	{
		bRelative = false;
	}
	
	var sPosition = MO.Dom.getStyle( this.sId, 'position' );
	var aXY = MO.Dom.getXY( this.sId );
	this.nStartX = aXY[ 0 ];
	this.nStartY = aXY[ 1 ];
	if( bRelative )
	{
		this.nEndX = nEndX != null ? this.nStartX + nEndX : this.nStartX;
		this.nEndY = nEndY != null ? this.nStartY + nEndY : this.nStartY;
	}
	else
	{
		this.nEndX = nEndX != null ? nEndX : this.nStartX;
		this.nEndY = nEndY != null ? nEndY : this.nStartY;
	}
	
	if( nType )
	{
		this.nType = nType;
	}
	this.calculate();
	this.start();
}

cMoEffects.cMover.prototype.doFrame = function()
{
	if( this.aPositions.length > this.nCurrentStep )
	{
		cMoEffects.cMover.setPosition( this.sId, this.aPositions[ this.nCurrentStep ] );
	}
}

cMoEffects.cMover.setPosition = function( sId, hPosition )
{
	var hElement = document.getElementById( sId );
	if( hElement )
	{
		MO.Dom.setXY( hElement, [ hPosition.left,  hPosition.top ] );
	}
}
/* Move effect */