/*
Author:        Andrew Paul Simmons
Last Modified: 9.25.2006
Contact:       andrew-simmons@andrew-simmons.com

General Description:

	This file contains two classes ImageLoader and XMLImageLoader. 
	This class was designed to make it possible to ensure that
	specific images were loaded before displaying content.  Also,
	these classes make it easy to display preloading graphics that
	may hidden once the main content is loaded.  These classes
	take a series of images and call back function(s) to be invoked
	when the series of images have been loaded.
	
	<Design Note>
	1.
	Neither class has any public member except for the constructor;
	however, both need to maintain their state while they are active.
	Further, it may be desirable to have more than one instance working
	at a time.  For this reason I used classes rather than simple functions.
	2.
	Inspite of the similarities between these classes I decided to
	go with composition rather than inharetance.  XMLImageLoader
	contains 1 to n ImageLoader objects.
	ImageLoader's constructor accepts an array of images to load
	and a callback function to invoke when all of the images have loaded.
*/

/*	
ImageLoader Description:

	The ImageLoader constructor requries requires an array of images to load
	and a callback function to invoke when all the images have been loaded.

	usage| 
		  |images = [img1.jpg,img2.jpg,img2.jpg];
		  |onLoadImagesCallBack = function()
		  |{
		  |	//[code to show fully loaded content]
		  |}
		  |new ImageLoader(images, onLoadImagesCallBack);
		  |
	
	
*/

ImageLoader = function(images_url, onLoad_func)
{
	this.images_url = images_url;
	this.onLoad_func = onLoad_func;
	
	//Note: shift,unshift, pop,push are added
	//to the  Array.prototype when in IE5 (in utils.js).
	this._loadImage(this.images_url.shift());

}

ImageLoader.prototype._loadImage = function(url)
{
		//*we don't want to load the image if it is already chached
		// we simply want to go to the next image.
		var testImg = new Image();
		testImg.src = url;
		if(testImg.complete)
		{
			this._onImageLoad();
			return;
		}
		
		var img = new Image();
		img.onload = Utils.createDelegate(this, this._onImageLoad);
		img.onerror = Utils.createDelegate(this, this._onImageLoad);
		img.onabort = Utils.createDelegate(this, this._onImageLoad);
		img.src = url;

}

// This is the call back for img.onload above^
ImageLoader.prototype._onImageLoad = function()
{
	//if there are more images load the next image
	if(this.images_url.length > 0) 
	{
		
		//setTimeout here ensures that the browser will not 
		// get ahead of itself.
		scope = this;
		setTimeout(function(){scope._loadImage(scope.images_url.shift())},0);
	}
	else // no images left invoke the call back and be done.
	{
		this.onLoad_func();
	}
}


/* 
XMLImageLoader description:
	The XMLImageLoader class loads images in the order specified by an
	xml document. The images are placed into groups (specified by a group tag)
	and a call back is invoked when each group finishes loading.  
	
	For example, the first group of images may be the images required to 
	load a preloader. The second group may be the document body.  And the final 
	group may be rollover images. (This class has no public methods.)
	
	When a group of images is done loading XMLImageLoader invokes the 
	onload callback for the group. 
	
	The constructor requires two parameters XML_rul and groups_aary.
	XML_url is the url of an XML document of the form:
		<rootTag>
			<groupOne>
				<image url = imageurl />
				<image url = imageurl />
			</groupOne>
			<groupTwo>
				<image url = imageurl />
				<image url = imageurl />
				<image url = imageurl />
				<image url = imageurl />
			</groupTwo>
			...[as many image groups as you like]
		</rootTag>
	
	groups_aary is an associative array of the from:
	{groupTagNameOne:callBackOne, groupTagNameTwo:callBackTwo, etc... }
	
	<Design Note>
	In order to iterate through all of the groups 
	_loadGroup method parses the xml group into an array
	and passes that array to a new instance of ImageLoader.  It passes
	the XMLImageLoader._loadNext method as the callback. 
	When the group is done being loaded by ImageLoader the XMLImageLoader._loadNext 
	is invoked.  XMLImageLoader._loadNext invokes the call back specified for the group
	and calls _loadGroup again passing it the next group to be loaded.

*/
XMLImageLoader = function(XML_url, groups_aary)
{
	
	this.groups_aary = groups_aary;
	// a list of all groups
	this.groups_ary = [];	
	// construct list of groups
	for(i in groups_aary) 
	{
		this.groups_ary.push(i);
	}
	this.images_xml = XML.syncLoad(XML_url);
	
	//start iterating through each group
	this.done = false;
	this._loadGroup(this.groups_ary[0]);

}

XMLImageLoader.prototype._loadGroup = function(group)
{
	//group tags are unique so we only take the element 0.
	group_nods = this.images_xml.getElementsByTagName(group)[0].childNodes;	
	var images_url = [];
	for(var i = 0; i < group_nods.length; i++)
	{
		var n = group_nods[i];
		if(n.tagName == "image")
		{
			images_url.push( n.getAttribute('url'));
		}
	}

		 new ImageLoader(images_url, Utils.createDelegate(this, this._loadNext));											
}

XMLImageLoader.prototype._loadNext = function()
{

	if(this.done) return;
	//invoke group loaded call back
	var callBack = this.groups_aary[this.groups_ary[0]]

	this.groups_aary[this.groups_ary[0]]();
	
	this.groups_ary.shift();
	
	if(this.groups_ary.length > 0 )
	{

		this._loadGroup(this.groups_ary[0]);
	}
	else
	{
		this.done = true;
	}	
}

