function ImagePreloader(images, retry, callback, calleach) {
  // store the call-back
  this.callback = callback;
  this.calleach = calleach;

  if ( retry == null)
    this.retry = 0;
  else
    this.retry = retry;

  // initialize internal state.
  this.nLoaded = 0;
  this.nProcessed = 0;
  this.aImages = new Array;
  this.FailedImages = 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]);
}

ImagePreloader.prototype.preload = function(image) {
  // create new Image object and add to array
  var oImage = document.createElement("img");
  this.aImages.push(oImage);

  // set up event handlers for the Image object
  oImage.onload = ImagePreloader.prototype.onload;
  oImage.onerror = ImagePreloader.prototype.onerror;
  oImage.onabort = ImagePreloader.prototype.onabort;

  // assign pointer back to this.
  oImage.oImagePreloader = this;
  oImage.bLoaded = false;

  // assign the .src property of the Image object
  oImage.src = image;
}

ImagePreloader.prototype.onComplete = function(imgsrc) {
  this.nProcessed++;
  this.calleach(imgsrc);

  if ( this.nProcessed == this.nImages ) {
    if ( this.FailedImages.length > 0  && this.retry > 0) {
      //decrement retry count
      this.retry--;
      this.nProcessed = 0;
      this.nImages = this.FailedImages.length;

      //clear the failed images
      var tmpImg = this.FailedImages;
      this.FailedImages = new Array;

      //preload failed images
      for ( var i = 0; i < tmpImg.length; i++)
      this.preload(tmpImg[i]);
    } else if (this.callback) {
      this.callback();
    }
  }
}

ImagePreloader.prototype.onload = function() {
  this.bLoaded = true;
  this.oImagePreloader.nLoaded++;
  this.oImagePreloader.onComplete(this.src);
}

ImagePreloader.prototype.onerror = function() {
  this.bError = true;
  this.oImagePreloader.OnError(this);
} 

ImagePreloader.prototype.onabort = function() {
  this.bAbort = true;
  this.oImagePreloader.onComplete(this.src);
}

ImagePreloader.prototype.OnError = function(imgObj) {
  this.aImages.remove(imgObj);
  this.FailedImages.push(imgObj.src);
  this.onComplete();
}

