﻿// Settings

var includeCaption = 1;   // Turn on the "caption" feature, and write out the caption HTML
var zoomTime       = 5;   // Milliseconds between frames of zoom animation
var zoomSteps      = 15;  // Number of zoom animation frames
var fade           = 1;   // Fade images in / out
var minBorder      = 90;  // Amount of padding between large, scaled down images, and the window edges

var zoomImageURI   = 'data/zoom/'; // Location of your zoom images

// Init. Do not add anything below this line, unless it's something awesome.

var debugShadow    = 0;

var myWidth = 0, myHeight = 0, myScroll = 0, zoomOpen = false, preloadFrame = 1, preloadActive = false, preloadTime = 0, imgPreload = new Image();

var zoomActive = new Array();
var zoomTimer  = new Array();
var zoomOrigW  = new Array();
var zoomOrigH  = new Array();
var zoomOrigX  = new Array();
var zoomOrigY  = new Array();

var zoomID    = "ZoomBox";
var theID     = "ZoomImage";
var theCap    = "ZoomCaption";
var theCapDiv = "ZoomCapDiv";

// Setup The Page! Called onLoad();

function setupZoom() {
  prepZooms();
  insertZoomHTML();
  zoomdiv = document.getElementById(zoomID);  
  zoomimg = document.getElementById(theID);
}

// Inject Javascript functions into zoomable href's, one by one.
// This is done at page load time via an onLoad() handler.

function prepZooms() {
  if (! document.getElementsByTagName) {
    return;
  }
  var links = document.getElementsByTagName("a");
  for (i = 0; i < links.length; i++) {
    if (links[i].getAttribute("href") && (links[i].getAttribute("rel"))) {
      if (links[i].getAttribute("rel").indexOf("zoom:") == 0) {
	    links[i].onclick = function () { zoomClick(this); return false; };
	    links[i].onmouseover = function () { zoomPreload(this); };
      }
    }
  }
}

// Preload a zoom image when hovering over the thumbnail, then set the image once the preload is complete.
// Preloaded image is stored in imgPreload() and swapped out in the zoom function.

function zoomPreload(from) {

  var theimage = from.getAttribute("href");

  // Only preload if we have to, i.e. the image isn't this image already

  if (imgPreload.src.indexOf(from.getAttribute("href").substr(from.getAttribute("href").lastIndexOf("/"))) == -1) {
    preloadActive = true;
    imgPreload = new Image();
      
    // Set a function to fire when the preload is complete, setting flags along the way.
   
    imgPreload.onload = function() {
      preloadActive = false;
    }

    // Load it!
    imgPreload.src = theimage;
  }
}

// Start the preloading animation cycle.

function preloadAnimStart() {
  preloadTime = new Date();
  document.getElementById("ZoomSpin").style.left = (myWidth / 2) + 'px';
  document.getElementById("ZoomSpin").style.top = ((myHeight / 2) + myScroll) + 'px';
  preloadFrame = 1;
  document.getElementById("SpinImage").src = zoomImageURI+'zoom-spin-'+preloadFrame+'.png';  
  preloadAnimTimer = setInterval("preloadAnimPending()", 100);
}

// Until we've been preloading for one second, just chill out in here.

function preloadAnimPending(from) {
  if (preloadActive != false) {
    if ((new Date() - preloadTime) > 1000) {
      document.getElementById("ZoomSpin").style.visibility = "visible";
      clearInterval(preloadAnimTimer);
      preloadAnimTimer = setInterval("preloadAnim()", 100);
    }
    else {
      // Stay in this loop and don't do anything while we wait one second
    }
  } else {
    clearInterval(preloadAnimTimer);
    zoomIn(preloadFrom);
  }
} 

// After one second, display and ANIMATE the jibber jabber widget

function preloadAnim(from) {
  if (preloadActive != false) {
    document.getElementById("SpinImage").src = zoomImageURI+'zoom-spin-'+preloadFrame+'.png';
    preloadFrame++;
    if (preloadFrame > 12) {
      preloadFrame = 1;
    }
  } else {
    document.getElementById("ZoomSpin").style.visibility = "hidden";    
    clearInterval(preloadAnimTimer);
    zoomIn(preloadFrom);
  }
}

// We got a click!
// Should we do the zoom? Or wait for the preload to complete?

function zoomClick(from) {

  // Get browser dimensions
  getSize();

  if (preloadActive == true) {
    // Preloading is otherwise still going on. So wait.
    preloadFrom = from;
    preloadAnimStart();
  } else {
    // Otherwise, we're loaded: do the zoom!
    zoomIn(from);
  }
}

// Zoom an element in to endH endW, using zoomHost as a starting point.
// "from" is an object reference to the href that spawned the zoom.

function zoomIn(from) {

  // Get the settings from the "rel" tag in the zoom href
  //
  // rel format: rel="zoom:width,height,source,[rollover img]"
  //
  // Example: <a href="test.jpg" rel="zoom:500,450,image1-id">
  
  theRel = from.getAttribute("rel");
  var tempArgs = theRel.substring(5,theRel.length).split(',');
  
  // Check for missing arguments
  
  if (tempArgs[0] == undefined || tempArgs[1] == undefined || tempArgs[2] == undefined) { alert("Missing zoom arguments!"); }
  
  // Setup all zoom arguments, including rollover, image, etc.
  
  if (tempArgs[3] == undefined || tempArgs[3] == 0 || tempArgs[3] == 1) { // 0 and 1 check to not break code from when arg3 was "fade" argument. Remove eventually
    rollOverImg = "";
  }
  else { rollOverImg = tempArgs[3]; }
  
  image         = from.getAttribute("href");
  var zoomHost  = tempArgs[2];
  var endW      = tempArgs[0];
  var endH      = tempArgs[1];
  
  // Don't act if we're already doing something.
  
  if (zoomActive[theID] != true) {
  
     // Clear everything out just in case something is already open
     
     document.getElementById("ShadowBox").style.visibility = "hidden";
     document.getElementById("ZoomClose").style.visibility = "hidden";     
     
     // Set the CAPTION if turned on
  
     if (includeCaption == 1) {
       zoomcap  = document.getElementById(theCap);
       zoomcapd = document.getElementById(theCapDiv);
       
       if (from.getAttribute('title') && includeCaption == 1) {
         zoomcapd.style.display = 'block';
         zoomcap.innerHTML = from.getAttribute('title');
       } else {
         zoomcapd.style.display = 'none';
       }
       
     }   
  
     // Set the image to the right image.
     
     zoomimg.src = image;
     
     // Find the initial size and position of our zoomer to the size of the source thumbnail, dynamically
  
     hostimg = document.getElementById(zoomHost);
     startW = hostimg.width;
     startH = hostimg.height;
  
     if (startW == undefined && startH == undefined) {
  	    startW = 50;
  	    startH = 12;
     }
  
     var hostX = 0;
     var hostY = 0;
     var hostFind = hostimg;
     
     do {
       hostX += hostFind.offsetLeft;
       hostY += hostFind.offsetTop;
     } while (hostFind = hostFind.offsetParent)
     
     // Store original position in an array for future zoomeOut
     
     zoomOrigW[theID] = startW;
     zoomOrigH[theID] = startH;
     zoomOrigX[theID] = hostX;
     zoomOrigY[theID] = hostY;
     
     // Now set it
     
     zoomimg.style.width = startW + 'px';
     zoomimg.style.height = startH + 'px';
     zoomdiv.style.left = hostX + 'px';
     zoomdiv.style.top = hostY + 'px';
     
     // Show the zoom box, make it invisible
     
     if (fade == 1) {
       setOpacity(0, zoomID);
     }
     zoomdiv.style.visibility = "visible";
  
     // If it's too big to fit, shrink the width and height to fit (with ratio).
     // (Fixed by JSH, who rocks)
  
     sizeRatio = endW / endH;
     if (endW > myWidth - minBorder) {
	endW = myWidth - minBorder;
	endH = endW / sizeRatio;
     }
     if (endH > myHeight - minBorder) {
        endH = myHeight - minBorder;
        endW = endH * sizeRatio;
     }
  
     // Setup Zoom
     
     zoomCurrent = 0;
     // zoomAmountW = (endW - startW) * ((0.9 - 1) / (Math.pow(0.9, zoomSteps) - 1));
     // zoomAmountH = (endH - startH) * ((0.9 - 1) / (Math.pow(0.9, zoomSteps) - 1));
  
     zoomAmountW = (endW - startW) / zoomSteps;
     zoomAmountH = (endH - startH) / zoomSteps;
  
     // Setup Movement
   
     zoomAmountX = ((myWidth / 2) - (endW / 2) - hostX) / zoomSteps;
     zoomAmountY = (((myHeight / 2) - (endH / 2) - hostY) + myScroll) / zoomSteps;
     
     // alert(zoomAmountX + " and " + zoomAmountY);
     
     // Setup Fade with Zoom, If Requested
     
     if (fade == 1) {
       fadeCurrent = 0;
       fadeAmount = (0 - 100) / zoomSteps;
     } else {
       fadeAmount = 0;
     }
     
     // Set the image, just in case it didn't get set via the preload system
     
     zoomimg.src = image;
       
     // Do It!

     zoomTimer[theID] = setInterval("zoomElement('"+zoomID+"', '"+theID+"', "+zoomCurrent+", "+endH+", "+endW+", "+zoomAmountH+", "+zoomAmountW+", "+zoomAmountX+", "+zoomAmountY+", "+zoomSteps+", "+fade+", "+fadeAmount+", 'zoomDoneIn(zoomID)')", zoomTime);
     zoomActive[theID] = true; 
  }
}

// Zoom it back out.

function zoomOut() {

  // Check to see if something is happening/open
  
  if (zoomActive[theID] != true) {
     
     // First, get rid of the shadow if necessary
     
     document.getElementById("ShadowBox").style.visibility = "hidden";
     document.getElementById("ZoomClose").style.visibility = "hidden";
     
     // Now, figure out where we came from, to get back there
     
     endH = zoomOrigH[theID];
     endW = zoomOrigW[theID];
     endX = zoomOrigX[theID];
     endY = zoomOrigY[theID];
     startH = zoomimg.height;
     startW = zoomimg.width;
     startX = parseInt(zoomdiv.style.left);
     startY = parseInt(zoomdiv.style.top);

     // Setup Zoom
     
     zoomCurrent = 0;
     // zoomAmountW = (endW - startW) * ((0.9 - 1) / (Math.pow(0.9, zoomSteps) - 1));
     // zoomAmountH = (endH - startH) * ((0.9 - 1) / (Math.pow(0.9, zoomSteps) - 1));
     zoomAmountW = (endW - startW) / zoomSteps;
     zoomAmountH = (endH - startH) / zoomSteps;
     
     // Setup Movement 
   
     getSize();
     zoomAmountX = (endX - startX) / zoomSteps;
     zoomAmountY = (endY - startY) / zoomSteps;
     
     // Setup Fade with Zoom, If Requested
     
     if (fade == 1) {
       fadeCurrent = 0;
       fadeAmount = (100 - 0) / zoomSteps;
     } else {
       fadeAmount = 0;
     }
     
     // Do It!
     
     zoomTimer[theID] = setInterval("zoomElement('"+zoomID+"', '"+theID+"', "+zoomCurrent+", "+endH+", "+endW+", "+zoomAmountH+", "+zoomAmountW+", "+zoomAmountX+", "+zoomAmountY+", "+zoomSteps+", "+fade+", "+fadeAmount+", 'zoomDone(zoomID, theID)')", zoomTime);
     zoomActive[theID] = true;
   }
}

// Finished Zooming In

function zoomDoneIn(zoomdiv, theID) {

  // Note that it's open
  
  zoomOpen = true;

  if (debugShadow == 1) {
    // alert("Here");              // DEBUG SHADOW
    setOpacity(0, "ZoomImage");    // DEBUG SHADOW
  }

  // Make sure they are gone

  setOpacity(0, "ShadowBox");
  setOpacity(0, "ZoomClose");

  // Position the shadow behind the zoomed in image.

  zoomdiv = document.getElementById(zoomdiv);
  shadowdiv = document.getElementById("ShadowBox");
 
  shadowLeft = parseInt(zoomdiv.style.left) - 13;
  shadowTop = parseInt(zoomdiv.style.top) - 8;
  shadowWidth = zoomdiv.offsetWidth + 26;
  shadowHeight = zoomdiv.offsetHeight + 26; 

  shadowdiv.style.width = shadowWidth + 'px';
  shadowdiv.style.height = shadowHeight + 'px';
  shadowdiv.style.left = shadowLeft + 'px';
  shadowdiv.style.top = shadowTop + 'px';
  
  // Display Shadow and Zoom
  
  document.getElementById("ShadowBox").style.visibility = "visible";
  fadeElementSetup("ShadowBox", 0, 100, 5);
  document.getElementById("ZoomClose").style.visibility = "visible";
  fadeElementSetup("ZoomClose", 0, 100, 5);
  
}

// Finished Zooming Out

function zoomDone(zoomdiv, theID) {

  // No longer open
  
  zoomOpen = false;

  // Clear stuff out, clean up

  zoomOrigH[theID] = "";
  zoomOrigW[theID] = "";
  document.getElementById(zoomdiv).style.visibility = "hidden";
  zoomActive[theID] == false;
}

function zoomElement(zoomdiv, theID, zoomCurrent, zoomEndH, zoomEndW, zoomAmountH, zooomAmountW, zoomAmountX, zoomAmountY, zoomSteps, fade, fadeAmount, execWhenDone) {
  zoomCurrent++;
  
  // window.status = "Zooming Step #"+zoomCurrent+ " (zoom by " + zoomAmountH + "/" + zoomAmountW + ") (zoom to " + zoomAmountX + "/" + zoomAmountY + ") Fade: "+fadeAmount;
  
  // Do the Fade!
  
  if (fade != 0) {
    if (fadeAmount < 0) {
      setOpacity(Math.abs(zoomCurrent * fadeAmount), zoomdiv);
    } else {
      setOpacity(100 - (zoomCurrent * fadeAmount), zoomdiv);
    }
  }
  
  // Do the Zoom
  
  // Used for ease in / out. Check with Dave about inaccurate finishing amounts
  // zoomAmountH = zoomAmountH * 0.9;
  // zoomAmountW = zoomAmountW * 0.9;

  // alert(zoomimg.width+" and "+zoomimg.height+ " ("+zoomimg.width+" + "+zoomAmountW+") ("+zoomimg.height+" + "+zoomAmountH+")");

  // Do the Movement And Scaling

  document.getElementById(zoomdiv).style.left = parseInt(document.getElementById(zoomdiv).style.left) + zoomAmountX + 'px';
  document.getElementById(zoomdiv).style.top = parseInt(document.getElementById(zoomdiv).style.top) + zoomAmountY + 'px';
  zoomimg.style.width = parseInt(zoomimg.style.width) + zoomAmountW + 'px';
  zoomimg.style.height = parseInt(zoomimg.style.height) + zoomAmountH + 'px';
  
  // Test if we're done, or if we continue

  if (zoomCurrent == zoomSteps) {
    zoomActive[theID] = false;
    clearInterval(zoomTimer[theID]);

    // It's possible our finishing position isn't perfect. Set it exactly here.
    // In version 2, don't pre-calculate movements.
    zoomimg.style.width = parseInt(zoomEndW) + 'px';
    zoomimg.style.height = parseInt(zoomEndH) + 'px';

    // alert(zoomEndW + " and " + zoomimg.width);
    // alert(zoomEndH + " and " + zoomimg.height);

    if (execWhenDone != "") {
      eval(execWhenDone);
    }
  } else {
    clearInterval(zoomTimer[theID]);
    zoomTimer[theID] = setInterval("zoomElement('"+zoomdiv+"', 'ZoomImage', "+zoomCurrent+", "+zoomEndH+", "+zoomEndW+", "+zoomAmountH+", "+zoomAmountW+", "+zoomAmountX+", "+zoomAmountY+", "+zoomSteps+", "+fade+", "+fadeAmount+", '"+execWhenDone+"')", zoomTime);  }
}

// Zoom Rollover Functions

function zoomMouseOver() {
  if (rollOverImg != "") {
     if (document.getElementById("ZoomImage").src != rollOverImg) {
        document.getElementById("ZoomImage").src = rollOverImg;
     }
  }
}

function zoomMouseOut() {
  if (rollOverImg != "") {
     if (document.getElementById("ZoomImage").src != image) {
        document.getElementById("ZoomImage").src = image;
     }
  }
}

// Get the size of the window, and set myWidth and myHeight

function getSize() {
  if (document.all) {
    // IE4+ or IE6+ in standards compliant 
    myWidth  = (document.documentElement.clientWidth) ? document.documentElement.clientWidth : document.body.clientWidth;
    myHeight = (document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.clientHeight;
    myScroll = (document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop;
  } else {
    // Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
    myScroll = window.pageYOffset;
  }
}