/*** Base code (C)2007 Stephen Chalmers Info: http://www.scripterlative.com?magnifimage ***/
/*** April 2010 adapted by AS Gilmour for Photographers Direct ***/

var MagnifImage=
{
 data:[],                                                    // array of data to trigger pop-up and populate it
 x:0, y:0, xDisp:0, yDisp:0,                                 // top and left gutters when using mouse
 screenWidth:0, screenHeight:0,                              // user's screen dimensions
 isViable:typeof document.getElementsByTagName!='undefined', // check if you can get a collection of objects by div id 
 browserCompatibilityCode:0,                                 // code for browser compatibility 3= IE6 standards, 2= DOM, 1 = Netscape
 firstCall:true,                                             // flag for code to do only once
 blinkFlag:true,                                             // set true to make text blink on loading, false to stop it
 useHorizontal:false,                                        // test for horizontal scroll-bar in play
 currentDisplayedIndex:-1,                                   // index of objects retrieved from div
 imgPreload:false,                                           // preload images. Set to false to only load images on rollover
 mouseUsed:true,                                             // check for focus by pointing with mouse, rather than by tabbing
 triggerElement:null,                                        // elements triggering pop-up
 cursorOffset:30,                                            // distance in pixels of pop-up from cursor position
 overTimer:null,                                             // onMouseOver timer
 outTimer:null,                                              // cleared on onMouseOver
 picHolder:null,                                             // place to put pop-up image or text for loading etc
 
 loadBgColour:null,                                          // background colour of pop-out when image loading
 noImageBgColour:null,                                       // background colour of pop-out when image not found
 
 above:false,                                                //
 left:false,                                                 // These variables are used for calculating 
 hRectData:0,                                                // the display area for the pop-up
 vRectData:0,                                                //
 reduceOffset:0,                                             //

//   setup   //
 setup:function()
 {
  var paramGroup=3;
  var i=0;
  var ii=0;
  var idParts=0;
  var j=0;
  var objRef=0;
  var sizeData=0;

  loadBgColour='#21868f';
  noImageBgColour='#d62931';

  if(this.isViable)
  {
   if(this.firstCall) // do once
   {
    this.firstCall=false;

    this.addToHandler(document, 'onmousemove', function(){MagnifImage.getMouseAndScrollData(arguments[0]);});

   } // end first call

   if( document.documentElement ){
      this.browserCompatibilityCode=3; //IE6 standards compliant mode
   }else{
       if(document.body && typeof document.body.scrollTop!='undefined'){
          this.browserCompatibilityCode=2; //DOM compliant
       }else{
          if( typeof window.pageXOffset!='undefined' ){
             this.browserCompatibilityCode=1; //Netscape compliant
          }
       }
    }
    
   for(i=this.data.length, idParts, sizeData, objRef, j=0; j<arguments.length; i++, j+=paramGroup)
   {
    objRef=this.data[i]={};     

    idParts=arguments[j].split(':');

    if( !(objRef.triggerElement=document.getElementById( idParts[0] )) ){
     alert("No'"+idParts[0]);
    }else
    {    
     if(objRef.triggerElement.parentNode && objRef.triggerElement.parentNode.tagName=='A'){
      objRef.triggerElement=objRef.triggerElement.parentNode;}
      
     objRef.classId=idParts[1] || "MagnifImage" ;
     objRef.imgObj=new Image();
     
     if( (sizeData=arguments[j+1].replace(/\s/g,'').split(",")).length==3 ) // replace whitespace, split at commas, take three elements
     {
      for(ii=0; ii<sizeData.length; ii++){
       sizeData[ii]=sizeData[ii].replace(/^\s|\s$/g,'');
      }
      objRef.imgObj.imgW=Number(sizeData[1]);
      objRef.imgObj.imgH=Number(sizeData[2]);     
     }     
        
     objRef.imgObj.imgIndex=i;
     objRef.imgObj.hasLoaded=0;     
     
     if(!isNaN(objRef.imgObj.imgW) && !isNaN(objRef.imgObj.imgH)){ // imgW and imgH are numeric
      objRef.imgObj.hasLoaded=1; 
     }else{
      objRef.imgObj.onload=function()
      {
       this.trueWidth=this.width;
       this.trueHeight=this.height;
       this.onload=null;
       this.hasLoaded=1;
       if(this.imgIndex==MagnifImage.currentDisplayedIndex){
        MagnifImage.display(this.imgIndex, true);}
      };
     }
     this.data[i].imgObj.onerror=function()
     {
      this.hasLoaded=-1;
      if(this.imgIndex==MagnifImage.currentDisplayedIndex){
       MagnifImage.display(this.imgIndex, true);}
     };
     
     objRef.imgObj.sourceFile=sizeData[0];
     
     if(this.imgPreload)
      objRef.imgObj.src=sizeData[0];
     
     objRef.titleText=arguments[j+2];

     this.addToHandler(objRef.triggerElement, 'onmouseover', new Function("clearTimeout(MagnifImage.outTimer);MagnifImage.overTimer=setTimeout('MagnifImage.display("+i+",true)',400)"));
    
     this.addToHandler(objRef.triggerElement, 'onfocus', function(){MagnifImage.mouseUsed=false;MagnifImage.triggerElement=this;MagnifImage.getElemPos(this);this.onmouseover();});
         
     this.addToHandler(objRef.triggerElement, 'onmouseout', new Function("clearTimeout(MagnifImage.overTimer);MagnifImage.display("+i+",false)"));
     
     this.addToHandler(objRef.triggerElement, 'onblur', function(){MagnifImage.getElemPos(this);this.onmouseout();});
    }
   }
  }
 },
//   end setup function   //


//   display   //
 display:function(objIndex, action)
 {
  clearInterval(this.blinkTimer);
    
  var img=this.data[objIndex].imgObj, classId=this.data[objIndex].classId;

  if(this.mainDiv)
   this.removeDiv();

  if(action)
  {
   this.getScreenData();
   if(this.screenWidth)
       this.screenWidth-=16;
   if(this.screenHeight)
    this.screenHeight-=16;
   this.mainDiv=document.createElement('div');
   var titleSpan=document.createElement('div');
   titleSpan.style.lineHeight='1.2em';
   titleSpan.className=classId+'Title';
   

   
   this.picHolder=img.hasLoaded==1 ? this.data[objIndex].imgObj : document.createElement('div');

   if(img.hasLoaded == -1 || (img.hasLoaded===0 && !img.imgW))
   {
    this.picHolder.appendChild(document.createTextNode(img.hasLoaded===0?'Loading Image':'Image Not Currently Available'));

    this.picHolder.style.backgroundColor=img.hasLoaded===0 ? loadBgColour : noImageBgColour; // background colours for whilst loading : can't find image
    // styling for writing in pop-out box, either that image is loading, or that it can't be found ... //
    this.picHolder.style.color='#fff';
    this.picHolder.style.textAlign='center';
    this.picHolder.style.lineHeight='1em';
    this.picHolder.style.padding='1em';
    this.picHolder.style.font='75% Arial, sans-serif';
  
    if(img.hasLoaded===0)
     this.blinkTimer=setInterval("MagnifImage.blink()", 600); // how fast to blink at, in milliseconds
    
    if(img.hasLoaded != -1) 
     img.src=img.sourceFile;
   }
   else
   {     
    if( img.imgH && img.imgW )
    {
     this.picHolder.trueWidth=this.picHolder.width=img.imgW;
     
     this.picHolder.trueHeight=this.picHolder.height=img.imgH;
     
     this.picHolder.alt="LOADING...";
    }
    
    this.data[objIndex].imgObj.src=img.sourceFile;
   } 

   this.mainDiv.style.position='absolute';
   this.mainDiv.style.top="0";
   this.mainDiv.style.left="0";
   this.mainDiv.style.visibility='hidden';
   this.mainDiv.style.zIndex='100000'; // stack order for the pop-out, i.e. puts this element in front of elements with lower stack orders
   this.mainDiv.style.lineHeight='0';
   this.mainDiv.className=classId;
      
   if(this.data[objIndex].titleText!="")
   {
    titleSpan.appendChild(document.createTextNode(this.data[objIndex].titleText));  
    titleSpan.style.position='relative';
    titleSpan.style.display='block';
    this.mainDiv.appendChild(titleSpan);    
   }
  
   this.mainDiv.appendChild(this.picHolder);
   
   this.computePosition(this.mainDiv);   
   document.body.appendChild(this.mainDiv);   
   this.computePosition(this.mainDiv);
   
   this.mainDiv.style.visibility='visible';
      
   this.currentDisplayedIndex=objIndex;  
  }
  else
   this.currentDisplayedIndex = -1;
 },
 //   end of display function   //
 

 //   removeDiv   //
 removeDiv:function()
 {
  document.body.removeChild(this.mainDiv);
  if(this.mainDiv)
   this.mainDiv=null;
 },
//   end of renoveDiv function   //


 //   blink   /
 // makes the text blink when loading an image     //
 // called if blinkFlag:true                    //
 blink:function()
 {
  this.picHolder.style.color=(this.blinkFlag^=true)?'#fff':'#21868f'; /*normal colour white, background colour same as background for loading image */
 },
 //   end blink function   //


 //   reduce   //
 reduce:function(elem, dims, elemX, elemY)
 {
  var wDiff=0,hDiff=0,shrink,thePic=elem.lastChild, 
      tempDim, changeData={h:0, w:0}; 

  elem.eHeight=elem.offsetHeight;
  elem.eWidth=elem.offsetWidth;
        
  if(thePic.width && thePic.width>0 && thePic.height && thePic.height>0)
  {                              
   changeData.h=thePic.height;
   changeData.w=thePic.width;
   hDiff=elem.eHeight-dims.height;
   wDiff=elem.eWidth-dims.width;
   
   shrink = 1- ( hDiff > wDiff ? (hDiff/thePic.height) : (wDiff/thePic.width) );
    
   tempDim=thePic.height; 
   
   thePic.width=Math.floor(Math.min(parseInt(thePic.width,10)*shrink, thePic.trueWidth));
     
   if(tempDim == thePic.height)
    thePic.height=Math.floor(Math.min(parseInt(thePic.height,10)*shrink, thePic.trueHeight));
    
   if(thePic!=elem.firstChild)
    elem.firstChild.style.width=thePic.width+'px';
    
   changeData.h = thePic.height - changeData.h;
   changeData.w = thePic.width - changeData.w;
  }
  
  return changeData;
 },
//   end reduce fucntion   //


//   getElemPos   //
 getElemPos:function(elem)
 {
    
  var left = !!elem.offsetLeft ? elem.offsetLeft : 0;
  var top = !!elem.offsetTop ? elem.offsetTop : 0;
  
  while(elem == elem.offsetParent)
  { 
   left += !!elem.offsetLeft ? elem.offsetLeft : 0;
   top += !!elem.offsetTop ? elem.offsetTop : 0;
  }
  
  this.x=left;
  this.y=top;  
 },
//   end getElemPos function   //


//   computePosition   //
 computePosition:function(elem)
 {
  reduceOffset={h:0,w:0};
  
  elem.eHeight=elem.offsetHeight;
  elem.eWidth=elem.offsetWidth;  
  
  left=false; above=false;
  
  if(!this.mouseUsed)
  {
   this.readScrollData();  
   this.getElemPos(this.triggerElement);
   this.x=this.xDisp;
   this.y=this.yDisp;
  }
  
  left=(this.x > (this.xDisp + this.screenWidth/2));
   
  above=(this.y > (this.yDisp + this.screenHeight/2));   
  
  vRectData=
  {
   top: this.yDisp, left: left ? this.xDisp: this.x+this.cursorOffset, right: left ? this.x-this.cursorOffset : this.xDisp+this.screenWidth,
   bottom: this.yDisp+this.screenHeight, containableArea:0, width:0, height:0
  };

  hRectData=
  {
   top: above?this.yDisp:this.y+this.cursorOffset, left: this.xDisp, right: this.xDisp+this.screenWidth,
   bottom: above?this.y-this.cursorOffset:this.yDisp+this.screenHeight, containableArea:0, width:0, height:0
  };  
  

   vRectData.containableArea=Math.min(vRectData.height=(vRectData.bottom-vRectData.top), elem.eHeight) * Math.min(vRectData.width=(vRectData.right-vRectData.left), elem.eWidth);

   hRectData.containableArea=Math.min(hRectData.height=(hRectData.bottom-hRectData.top), elem.eHeight) * Math.min(hRectData.width=(hRectData.right-hRectData.left), elem.eWidth);

  this.useHorizontal=hRectData.containableArea > vRectData.containableArea;
  
  reduceOffset=this.reduce(elem, this.useHorizontal?hRectData:vRectData);
      
  var halfHeight=elem.eHeight/2, halfWidth=elem.eWidth/2;  
  
  if(this.useHorizontal)
  {
   this.mainDiv.style.left= (this.x-halfWidth) +     
     ((this.x-halfWidth<hRectData.left && this.x+halfWidth<hRectData.right) ? Math.min( Math.abs(this.x+halfWidth-hRectData.right), Math.abs(this.x-halfWidth-hRectData.left))  //min of add right gap and left o/f
     : ( this.x+halfWidth > hRectData.right  &&  hRectData.left < this.x-halfWidth) ? -Math.min(Math.abs(this.x-halfWidth-hRectData.left),Math.abs(this.x+halfWidth-hRectData.right)) 
       : 0) +'px';    
   
   this.mainDiv.style.top=(above ? (hRectData.bottom-elem.eHeight) : hRectData.top)+'px';
  }
  else
   {
    this.mainDiv.style.left=(left ? vRectData.right-elem.eWidth : vRectData.left) +'px';
    
    this.mainDiv.style.top = (this.y-halfHeight) +
     ((this.y-halfHeight<vRectData.top && this.y+halfHeight<vRectData.bottom) ? Math.min( Math.abs(this.y+halfHeight-vRectData.bottom), Math.abs(this.y-halfHeight-vRectData.top))  //min of add bottom gap and top o/f
     : ( this.y+halfHeight > vRectData.bottom  &&  vRectData.top < this.y-halfHeight) ? -Math.min(Math.abs(this.y-halfHeight-vRectData.top),Math.abs(this.y+halfHeight-vRectData.bottom)) 
       : 0) +'px';  
   }   
      
   if(left)
    this.mainDiv.style.left=parseInt(this.mainDiv.style.left,10)-(reduceOffset.w) +'px';
    
   if(above)
    this.mainDiv.style.top=parseInt(this.mainDiv.style.top,10)-(reduceOffset.h) +'px';
    
 },
//   end computePosition function   //


//   readScrollData   //
 readScrollData:function()
 {
  switch( this.browserCompatibilityCode )
  {
   case 3 : this.xDisp=Math.max(document.documentElement.scrollLeft, document.body.scrollLeft); //IE6 standards compliant mode
            this.yDisp=Math.max(document.documentElement.scrollTop, document.body.scrollTop);
            break;

   case 2 : this.xDisp=document.body.scrollLeft; //DOM compliant
            this.yDisp=document.body.scrollTop;
            break;
            
   case 1 : this.xDisp=window.pageXOffset; this.yDisp=window.pageYOffset; //Netscape compliant
  }
 },
//   end readScrollData fucntion   //


//   getMouseAndScrollData   //
 getMouseAndScrollData:function()
 {
  var e = arguments[0] || window.event;

  this.mouseUsed=true;

  this.readScrollData();  
   
  switch( this.browserCompatibilityCode )
  {
   case 3 : this.x = this.xDisp + e.clientX; //IE6 standards compliant mode
            this.y = this.yDisp + e.clientY;
            break;

   case 2 : this.x = this.xDisp + e.clientX; //DOM compliant
            this.y = this.yDisp + e.clientY;
            break;

   case 1 : this.x = e.pageX - window.pageXOffset; //Netscape compliant
            this.y = e.pageY - window.pageYOffset;
  }

  if(this.currentDisplayedIndex>-1 && this.mainDiv)
   this.computePosition(this.mainDiv);
  
 },
 //   end getMouseAndScrollData fucntion   //
 
 //   getScreenData   //
 // Returns the height and width of the user's browser window in pixels //
 getScreenData:function()
 {
  this.screenWidth=
   window.innerWidth != null? window.innerWidth : //Non-IE
   document.documentElement && document.documentElement.clientWidth ? //IE 6+ in 'standards compliant mode'
   document.documentElement.clientWidth : document.body != null ? //IE 4 compatible
   document.body.clientWidth : null;
  this.screenHeight=
   window.innerHeight != null? window.innerHeight : //Non-IE
   document.documentElement && document.documentElement.clientHeight ? //IE 6+ in 'standards compliant mode'
   document.documentElement.clientHeight : document.body != null ? //IE 4 compatible
   document.body.clientHeight : null;  
 },
 //   end getScreenData fucntion   //
 

/*                     preLoad                    
 loads images for pop-out boxes on a page 
 called if imgPreload:true,                 
 othewise images loaded on mouseover        */
 preLoad:function(set)
 {
  if(typeof set != 'boolean')
   alert('Magnifimage.preLoad() parameter must be a boolean (true or false)') ;
  else
   this.imgPreload=set;
 },
//   end preLoad function   //


//   addToHandler   //
// co-ordinates what happens with a mouseover,moueout etc on trigger elements   //
addToHandler:function(obj, evt, func)
 {
  if(obj[evt])
  {
   obj[evt]=function(f,g)
   {
    return function()
    {
     f.apply(this,arguments);
     return g.apply(this,arguments);
    };
   }(func, obj[evt]);
  }
  else
   obj[evt]=func;
 }
//   end addToHandler function   // 

}
/** End of javascript **/