//To make preloading work properly, the code must wait for the image to complete 
//  loading before it is used. In this article, I’ve created an ImagePreloader class 
//  that will preload an array of images and call a call-back function when all the 
//  images have been loaded into the browser.

//The constructor for the ImagePreloader takes an array of image URLs and a 
//  call-back function as arguments.
function ImagePreloader(images, callback)
{
	// store the callback
	this.callback = callback;
	
	// initialize internal state.
	this.nLoaded = 0;
	this.nProcessed = 0;
	this.aImages = new Array;
	
	// record the number of images.
	this.nImages = images.length;
	
	// for each image, call preload()
	for ( var i = 0; i < images.length; i++ ) 
		this.preload(images[i]);
}

//The callback function is stored for later use, then each image URL is passed 
//into the preload() method.

ImagePreloader.prototype.preload = function(image)
{
	//The preload function creates an Image object and assigns functions 
	//  for the three Image events; onload, onerror and onabort. 
	
	// create new Image object and add to array
	var oImage = new Image;
	this.aImages.push(oImage);
	
	//The onload event is raised when the image has been loaded into memory, 
	//  the onerror event is raised when an error occurs while loading the image 
	//  and the onabort event is raised if the user cancels the load 
	//  by clicking the Stop button on the browser. 
	// set up event handlers for the Image object
	oImage.onload = ImagePreloader.prototype.onload;
	oImage.onerror = ImagePreloader.prototype.onerror;
	oImage.onabort = ImagePreloader.prototype.onabort;
	
	//A pointer to the ImagePreloader object is stored in each Image object to facilitate 
	//  the callback mechanism. An optional boolean flag can be added here to indicate 
	//  whether the image loads properly or not.
	// assign pointer back to this.
	oImage.oImagePreloader = this;
	oImage.bLoaded = false;

	//Finally, the "src” attribute is assigned to start the loading of the image.
	// assign the .src property of the Image object
	oImage.src = image;
}

//The three event handler functions act in pretty much the same way; 
//  after recording the type of completion (load, error or abort), 
//  the onComplete() method of the ImagePreloader object is called. 
//  This method counts the number of images that have been processed. 
//  When the count matches the total number of images, the callback function is called 
//  with the array of Image objects and a count of the number of images that loaded 
//  correctly as arguments.

ImagePreloader.prototype.onComplete = function()
{
   this.nProcessed++;

   if ( this.nProcessed == this.nImages )
   {
      this.callback(this.aImages, this.nLoaded);
   }
}

ImagePreloader.prototype.onload = function()
{
   this.bLoaded = true;
   this.oImagePreloader.nLoaded++;
   this.oImagePreloader.onComplete();
}

ImagePreloader.prototype.onerror = function()
{
   this.bError = true;
   this.oImagePreloader.onComplete();
}

ImagePreloader.prototype.onabort = function()
{
   this.bAbort = true;
   this.oImagePreloader.onComplete();
}


//Note: While I’ve included the onload, onerror and onabort functions in the 
//  ImagePreloader prototype, they are not actually used as methods of the ImagePreloader 
//class. However, this offers a convenient way to namespace the function names.

//Making use of the ImagePreloader class is easy. 
//  During the body.onload event (or any time afterwards), an instance of the 
//  ImagePreloader class is created with an array of image URLs and a callback function. 
//  Providing the images have all loaded, they may be referenced in the new HTML safely.

//<script type=”text/javascript” src=”ImagePreloader.js”></script>
//<script type=”text/javascript”>
//var aImg = ["node.gif”, "plus.gif”, "minus.gif”, "line.gif”, "gap.gif”];
//var ip = null;
//function onPreload(aImages, nImages)
//{
//   var oDiv = document.getElementById("theDiv”);
//   if ( nImages = aImg.length )
//   {
//      oDiv.innerHTML = "Images did not load properly”;
//      return;
//   }

   // now create some elaborate tree structure using the preloaded images
//   ...
//}
//</script>
//<body onload=”ip = new ImagePreloader(aImg, onPreload);”>
//   <div id="theDiv"></div>
//</body>


