/*
Summary:  Loads a pairs of Images, a thumbnail and big version, in a user
          friendly manner.
Remarks:  The images are downloaded after the end of the page loading.
          Only when the big version is downloaded is the corresponding
          thumbnail made visibile to the user.
          The user can click on the thumbnail to examine the big version
          even while other images are downloading. This is the Ajaxian
          feature (without using the xmlHTTPRequest object).  
Version:  0.8d
Author:   John Bentley (www.softmake.com.au)     
Depends on: 
  -

Usage Requirements:

1. In your XHTML source reference this javascript file, thumbnailViewer.js,
    and the stylesheet thumbnailViewer.css.
    
  <link type="text/css" rel="stylesheet" href="thumbnailViewer.css" />
  <script type="text/javascript" src="thumbnailViewer.js"></script>

2. Copy and paste the following code.
        <div id="imageSection">
          
          <div id="statusSection">
            <div id="statusMessage">Loading Images </div> 
            <div id="progressBarHolder">
              <div id="progressBar"></div>            
            </div>
            <span id="progressMessage"></span>
          </div>
          
          <div id="instructions">Click on a thumbnail to see the big version.</div>
          
          <table class="thumbnailRack">
            <tr>
              <td>
                <img id="thumb010" class="thumbnailImage" width="90" height="71" src="images/hangGliderBoot/thumbnail/hangGliderBoot010.jpg" onclick="showBigImage(this)" alt="Thumbnail" />
              </td>
            </tr>
            <tr>
              <td>
                <img id="thumb020" class="thumbnailImage" width="75" height="96" src="images/hangGliderBoot/thumbnail/hangGliderBoot020.jpg" onclick="showBigImage(this)" alt="Thumbnail" />
              </td>
            </tr>
            <tr>
              <td>
                <img id="thumb030" class="thumbnailImage" width="78" height="75" src="images/hangGliderBoot/thumbnail/hangGliderBoot030.jpg" onclick="showBigImage(this)" alt="Thumbnail" />
              </td>
            </tr>
          </table>
          <!--
            The onload event is not HTML. That's why we build the image, of the following kind and in this location, with
            javascript code ... so the page validates.
            <img id="bigImage010" class="bigImage" src="images/hangGliderBoot/hangGliderBoot010.jpg" onload="showThumbnail(this)" />
           -->
        
        </div><!--imageSection-->

Note the following about the above code        
  * Any element with an Id is compulsory.
  * Thumnail images must have:
        id="thumb###"
        class="thumbnailImage"
        onclick="showBigImage(this)"
        src=[Points to a thumbnail image]
  * You DON'T have to have the thumbnails in the table with "thumbnailRack" class.

3. Put the following in your XHTML source file and
    * Modify the source path to the images (optional
    * Edit the file names of your images. 
      (You don't have to worry about specifying image width and height).

      // path relative to the XHTML source.
      var loader = new ImageLoader("images/hangGliderBoot/");
      
      // The id must be of the form "bigImage###".
      // The number of the big image will associate it with the 
      // corresponding number of the thumnailId. 
      //  Eg "bigImage020" <-> id="thumb020" 
      loader.pushImage("hangGliderBoot010.jpg", "bigImage010");
      loader.pushImage("hangGliderBoot020.jpg", "bigImage020");
      loader.pushImage("hangGliderBoot030.jpg", "bigImage030");
      
    
4. Modify and Style to fit in with your website.
*/

var currentBigImageId = null;
          
function ProgressHandler (total) {
  this.total = total || 100;
  this.percentDone = 0;
          
  this.update = function (doneCount) {
    this.percentDone = (doneCount/this.total) * 100;
    
    $("progressBar").style.width = this.percentDone + "%";
    $("progressMessage").innerHTML = "Loaded " + doneCount + " of " + this.total + ".";
    //alert("completed " + this.percentDone + "%");
    
    if (doneCount == this.total) {
      $("progressBarHolder").style.display = "none";
      $("progressBar").style.display = "none";
      $("progressMessage").style.display = "none";
      
      clearTimeout(timerId); // stop animation of statusMessage.
      //$("statusSection").style.visibility = "hidden";
      $("statusMessage").innerHTML = "All " + this.total + " images Loaded.";            
      $("statusMessage").style.cssFloat = "none"; // Gecko
      $("statusMessage").style.styleFloat = "none"; // IE
      $("statusMessage").style.marginLeft = "auto";
      $("statusMessage").style.marginRight = "auto";
    }
  } // update
  
} // ProgressHandler
  
var progress = new ProgressHandler();

var animateCount = 0;
var timerId = 0;

function animate() {
  var maxDots = 10;
  var safety = 100;
  var textOut = "";
  var re = /([^.]*)(\.*)/;
  var stringToSearch = $("statusMessage").childNodes[0].nodeValue;
  //window.status = animateCount;
  animateCount++;
  if (animateCount <= safety) {
    var matchArray = re.exec(stringToSearch)
    if (matchArray == null) {
      throw new Error("No match in " + stringToSearch);
    }
    var dots = matchArray[2];
    var newString = "";
    var newDots = "";
    if (dots.length < maxDots) {
      newDots = dots + ".";
    } else {
      newDots = ".";
    }
    
    var newString = stringToSearch.replace(re,"$1" + newDots);
    $("statusMessage").childNodes[0].nodeValue = newString;
    timerId = setTimeout("animate()", 500);
  } else {
    clearTimeout(timerId);
  }
}      

function showBigImage(thumbnailElement) {
  var re = /(\d+(?=\.))(\.)(\w+)$/m;
  
  var stringToSearch = thumbnailElement.src
  var matchArray = re.exec(stringToSearch);
  if (matchArray == null) {
    throw new Error("No match in " + stringToSearch);
  }
  
  var bigImageId = "bigImage" + matchArray[1];
  
  if(currentBigImageId) {
    $(currentBigImageId).style.display = "none";
  }
  $(bigImageId).style.display = "block";
  currentBigImageId = bigImageId;
} // showBigImage


var showThumbnailRunCount = 1;

function showThumbnail(bigImageElement) {
  var re = /(\d+(?=\.))(\.)(\w+)$/m;
  
  var stringToSearch = bigImageElement.src
  var matchArray = re.exec(stringToSearch);
  if (matchArray == null) {
    throw new Error("No match in " + stringToSearch);
  }
  
  var thumbnailId = "thumb" + matchArray[1];
  document.getElementById(thumbnailId).style.visibility = "visible"; 
  //alert(thumbnailId + " visible");
  
  /* Show the first one when loaded */
  if (showThumbnailRunCount == 1) {
    progress.total = loader.specOfImages.length;
    $("instructions").style.visibility = "visible";
    $("progressBarHolder").style.visibility = "visible";
    showThumbnailFirstRun = false;
  }
  progress.update(showThumbnailRunCount);
  showThumbnailRunCount++;
}// showThumbnail    


function ImageLoader(baseUri) {
  this.baseUri = (baseUri || "");
  
  this.specOfImages = [];

  this.pushImage = function(fileName, id) {
    var specOfImage = new Object();
    specOfImage.src = this.baseUri + fileName;
    specOfImage.className = "bigImage";
    specOfImage.id = id;
    this.specOfImages[this.specOfImages.length] = specOfImage;
  }
  
  /* Don't worry about width & height, that's just for posers. */
  this.load = function(containerElement, imageOnLoadFunction) {
    if (!containerElement) containerElement = document.body;  
    for (var i = 0; i < this.specOfImages.length; i++) {
      var imgElement = document.createElement("img");
      imgElement.className = this.specOfImages[i].className 
      imgElement.id = this.specOfImages[i].id           
      imgElement.onload = function(evt) {
        // The 'this' is the imgElement, not the ImageLoader Object.
        imageOnLoadFunction(this); 
      }       
      imgElement.src = this.specOfImages[i].src 
      containerElement.appendChild(imgElement);
    }
  }
  
} // ImageLoader.

/* Utiltiy */
function $(id){
  return document.getElementById(id);
}

/* 
Summary:  adds a function to the onload event without overwriting
          previous functions assignments to onload.
Usage Examples: 
    addLoadEvent(nameOfSomeFunctionToRunOnPageLoad);
    // Or
    addLoadEvent(function() {
      // more code to run on page load 
    });
Master:  WebScriptLibrary > events.js

Source:      Simon Willson > Executing JavaScript on page load  
        http://simon.incutio.com/archive/2004/05/26/addLoadEvent */             
function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}      

function onLoad(){
  animate();
  loader.load(document.getElementById("imageSection"), showThumbnail); 
} 

addLoadEvent(onLoad);