// Image Zoom II (22-May-2006)
// by Vic Phillips http://www.vicsjavascripts.org.uk
// http://www.vicsjavascripts.org.uk/ImageZoom/ImageZoom.htm

// Zoom In or Out of an image by mouseOver of an element.
// The object may be the parent element of the image or a remote element.
// The minimum and maximum dimensions are specified by width and the aspect ratio and position retained.
// The 'Zoom' activated by mouseover of the  mouseover element
// and 'Zoom' factor dictated by the mouse position from the center of the mouseover element.
// Options allow,
// the 'Zoom' element to be positioned centered horizontally and/or vertically in the parent element during Zoom
// and hidden at the zoom extremity.
//
// The effect be applied to any 'block' elements in addition to images.
//
// There may be as many applications on a page as required.

// ***** Application Notes

// **** The HTML Code
//
// ** Where the mouseover element is the parent of the image
// e.g.
//  <div id="P1" style="position:relative;width:100px;height:75px" >
//   
//   <img id="Img1" style="position:absolute;top:30px;left:40px;" src="One.gif" width="20" height="15" >
//   <img src="Blank.gif" width="100" height="75" >
//  </div>
//
// ** Where the mouseover element is the parent of the image
// e.g.
//  <div id="P3" style="position:absolute;left:0px;top:30px;width:100px;height:75px;background-color:red;" ></div>
//
//  <div style="position:absolute;left:110px;top:0px;width:200px;height:150px" >
//   
//  <img id="Img3" style="position:absolute;top:0px;left:0px;" src="One.gif" width="200" height="150" >
//  </div>
//


// **** IMPORTANT NOTES
//
// The 'Zoom' activated by mouseover of the  mouseover element
// and 'Zoom' factor dictated by the mouse position from the center of the mouseover element.
//
// When the parent element has no specified it must contain a blank .gif image of the parent element size.
// The style position of the  image and parent element must be 'position:relative' or 'position:absolute;'
//
// During Zoom the zoom element is positioned centered horizontally and vertically in the parent element.
//

// **** Initialising the Application
//
// Each application would normally be initialised by a <BODY> or window onload event.
// e.g.
// <body onload="zxcZoomII('P1','Img1',20,200);zxcZoomII('P2','Img2',200,20,C);zxcZoomII('P3','Img3',200,20);">
// where function 'zxcZoomII('
// parameter 0 = the unique ID name of the parent element.       (string)
// parameter 1 = the unique ID name of the element to Zoom.      (string)
// for Zoom Out parameter 3 = maximum zoom dimension(extremity). (digits)
// for Zoom Out parameter 4 = minimum zoom dimension.            (digits)
// for Zoom In parameter 3 = minimum zoom dimension(extremity).  (digits)
// for Zoom In parameter 4 = maximum zoom dimension.             (digits)
// parameter 5 = (optional) the options.                         (string)
//               include character 'C' to positioned the zoom element centered horizontally in the parent element during Zoom.
//               include character 'M' to positioned the zoom element centered vertically in the parent element during Zoom.
//               include character 'X' to restrict the active mouse position to horizontal(X) (the default is X and Y).
//               include character 'Y' to restrict the active mouse position to vertical(Y) (the default is X and Y).
//               include character 'H' to hide the zoom element at the zoom extremity.

// **** Controlling Multipe Zoom Elements
//
// Example HTML Code
// <div style="position:relative;width:310px;height:180px;" >
// <div id="P5" style="position:absolute;left:0px;top:30px;width:100px;height:75px;background-color:#FFFFCC;border:solid black 1px;text-align:center;font-size:13px;" >
// <div id="P6" style="position:absolute;left:0px;top:0px;width:100px;height:75px;background-color:#FFFFCC;text-align:center;font-size:13px;" >
// </div>
//
// <div style="position:absolute;left:110px;top:0px;width:0px;height:0px;" >
//  
//  <img id="Img5" style="position:relative;visibility:hidden;top:0px;left:0px;" src="One.gif" width="20" height="15" >
//  <div id="Img6" style="position:relative;visibility:hidden;overflow:hidden;top:0px;left:0px;width:20px;height:5px;background-color:#FFFFCC"  >Some Text</div>
// </div>
// </div>


// **** General
//
// All variable, function etc. names are prefixed with 'zxc' to minimise conflicts with other JavaScripts
// These character are easily changed to characters of choice using global find and replace.
//
// The Functional Code(about (3K) is best as an External JavaScript
//
// Tested with IE6 and Mozilla FireFox
//


// **** Functional Code - NO NEED to Change

// **** Customising Variables

var zxcZIndex=0;         // the base Z-Index for the images
var zxcDelay=5;         // the global zoom speed may be specified in addition to the call
var zxcAddCursor=true;   // true to add a 'hand'/'pointer' cursor to the Zoom Image, false for no cursor

var zxcEvt=0;
/*
function zxcZoomII(zxcpid,zxcimgid,zxcmax,zxcmin,zxcopt){
 var zxcobj=document.getElementById(zxcpid);
 alert(zxcpid);
 if (zxcobj.mm){ return; }
 zxcopt=zxcopt||'';
 zxcopt=zxcopt.toUpperCase();
 var zxcimg=document.getElementById(zxcimgid);
 zxcimg.par=zxcimg.parentNode;
 zxcobj.img=zxcimg;
 zxcobj.vis=zxcopt.match('H')?'hidden':'visible';
 zxcobj.cen=zxcopt.match('C')?true:false;
 zxcobj.mid=zxcopt.match('M')?true:false;
 zxcobj.x=zxcopt.match('X')?true:false;
 zxcobj.y=zxcopt.match('Y')?true:false;
 zxcobj.mm=[zxcmax,zxcmin,zxcimg.offsetWidth/zxcimg.offsetHeight];
 zxcAddEvt(zxcobj,'zxcZoomDo','mousemove')
 zxcAddEvt(zxcobj,'zxcZoomOut','mouseout')
}
*/
/*
function zxcZoomDo(zxce){
 var zxcx=Math.abs((zxcMse(zxce)[0]-zxcPos(this)[0]-parseInt(this.style.width)/2)/parseInt(this.style.width)*2);
 var zxcy=Math.abs((zxcMse(zxce)[1]-zxcPos(this)[1]-parseInt(this.style.height)/2)/parseInt(this.style.height)*2)
 var zxccng=Math.max(zxcx,zxcy);
 if (this.x&&!this.y){ zxccng=zxcx; };
 if (this.y&&!this.x){ zxccng=zxcy; };
 var zxcnw=(this.mm[0]>this.mm[1])?(this.mm[1]+(this.mm[0]-this.mm[1])*zxccng):((this.mm[0])+(this.mm[1]-this.mm[0])*Math.max((1-zxccng),.001));
 if (zxcnw<.01){ return; }
 zxcStyle(this.img,{visibility:'visible',width:zxcnw+'px',height:(zxcnw/this.mm[2])+'px'});
 zxcCenMid(this);
}
*/
function zxcZoomOut(){
 zxcStyle(this.img,{visibility:this.vis,width:(this.mm[0])+'px',height:(this.mm[0]/this.mm[2])+'px'});
 zxcCenMid(this);
}

function zxcCenMid(zxcobj){
 if (zxcobj.cen){ zxcStyle(zxcobj.img,{left:((parseInt(zxcobj.img.par.style.width)-parseInt(zxcobj.img.style.width))/2)+'px'});  }
 if (zxcobj.mid){ zxcStyle(zxcobj.img,{top:((parseInt(zxcobj.img.par.style.height)-parseInt(zxcobj.img.style.height))/2)+'px'}); }
}

function zxcStyle(zxcele,zxcstyle){
 for (key in zxcstyle){ zxcele.style[key]=zxcstyle[key]; }
}

function zxcMse(event){
 if(!event) var event=window.event;
 if (document.all){ return [event.clientX+zxcDocS()[0],event.clientY+zxcDocS()[1]]; }
 else { return[event.pageX,zxcMseY=event.pageY]; }
}

function zxcDocS(){
 var zxcsx,zxcsy;
 if (!document.body.scrollTop){ zxcsx=document.documentElement.scrollLeft; zxcsy=document.documentElement.scrollTop; }
 else { zxcsx=document.body.scrollLeft; zxcsy=document.body.scrollTop; }
 return [zxcsx,zxcsy];
}

function zxcPos(zxcobj){
 zxclft=zxcobj.offsetLeft;
 zxctop=zxcobj.offsetTop;
 while(zxcobj.offsetParent!=null)
 {
  zxcpar=zxcobj.offsetParent;
  zxclft+=zxcpar.offsetLeft;
  zxctop+=zxcpar.offsetTop;
  zxcobj=zxcpar;
 }
 return [zxclft,zxctop];
}

function zxcEventAdd(zxco,zxct,zxcf) {
 if ( zxco.addEventListener ){ zxco.addEventListener(zxct, function(e){ zxco[zxcf](e);}, false); }
 else if ( zxco.attachEvent ){ zxco.attachEvent('on'+zxct,function(e){ zxco[zxcf](e); }); }
 else {
  var zxcPrev=zxco["on" + zxct];
  if (zxcPrev){ zxco['on'+zxct]=function(e){ zxcPrev(e); zxco[zxcf](e); }; }
  else { zxco['on'+zxct]=zxco[zxcf]; }
 }
}

function zxcAddEvt(zxc,zxcfun,zxcevt){
 zxc['zxcaddEvt'+zxcEvt]=window[zxcfun];
 zxcEventAdd(zxc,zxcevt,'zxcaddEvt'+zxcEvt);
 zxcEvt++;
}

var zxcOOPCnt=0;
var zxcCursor=document.all?'hand':'pointer';
zxcZIndex=-zxcZIndex||1;
var zxcZIndx=zxcZIndex;
zxcDelay=zxcDelay||10;

function zxcZoom(zxcobj,zxcph,zxcmw,zxcmh,zxcspd,zxcopt){  
 if (typeof(zxcobj)=='string'){ zxcobj=document.getElementById(zxcobj); }
 var zxcphoto;
 if (zxcobj.tagName.toUpperCase()=='IMG'){
  zxcphoto=zxcph||zxcobj.src;
  if (zxcphoto.length<5){zxcphoto=zxcobj.src; }
//  alert(zxcobj.src);
 }
 var zxcspd=zxcspd||1;
 var zxcopt=zxcopt||null;
 if (!zxcobj.zxcoop){ zxcobj.zxcoop=new zxcOOPZoom(zxcobj,zxcphoto,zxcmw,zxcmh,zxcspd,zxcopt,zxcopt); }
 clearTimeout(zxcobj.zxcoop.to);
 zxcobj.zxcoop.inc*=-1
 if (zxcobj.zxcoop.large.load){ zxcobj.src=zxcobj.zxcoop.large.src; }
 zxcZIndx++;
// alert(zxcZIndx);
 zxcStyle(zxcobj,{zIndex:(zxcZIndx+'')});
 zxcobj.zxcoop.zoom();
}

function zxcOOPZoom(zxcobj,zxcph,zxcmw,zxcmh,zxcspd,zxcopt){
 this.obj=zxcobj;
 this.objS=zxcobj.style;
 this.clone=zxcobj.cloneNode(true);
 this.zxcspd=zxcspd;
 this.zxct=zxcPos(zxcobj)[1];
 this.zxcl=zxcPos(zxcobj)[0];
// alert(this.zxct + "   " + this.zxcl);
 zxcStyle(this.obj,{position:'absolute',zIndex:(zxcZIndex*1+1+''),width:zxcobj.offsetWidth+'px',height:zxcobj.offsetHeight+'px',left:this.zxcl+'px',top:this.zxct+'px'});
 if (zxcAddCursor){ zxcStyle(this.obj,{cursor:zxcCursor}); }
 this.minw=zxcobj.offsetWidth-4;    //reduced by Sieg
 this.minh=zxcobj.offsetHeight-4;   //reduced by Sieg
// alert(this.minw + '  ' + this.minh);
 this.center=zxcopt;
 this.maxw=zxcmw;
 this.maxh=zxcmh||zxcmw*this.minh/this.minw;
 this.thumb=zxcobj.src;
 this.large=new Image();
 this.large.obj=this.obj;
 if (zxcph){ this.large.onload=function(){ this.load=true; this.obj.src=this.src; }; this.large.src=zxcph; }
 zxcobj.parentNode.insertBefore(this.clone,zxcobj);
 this.inc=((this.maxw-this.minw)/100);
 this.inc=-this.inc*this.zxcspd;
 this.ratio=(this.maxh/this.maxw);
 this.ref='zxc'+zxcOOPCnt;
 window[this.ref]=this;
 this.to=null;
 zxcOOPCnt++;
}

zxcOOPZoom.prototype.setTimeOut=function(zxcf,zxcd){
 this.to=setTimeout("window."+this.ref+"."+zxcf,zxcd);
}

zxcOOPZoom.prototype.zoom=function(){
 this.w=parseInt(this.objS.width)+this.inc; this.h=parseInt(this.objS.width)*this.ratio;
 zxcStyle(this.obj,{width:(this.w)+'px',height:(this.h)+'px'});
 this.w=parseInt(this.objS.width); this.h=parseInt(this.objS.height);
 if (this.center){ zxcStyle(this.obj,{top:(this.zxct-(this.h-this.minh)/2)+'px',left:(this.zxcl-(this.w-this.minw)/2)+'px'}); }
 if ((this.inc>0&&this.w<this.maxw)||(this.inc<0&&this.w>this.minw)){ this.setTimeOut('zoom();',zxcDelay); }
 else {
  if (this.inc>0){ zxcStyle(this.obj,{width:this.maxw+'px',height:this.maxh+'px'}); }
  else {
   zxcStyle(this.obj,{zIndex:zxcZIndex,width:this.minw+'px',height:this.minh+'px',top:(this.zxct)+'px',left:(this.zxcl)+'px'});
   zxcZIndx--;
   this.obj.src=this.thumb;
  }
 }
}

function zxcStyle(zxcele,zxcstyle){
 for (key in zxcstyle){ zxcele.style[key]=zxcstyle[key]; }
}

function zxcPos(zxc){ 
 zxcObjLeft=zxc.offsetLeft;
 zxcObjTop=zxc.offsetTop;
 while(zxc.offsetParent!=null){
  zxcObjParent=zxc.offsetParent;
  zxcObjLeft+=zxcObjParent.offsetLeft;
  zxcObjTop+=zxcObjParent.offsetTop;
  zxc=zxcObjParent;
 }
 return [zxcObjLeft,zxcObjTop];
}

