/*******************************************************************
*
* File    : animate.js
*
*
* Created : 1999/08/10
*
* Author  : Roy Whittle  (Roy@Whittle.com)
*
* Purpose : To create animated 'onMouseOver' buttons
*
* History
*
* Date         Version        Description
* 1999-08-10     1.0          First Version It works! amazing.
* 1999-08-11     1.1          Allowed for different extension.
*                             Animated jpegs!
* 1999-08-17     1.2          Added function AnimatedImage2 to
*                             animate transparent "opening" gifs
* 1999-09-12     1.3          Replaced all switch statements with "if"
*                             as switch is only javascript 1.2
* 1999-09-16     1.4          Major re-write to make this a set
*                             of library routines. The user
*                             needs to know only about the interface
*                             functions that create and 
*                             animate the images.
* 1999-10-08     1.5          Bugfix in turn_off_using. Off Animation
*                             need not have same number of frames
*                             as On Animation
*
* Program Notes:
* The functions make use of associative arrays where possible.
* The main Btn array had to be a non-associative array so the
* Animate function could loop through all the animations. For this
* reason the Index array was created to quickly convert from
* an image name to an image index.
*******************************************************************/

/*** Create some global variables ***/
var AnimationRunning = false; /*** Global state of animation ***/
var FrameInterval     = 30;   /*** Time between frames in milliseconds   ***/

var NumButtons=0;
var Btn  = new Array();
var Anim = new Array();
var Index= new Array();

/***********************************************************
* Function   : CreateAnimationFrames
*
* Parameters : name - the name of the animation.
*              n    - number of frames in animation
*              ext  - the type of image (".GIF", ".JPG")
*              
* Description : Creates an object that can hold the current
*               images for the animation.
*               There must be 1 ".ext" file for every frame
*               of animation  and they must reside in a 
*               the directory "images/name/x.ext". 
*               E.g.
*                 "images/email/0.gif"
*                 "images/email/1.gif"
*                 ....
*                 "images/email/x.gif" //where x=(n-1);
***********************************************************/
function CreateAnimationFrames(name, n, ext)
{
	this.num_frames = n;
	for(var i=0 ; i<n ; i++)
	{
		this[i]=new Image();
		this[i].src = "images/" + name + "/" + i + ext;
	}
}
/***********************************************************
* Function   : CreateAnimatedImage
*
* Parameters : name     - the name of the image.
*              ani_name - the name of the animation effect
*                     to use with this image
*              
* Description : Creates an object that can hold the current
*               state of the animation for a particular image
***********************************************************/
function CreateAnimatedImage(name, open_name, close_name)
{
	if(document.images)
	{
		this.name       = name;
		this.ani_open   = open_name;
		this.ani_close  = close_name;
		this.index      = 0;
		this.state      = "CLOSED";
	}
	
}
/*******************************************************************
*
* Function    : Animate
*
* Description : Each animation object has a state.
*               The states normally go as follows
*                   CLOSED->OPENING->OPEN
*                   OPEN->CLOSING->CLOSED.
*               When the onMouseOver event is received, a button in the
*               CLOSED state is switched to the OPENING state until OPEN
*               is reached. When the onMouseOut event is received a button
*               in the OPEN state is switched to the CLOSING state until
*               the CLOSED state is reached. 
*
*               The special cases are what happens when we get onMouseOut when
*               in the middle of opening. In this case the path is :-
*               CLOSED->OPENING->OPEN_CLOSE->CLOSING->CLOSED.
*               in this way the button will fully "open" before it starts 
*               closing. This can be changed by always setting the state
*               to "CLOSING" when the onMouseOut event is received.
*
*               If the button is "CLOSING" and the onMouseOver event is
*               received and the open/close animations are the same
*               then the state is set back to "OPENING and the
*               button will start opening again immediately.
*                 Otherwise the state is set to CLOSE_OPEN so the image
*               will get to the CLOSED state and start opening with the
*               different animation.
*
*******************************************************************/
function Animate()
{	
	AnimationRunning = false; /*** Are there more frames that need displaying? ***/

	for(var i=0 ; i<NumButtons ; i++)
	{
		/*** Create some shortcut variables ***/
		var button=Btn[i];
		var ani_open  = Anim[button.ani_open];
		var ani_close = Anim[button.ani_close];

		if(button.state == "OPENING")
		{
			/*** Increment the frame index - display the next frame ***/
			/*** when fully open, set state to "OPEN"               ***/
			if(button.index < ani_open.num_frames-1)
			{
				button.index++;
				document.images[button.name].src=ani_open[button.index].src;
				AnimationRunning = true;
			}
			else
			{
				button.state = "OPEN";
				button.index = ani_close.num_frames;
			}
		}
		else if(button.state == "OPEN_CLOSE")
		{
			/*** Increment the frame index - display the next frame ***/
			/*** when fully open, set state to "CLOSING"            ***/
			if(button.index < ani_open.num_frames-1)
			{
				button.index++;
				document.images[button.name].src=ani_open[button.index].src;
			}
			else
			{
				button.state = "CLOSING";
				button.index = ani_close.num_frames;
			}

			AnimationRunning = true;
		}
		else if(button.state == "CLOSING")
		{
			/*** Decrement the frame index - display the next frame ***/
			/*** when fully closed, set state to "CLOSED"           ***/
			if(button.index > 0)
			{
				button.index--;
				document.images[button.name].src=ani_close[button.index].src;
				AnimationRunning = true;
			}
			else
				button.state = "CLOSED";
		}
		else if(button.state == "CLOSE_OPEN")
		{
			/*** Decrement the frame index - display the next frame ***/
			/*** when fully closed, set state to "OPENING"           ***/
			if(button.index > 0)
			{
				button.index--;
				document.images[button.name].src=ani_close[button.index].src;
			}
			else
				button.state = "OPENING";

			AnimationRunning = true;
		}
	}
	/*** Check to see if we need to animate any more frames. ***/
	if(AnimationRunning)
		setTimeout("Animate()",FrameInterval);
}
/*****************************************************************
* Function    : start_animation
*
* Description : Set a timeout which will call the animate routine
*               and start the animation running
*****************************************************************/
function start_animation()
{
	if(!AnimationRunning)
		Animate();
}
/*****************************************************************
*
* Function   : turn_on
*
* Parameters : button_name - string containing the name of the
*                            button to start animating.
*
* Description: Checks that the button is in a valid state to
*              start "OPENING". If it is it sets the state to
*              "OPENING" and calls start_animation.             
*
*****************************************************************/
function turn_on(btn_name)
{
	if(Btn)
	{
		var b=Btn[ Index[btn_name] ];

		if( ( b.state == "CLOSED" )
		 || ( b.state == "OPEN_CLOSE" ) )
		{
			b.state = "OPENING";
			start_animation();
		}
		else if ( b.state == "CLOSING" )
		{
			if(b.ani_open == b.ani_close)
				b.state = "OPENING";
			else
				b.state = "CLOSE_OPEN";

			start_animation();
		}
	}
}
/*****************************************************************
*
* Function   : turn_on_using
*
* Parameters : button_name - string containing the name of the
*                            button to start animating.
*              ani_name    - the name of the open animation
*
* Description: Animate the named image with the named animation
*
*****************************************************************/
function turn_on_using(btn_name, ani_name)
{
	if(Btn)
	{
		var b=Btn[ Index[btn_name] ];
		b.ani_open = ani_name;
		turn_on(btn_name);
	}
}
/*****************************************************************
*
* Function   : turn_on2
*
* Parameters : button_name - string containing the name of the
*                            buttons to start animating.
*
* Description: Simply starts 2 animations. One called name
*              and one called name2
*
*****************************************************************/
function turn_on2(name)
{
	turn_on(name);
	turn_on(name + "2");
}
/*****************************************************************
*
* Function   : turn_off
*
* Parameters : button_name - string containing the name of the
*                            button to start animating.
*
* Description: Checks that the button is in a valid state to
*              start "CLOSING". If it is it sets the state to
*              "CLOSING" and calls start_animation.             
*
*****************************************************************/
function turn_off(btn_name)
{
	if(Btn)
	{
		var b=Btn[ Index[btn_name] ];

		if( b.state == "OPEN" || b.state == "CLOSE_OPEN")
		{
			b.state = "CLOSING";
			start_animation();
		}
		else if( b.state == "OPENING" )
		{
			b.state = "OPEN_CLOSE";
			start_animation();
		}
	}
}
/*****************************************************************
*
* Function   : turn_off_using
*
* Parameters : button_name - string containing the name of the
*                            button to start animating.
*              ani_name    - the name of the close animation
*
* Description: Animate the named image with the named animation
*
*****************************************************************/
function turn_off_using(btn_name, ani_name)
{
	if(Btn)
	{
		var b=Btn[ Index[btn_name] ];
		b.ani_close = ani_name;
		if(b.state == "OPEN")
			b.index = Anim[ani_name].num_frames;
		turn_off(btn_name);
	}
}
/*****************************************************************
*
* Function   : turn_off2
*
* Parameters : button_name - string containing the name of the
*                            buttons to start animating to the
*                            "CLOSED" state.
*
* Description: Simply starts 2 animations. One called name
*              and one called name2
*
*****************************************************************/
function turn_off2(name)
{
	turn_off(name);
	turn_off(name + "2");
}
/***********************************************************
* Function   : AnimatedImage
*
* Parameters : name - the name of the image.
*              aniname - the name of the animation effect
*                     to use with this image
*              n    - number of frames in animation
*              ext  - the type of image (".GIF", ".JPG")
*              
* Description : Creates Objects to hold the state of the
*               animation and gets all the images for the
*               animation.
***********************************************************/
function AnimatedImage(name, open_name, close_name)
{
	Btn[ NumButtons ] = new CreateAnimatedImage( name, open_name, close_name);
	Index[name]       = NumButtons++;
}
/***********************************************************
* Function   : AnimationFrames
*
* Parameters : ani_name - the name of the animation effect
*              n    - number of frames in animation
*              ext  - the type of image (".GIF", ".JPG")
*              
* Description : Creates an object to hold all the frames
*               for an animation and gets all the images.
***********************************************************/
function AnimationFrames(ani_name, n, ext)
{
	/*** Only download this animation if we don't already have it ***/
	if(Anim[ani_name] == null)
		Anim[ ani_name ]= new CreateAnimationFrames(ani_name, n, ext);
	else
//		alert(ani_name + " already defined");
		;
}
/***********************************************************
* Function   : AnimatedGif AnimatedJpg
*
* Parameters : name - the name of the image.
*              n    - number of frames in animation
*              
* Description : These are a couple of helper functions to
*               help create simple animations.
*
***********************************************************/
function AnimatedGif(name, n)
{
	AnimatedImage( name, name, name);
	AnimationFrames(name, n, ".gif");
}
function AnimatedJpg(name, n)
{
	AnimatedImage( name, name, name);
	AnimationFrames(name, n, ".jpg");
}
