
//====================================================================================
// Object Constructors
//====================================================================================

//Define Group Constructor for imgSwapGroup
//----------------------------------------------------------------------
function ImgSwapGroup(thePath, theType)
	{
		this.image_path						= thePath;				//The root path for the images, can be overridden at the swaps level
		this.swapsok              = false;          // Are we ready to do swaps (eg, preloads done & browser check passed)
		this.preloaded            = false;					// Are the preloads loaded (or at least called to load)
		
		this.suffix_over					= 'on';						// suffix defaults
		this.suffix_out           = 'off';
		this.suffix_on						= 'on';
		this.suffix_disable       = 'dis';
		
		if (!theType)
			{this.image_type				=	'.gif';}
		else
			{this.image_type        = theType;}				// The default image type for swaps created with BuildImages() prototype
		
		this.parameter_delimiter	= ',';						// The item delimiter for parameters such as 'a,b,c' - used with split command	
		this.swap_delimiter				= '+';						// The delimiter for the swap collection index
		
		this.suffix_delimiter			= '_';						// The suffix that will go between the image name & states
																								// NOTE: This is only used in the utility functions
																								
		this.images								= new Array();		// Image objects that can change
		this.resets               = new Array();		// Saved states of changed images
																								// NOTE: "resets" items don't have to be in "images"
		
		this.preloads             = new Array();    // Preloaded images array
		
		this.show_errors					= false;
	}

//Define Group Constructor for ImgSwapGroupImage
//----------------------------------------------------------------------
function ImgSwapGroup_Image()
	{
		this.collections = new Array();
	}

//Define Group Constructor for ImgSwapGroupSwap
//----------------------------------------------------------------------
function ImgSwapGroup_Collection()
	{
		this.swaps = new Array();
	}


//====================================================================================
// Group Level Prototypes
//====================================================================================
new ImgSwapGroup();  //Created but not used for Nav 3 Prototype Issues

//---- Prototype for Adding images to a group
function f_AddImages(theImages)
	{

		//if (theImages.indexOf(this.suffix_delimiter) == -1)
		//	{
				theImages = CustomSplit(theImages,this.parameter_delimiter);

				for (var indexImage in theImages)
					{ this.images[trim(theImages[indexImage])] = new ImgSwapGroup_Image(); }
		//	}
	//	else
	//		{ 
		//		this.show_errors = true; //this error is too serious, got to show it.
		//		this.ShowMessage('ERROR: Suffix delimiter : "' + this.suffix_delimiter + '" is used in an image name.');
		//	}
	}
ImgSwapGroup.prototype.AddImages = f_AddImages;


//---- Utility to build one or several standard single image items (eg on/off collections only for each image)
function f_BuildImages(theImages, theCollections)
	{

		//Convert theImages and theStates strings to arrays
		theImages 			= CustomSplit(theImages, this.parameter_delimiter);
		theCollections	= CustomSplit(theCollections, this.parameter_delimiter);							
		
		for (var indexImage in theImages)
			{
				var thisImage = trim(theImages[indexImage]);
				this.AddImages(thisImage);
				for (var indexCollection in theCollections)
					{
						var thisCollection = trim(theCollections[indexCollection]);
						this.AddCollections(thisImage, thisCollection);
						this.AddSwaps(thisImage,
													thisCollection,
													thisImage + this.swap_delimiter + thisCollection,
													this.image_type,
													this.image_path);
					}
			}
	}
ImgSwapGroup.prototype.BuildImages = f_BuildImages;


//---- Prototype for Adding collections to all images in the group
function f_AddCollections()
	{

		if (f_AddCollections.arguments.length == 2)
			{
				myImages = CustomSplit(f_AddCollections.arguments[0],this.parameter_delimiter);
				theCollections = CustomSplit(f_AddCollections.arguments[1],this.parameter_delimiter);
			}
		else
			{
				myImages = this.images;
				theCollections = CustomSplit(f_AddCollections.arguments[0],this.parameter_delimiter);
			}

		for (thisImage in myImages)
			{
				for (var thisCollection in theCollections)
					{ 
						if (f_AddCollections.arguments.length == 2)
							{ this.images[myImages[thisImage]].collections[theCollections[thisCollection]] = new ImgSwapGroup_Collection();	}
						else
							{	thisImage.collections[theCollections[thisCollection]] = new ImgSwapGroup_Collection();	}
					}
			}
	}
ImgSwapGroup.prototype.AddCollections = f_AddCollections;


//---- Prototype for Adding swaps to an image collection in the group
function f_AddSwaps(theImage, theCollection, theSwaps, theImageType, theImagePath)  //optional passing of type and path
	{
		var okToProcess;
		var errMsg;
		var errBase = 'ERROR - AddSwaps(' + theImage + ',' + theCollection + ',' + theSwaps + ',' + theImageType + ',' + theImagePath + '):  ';

		var theSplitSwaps = CustomSplit(theSwaps,this.parameter_delimiter);

		var theImageState = '';
		var theImageName	= '';
		var theSwapInfo;


		//Check to see if the image object exists, if not create it
		if (!this.images[theImage])
			{this.AddImages(theImage);}

		//Check to see if the collection object exists, if not create it
		if (!this.images[theImage].collections[theCollection])
			{this.AddCollections(theImage, theCollection);}
						
		//Did we also pass the type & path?
		if (f_AddSwaps.arguments.length == 5)
			{
				theImageType = f_AddSwaps.arguments[3];
				theImagePath = f_AddSwaps.arguments[4];				
			}
		else
			{
				theImageType = this.image_type;
				theImagePath = this.image_path;			
			}				
		
		for (thisSwap in theSplitSwaps)
			{
				theSwapInfo = StateSplit(theSplitSwaps[thisSwap],this.swap_delimiter);

				theImageName		= trim(theSwapInfo[0]);
				theImageState 	= trim(theSwapInfo[1]);
				theImageType		= trim(theImageType);
				theImagePath		= trim(theImagePath);
	
				this.images[theImage].collections[theCollection].swaps[theImageName] = new Array();

				this.images[theImage].collections[theCollection].swaps[theImageName].state		= theImageState;
				this.images[theImage].collections[theCollection].swaps[theImageName].srcbase	= theImageName;
				this.images[theImage].collections[theCollection].swaps[theImageName].type			= theImageType;
				this.images[theImage].collections[theCollection].swaps[theImageName].path			= theImagePath;
																																				
			}			
	}
ImgSwapGroup.prototype.AddSwaps = f_AddSwaps;
		
		
//---- Prototype for Setting the swaps' srcbase for all swaps in all images
function f_SetSrcBase()
	{
	
		//1 Arg  = SrcBase, Change everything
		//2 Args = TheImages + SrcBase, change for each image given
		//3 Args = theImages + theCollections + SrcBase, change for each collection of each image (rarely used)
		//4 Args = theImages + theCollections + theSwaps + SrcBase, you get the drill...
		
		//Normally, if you give 3 or 4, you will use a single item except for the last item (not counting srcBase)
		//so if you gave 4 parameters, you would probably give a single image, a single collection, and one or more swaps
		var srcBaseArg = f_SetSrcBase.arguments.length - 1;

		if (f_SetSrcBase.arguments.length >= 2)
			{ var theImages = new CustomSplit(f_SetSrcBase.arguments[0],this.parameter_delimiter); }
		else
			{ var theImages = new convertToArray(this.images) }

		for (var thisImage in theImages)
			{
				var idxImage = theImages[thisImage];

				if (f_SetSrcBase.arguments.length >= 3)
					{ var theCollections = new CustomSplit(f_SetSrcBase.arguments[1],this.parameter_delimiter); }
				else
					{ var theCollections = new convertToArray(this.images[idxImage].collections) }

				for (var thisCollection in theCollections)
					{ 
						var idxCollection = theCollections[thisCollection];

						if (f_SetSrcBase.arguments.length >= 4)
							{ var theSwaps = new CustomSplit(f_SetSrcBase.arguments[2],this.parameter_delimiter); }
						else
							{ var theSwaps = new convertToArray(this.images[idxImage].collections[idxCollection].swaps) }

						for (var thisSwap in theSwaps)
							{ 
								var idxSwap = theSwaps[thisSwap];
								this.images[idxImage].collections[idxCollection].swaps[idxSwap].srcbase = f_SetSrcBase.arguments[srcBaseArg];
							}
					}
			}
	}
ImgSwapGroup.prototype.SetSrcBase = f_SetSrcBase;
	
//---- Prototype for Setting the swaps' type for all swaps in all images
function f_SetType()
	{
	
		//1 Arg  = theType, Change everything
		//2 Args = TheImages + theType, change for each image given
		//3 Args = theImages + theCollections + theType, change for each collection of each image (rarely used)
		//4 Args = theImages + theCollections + theSwaps + theType, you get the drill...
		
		//Normally, if you give 3 or 4, you will use a single item except for the last item (not counting srcBase)
		//so if you gave 4 parameters, you would probably give a single image, a single collection, and one or more swaps
		var theTypeArg = f_SetType.arguments.length - 1;

		if (f_SetType.arguments.length >= 2)
			{ var theImages = new CustomSplit(f_SetType.arguments[0],this.parameter_delimiter); }
		else
			{ var theImages = new convertToArray(this.images) }
						
		for (var thisImage in theImages)
			{
				var idxImage = theImages[thisImage];

				if (f_SetType.arguments.length >= 3)
					{ var theCollections = new CustomSplit(f_SetType.arguments[1],this.parameter_delimiter); }
				else
					{ var theCollections = new convertToArray(this.images[idxImage].collections) }
					
				for (var thisCollection in theCollections)
					{ 
						var idxCollection = theCollections[thisCollection];

						if (f_SetType.arguments.length >= 4)
							{ var theSwaps = new CustomSplit(f_SetType.arguments[2],this.parameter_delimiter); }
						else
							{ var theSwaps = new convertToArray(this.images[idxImage].collections[idxCollection].swaps) }
							
						for (var thisSwap in theSwaps)
							{ 
								var idxSwap = theSwaps[thisSwap];
								this.images[idxImage].collections[idxCollection].swaps[idxSwap].type = f_SetType.arguments[theTypeArg];
							}
					}
			}
	}
ImgSwapGroup.prototype.SetType = f_SetType;


//---- Prototype for Setting the swaps' path for all swaps in all images
function f_SetPath()
	{
	
		//1 Arg  = thePath, Change everything
		//2 Args = TheImages + thePath, change for each image given
		//3 Args = theImages + theCollections + thePath, change for each collection of each image (rarely used)
		//4 Args = theImages + theCollections + theSwaps + thePath, you get the drill...
		
		//Normally, if you give 3 or 4, you will use a single item except for the last item (not counting srcBase)
		//so if you gave 4 parameters, you would probably give a single image, a single collection, and one or more swaps
		var thePathArg = f_SetPath.arguments.length - 1;

		if (f_SetPath.arguments.length >= 2)
			{ var theImages = new CustomSplit(f_SetPath.arguments[0],this.parameter_delimiter); }
		else
			{ var theImages = new convertToArray(this.images) }
						
		for (var thisImage in theImages)
			{
				var idxImage = theImages[thisImage];

				if (f_SetPath.arguments.length >= 3)
					{ var theCollections = new CustomSplit(f_SetPath.arguments[1],this.parameter_delimiter); }
				else
					{ var theCollections = new convertToArray(this.images[idxImage].collections) }
					
				for (var thisCollection in theCollections)
					{ 
						var idxCollection = theCollections[thisCollection];

						if (f_SetPath.arguments.length >= 4)
							{ var theSwaps = new CustomSplit(f_SetPath.arguments[2],this.parameter_delimiter); }
						else
							{ var theSwaps = new convertToArray(this.images[idxImage].collections[idxCollection].swaps) }

						for (var thisSwap in theSwaps)
							{ 
								var idxSwap = theSwaps[thisSwap];
								this.images[idxImage].collections[idxCollection].swaps[idxSwap].path = f_SetPath.arguments[thePathArg];
							}
					}
			}
	}
ImgSwapGroup.prototype.SetPath = f_SetPath;

	
//---- Prototype for Adding states to all images in the group
function f_Preload()
	{
		var mySRCpath   = '';
		var myImageName = '';
		var myImageSRC  = '';
		var mySwapObj;
		var updatePreloads = false;
		var autoProcess = true;
		
		if (document.images) //don't bother if the DOM doesn't support image swapping eg NN2 or IE3
			{
				if (f_Preload.arguments.length > 0)
					{ 
			  		//Are the arguments trying to force updates
						//arg[0] : true/false for force updates
						if (f_Preload.arguments.length == 1)
							{if (f_Preload.arguments[0] == true) {updatePreloads = true}}
				
						//Are the arguments trying to set a manual preload
						//arg[0] : preload image name
						//arg[1] : preload image src
						if (f_Preload.arguments.length == 2)
							{
								if (!this.preloads[f_Preload.arguments[0]])
									{	this.preloads[f_Preload.arguments[0]] = new Image();	}
								this.preloads[f_Preload.arguments[0]].src = f_Preload.arguments[1];
								autoProcess = false;
							}
					
					} //if f_Preload.arguments.length > 0
			
				if (autoProcess)
					{
						for (var thisImage in this.images)
							{
								for (var thisCollection in this.images[thisImage].collections)
									{
										mySwapObj = this.images[thisImage].collections[thisCollection].swaps;

										for (var thisSwap in mySwapObj)
											{
												myImageName = thisSwap + this.suffix_delimiter + mySwapObj[thisSwap].state;
												myImageSRC  = mySwapObj[thisSwap].path + 
																			mySwapObj[thisSwap].srcbase + 
																			this.suffix_delimiter +
																			mySwapObj[thisSwap].state + 
																			mySwapObj[thisSwap].type;
										
												//Add image to group preloads array if needed
												if (!this.preloads[myImageName] || updatePreloads)
													{
														this.preloads[myImageName] = new Image();
														this.preloads[myImageName].src = myImageSRC;
													}
											}  	//for thisSwap
									} 			//for thisCollection
							} 					//for thisImage

							//Now sort everything
							this.images.sort();
							this.preloads.sort();
																					
							this.preloaded 	= true;			//Preloads done
							this.swapsok 		= true;  		//We're done now, swapping is ready
					}  							//if autoprocess
			} 									//if document.images
	}
ImgSwapGroup.prototype.Preload = f_Preload;

		
				
//---- Prototype for processing an image swap set
function f_SwapCollection(whichImage, whichCollection)
	{

		var okToSwap = true;	//Assume all is well
		var errMsg;
		var errBase = 'ERROR - SwapCollection(' + whichImage + ',' + whichCollection + '):  ';
					
		//Now start checking
		if (!this.swapsok)	//Are the swaps ready
			{ okToSwap = false; errMsg		= errBase + 'Swaps are not ready, probably not preloaded'; }
					
		if (okToSwap)
			{
				if (!document.images[whichImage])	//Does whichImage exist as an image on the page
					{ okToSwap = false; errMsg		= errBase + 'Image "' + whichImage + '" does not exist on the page (eg <IMG> not named).'; }
			}

		if (okToSwap)
			{
				if (!this.images[whichImage])	//Does whichImage exist in the group
					{ okToSwap = false; errMsg		= errBase + 'Image "' + whichImage + '" does not exist in the group.'; }
			}

		if (okToSwap)
			{
				if (!this.images[whichImage].collections[whichCollection])	//Does whichState exist in the image
					{ okToSwap = false; errMsg		= errBase + 'Collection "' + whichState + '" does not exist for image "' + whichImage + '"'; }					
			}

		if (okToSwap)
			{
				this.resets = new Array();  //Reset the array
				
				var mySwapObj     = this.images[whichImage].collections[whichCollection].swaps;
				var thisSwapImage = '';
			
				for (var thisSwap in mySwapObj)
					{ 
						//Get the preloaded swap image
						thisSwapImage = thisSwap + this.suffix_delimiter + mySwapObj[thisSwap].state;
						//Save the current image
						this.resets[thisSwap] = document.images[thisSwap].src;
						//Change to the preloaded swap image				
						document.images[thisSwap].src = this.preloads[thisSwapImage].src;
					}
			}
		else
			{ this.ShowMessage(errMsg); }
	}
ImgSwapGroup.prototype.SwapCollection = f_SwapCollection;


//---- Prototype for processing an image swap set
function f_Reset()
	{
		for (var thisImage in this.resets)
			{ 
				document.images[thisImage].src = this.resets[thisImage];
			}
	}
ImgSwapGroup.prototype.Reset = f_Reset;


//---- Prototype for Rollovers - a wrapper for calling SwapCollection(image, 'on')
function f_Rollover(whichImage)
	{
						this.SwapCollection(whichImage, this.suffix_over);
	}
ImgSwapGroup.prototype.Rollover = f_Rollover;


//---- Prototype for Rollovers - a wrapper for calling SwapCollection(image, 'on')
function f_Rollout(whichImage)
	{
		this.SwapCollection(whichImage, this.suffix_out);
	}	
ImgSwapGroup.prototype.Rollout = f_Rollout;


//---- Prototype for processing an image swap set
function f_ShowMessage(theMessage)
	{
		if (this.show_errors)
			{alert(theMessage);}
	}
ImgSwapGroup.prototype.ShowMessage = f_ShowMessage;

//====================================================================================
// Utility Functions
//====================================================================================

//---- Utility to build image groups
function BuildGroup(doPreload, theBasePath, theType, theImages, theCollections)
	{
		var theGroup = new ImgSwapGroup(theBasePath, theType);
		
		if (BuildGroup.arguments.length == 4)
			{ theCollections = 'on,off' } //We didn't pass in theStates then use these default values

		theGroup.BuildImages(theImages, theCollections);
				
		if (doPreload) {theGroup.Preload()};  //Preload the images if it is ok to do so
		return theGroup;
	}

//---- Utility to trim spaces from front/back of chars
function trim (str)
{
  while (str.charAt(0) == ' ')
    str = str.substring(1);
  while (str.charAt(str.length - 1) == ' ')
    str = str.substring(0, str.length - 1);
  return str;
}

function makeArray(intArraySize)
{

  for (var n = 0; n < intArraySize; n++)
    this[n] = "";

  return this;
}


function CustomSplit(str, separator)
{

	var theArray = new makeArray(1);
	var index = 0;

	if (document.images)
	  { theArray = str.split(separator); }
	else
		{
			if (separator.length)
				{
					while (str.indexOf(separator) != -1)
						{
							thisStr  = str.substring(0, str.indexOf(separator));
							str = str.substring(str.indexOf(separator)+1, str.length);
							theArray[index] = thisStr;
							index++;
						}
					theArray[index] = str;
				}
		}
		
  return theArray;
}

function StateSplit(str, separator)
{

	var theArray = new makeArray(1);

	theArray[0] = str.substring(0, str.lastIndexOf(separator));
	theArray[1] = str.substring(str.lastIndexOf(separator)+1, str.length);
	
  return theArray;
}

function convertToArray(theObject)
{
	var theArray = new makeArray(1);
	var index = 0;
	
	for (thisObject in theObject)
		{
			theArray[index] = thisObject;
			index++;
		}
		
	return theArray;
}


function SetupBrowserInfo()
	{
		// Based on -- Ultimate client-side JavaScript client sniff. Version 3.01
		// (C) Netscape Communications 1999-2001.  Permission granted to reuse and distribute.

		// NOTE:  The variables are global, so if this is called, the info is available to other scripts
		// We also check that we haven't called it already by checking one of the variables
		
		if (!agt)
			{
		    // convert all characters to lowercase to simplify testing
		    agt=navigator.userAgent.toLowerCase();

    		// *** BROWSER VERSION ***
		    // Note: On IE5, these return 4, so use is_ie5up to detect IE5.
		    is_major = parseInt(navigator.appVersion);
		    is_minor = parseFloat(navigator.appVersion);

		    // Note: Opera and WebTV spoof Navigator.  We do strict client detection.
		    // If you want to allow spoofing, take out the tests for opera and webtv.
		    is_nav  		= ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
				              && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
        			        && (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1));
		    is_nav2 		= (is_nav && (is_major == 2));
		    is_nav3 		= (is_nav && (is_major == 3));
		    is_nav3up 	= (is_nav && (is_major >= 3));
		    is_nav4 		= (is_nav && (is_major == 4));
		    is_nav4up 	= (is_nav && (is_major >= 4));
		    is_navonly	= (is_nav && ((agt.indexOf(";nav") != -1) ||
                          (agt.indexOf("; nav") != -1)) );
		    is_nav6 		= (is_nav && (is_major == 5));
		    is_nav6up 	= (is_nav && (is_major >= 5));

		    is_ie     = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
		    is_ie3    = (is_ie && (is_major < 4));
    		is_ie4    = (is_ie && (is_major == 4) && (agt.indexOf("msie 5")==-1) );
		    is_ie4up  = (is_ie && (is_major >= 4));
		    is_ie5    = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.0")!=-1) );
		    is_ie5_5  = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.5") !=-1));
		    is_ie5up  = (is_ie && !is_ie3 && !is_ie4);
		    is_ie5_5up =(is_ie && !is_ie3 && !is_ie4 && !is_ie5);

		    // KNOWN BUG: On AOL4, returns false if IE3 is embedded browser
		    // or if this is the first browser window opened.  Thus the
		    // variables is_aol, is_aol3, and is_aol4 aren't 100% reliable.
		    is_aol   = (agt.indexOf("aol") != -1);
		    is_aol3  = (is_aol && is_ie3);
		    is_aol4  = (is_aol && is_ie4);
		    is_aol5  = (agt.indexOf("aol 5") != -1);
		    is_aol6  = (agt.indexOf("aol 6") != -1);

	  	  is_opera 		= (agt.indexOf("opera") != -1);
	  	  is_opera4 	= (agt.indexOf("opera 4") != -1);
		    is_opera5 	= (is_opera5 && (is_major == 5));
		    is_opera5up = (is_opera5 && (is_major >=5));

		    is_webtv = (agt.indexOf("webtv") != -1);

		    is_TVNavigator	= ((agt.indexOf("navio") != -1) || (agt.indexOf("navio_aoltv") != -1));
		    is_AOLTV 				= is_TVNavigator;	
			}
	}

