//PMGR SLIDE SHOW JAVASCRIPT version 2010-04-13
//built to incorporates variable-width autosizing; see "this.forceWidth"
//correction in imagechange function for HREF (use this.hrefs, not this.originals)

//Programmed by Jim Ahrend/Falcorweb
//transitions based on brothercake transitions (adapted, and incorporated into slideshow object)

function slideshow() {//constructor - slideshow object

//  these vars should be reset in pms templates config file, or db vars
this.self = ""; //REQUIRED when new object is declare---required for timeout function in start function below
this.viewerImageId = "";
this.viewerLinkId = "";
this.captionDivId = "";
this.descriptionDivId = "";
this.thumbDivIdPrefix = "";
this.thumbClassNameActive = "";
this.thumbClassNameInactive = "";

//NEW---for auto-size feature
this.forceWidth = 0;//sizes new image in transitions

//   defaults, inits
this.running = 0;
this.loop = 0;
this.slideCounter = 0;
this.allCached = 0;

//   init data arrays - completed when show is fetched - see templates/pmss/final
this.images = [];
this.transitions = [];
this.durations = [];
this.delays = [];
this.captions = [];
this.descriptions = [];
this.titles = [];
this.originals = [];
this.hrefs = [];

//   util for preloading
this.imgCache = [];

//   util for changing thumb div outline
this.divsArray = document.getElementsByTagName('div');

//   transitions vars
this.clock = null;
this.count = 1;

}//end slideshow constructor


// /////////////////////////// SLIDESHOW OBJECT FUNCTIONS ///////////////////////////////

slideshow.prototype.addImage = function(imgSrc,imgTransition,imgDuration,imgDelay,imgCaption,imgDescription,imgTitle,imgOriginal,imgHref) {
   //DEFAULTS
   imgTransition = (typeof imgTransition  == "undefined") ? "crossfade" : imgTransition;
   imgDuration   = (typeof imgDuration    == "undefined") ? 2 : imgDuration;
   imgDelay      = (typeof imgDelay       == "undefined") ? 4 : imgDelay;
   imgCaption    = (typeof imgCaption     == "undefined") ? " " : imgCaption;
   imgDescription= (typeof imgDescription == "undefined") ? " " : imgDescription;
   imgTitle         = (typeof imgTitle    == "undefined") ? imgCaption : imgTitle;//caption = default for viewer link hover
   imgOriginal      = (typeof imgOriginal == "undefined") ? imgSrc : imgOriginal; //defaults to img source
   imgHref          = (typeof imgHref == "undefined" || imgHref == "original") ? 
      imgOriginal : imgHref; //viewer link defaults to original image, or is set with text: "original"
   if(imgDelay<imgDuration)  imgDelay = imgDuration; //safety

   //add to arrays
   this.images.push(imgSrc);
   this.transitions.push(imgTransition);
   this.durations.push(imgDuration);
   this.delays.push(imgDelay);
   this.captions.push(imgCaption);
   this.descriptions.push(imgDescription);
   this.titles.push(imgTitle);
   this.originals.push(imgOriginal);
   this.hrefs.push(imgHref);

   //PRE-LOAD FIRST 3 IMAGES
   if(this.images.length <4 ) {
      preload = new Image;
      preload.src = imgSrc;
      this.imgCache.push(preload);
      }
   }

slideshow.prototype.cacheAll = function() {//PRE-LOADS from slide 4 on...
   //REPLACED BY cacheProg (loads 5 at a time)
   if(this.allCached > 0) return;
   if(this.images.length > 3 && this.images.length > this.imgCache.length ) {
      var imagesLen = this.images.length;
      var imgPath;
      var preload;
      for(i=3;i<imagesLen;i++) {
         preload = new Image;
         preload.src = (this.images[i]); //pre-load into cache
         this.imgCache.push(preload);
         }
      this.allCached = 1;
      }
   }

slideshow.prototype.cacheProg = function() {//PRE-LOADS 5 at a time (till done)
   if(this.allCached == 0) {
      var imCaLen = this.imgCache.length;
      var imLen = this.images.length;
      var imThru = (imCaLen + 5 > imLen) ? imLen : imCaLen + 5;
      if(imLen > 3 && imLen > imCaLen ) {
         var preload;
         for(i=imCaLen;i<imThru;i++) {
            preload = new Image;
            preload.src = (this.images[i]); //pre-load into cache
            this.imgCache.push(preload);
            }//end for
         this.allCached = (this.imgCache.length == this.images.length) ? 1 : 0;
         }//end if imLen>3
      }//end if allCached == 0
   }

slideshow.prototype.imageChange = function(slideNo) {
   if(slideNo>this.images.length) { alert ("Slide number exceeded slide quantity."); return; } //safety
   if(!document.getElementById(this.viewerImageId)) { alert (this.viewerImageId); return; } //safety
   this.cacheProg();
   var duration = this.durations[slideNo];
   var transition = this.transitions[slideNo];   

   //VIEWER
   if(transition.indexOf("crosswipe")>-1) {//NEW IMAGE - CROSSWIPE
      var direction = transition.substring(10);
      this.crosswipe(document.getElementById(this.viewerImageId),this.images[slideNo],duration,direction,"Slide #"+slideNo);
      }
      else { //NEW IMAGE - CROSSFADE (default)
      this.crossfade(document.getElementById(this.viewerImageId),this.images[slideNo],duration,"Slide #"+slideNo);
      }

   //NEW LINK TITLE (on hover)
   if(typeof this.titles[slideNo] == "string" && this.titles[slideNo] != "" && document.getElementById(this.viewerLinkId))
      document.getElementById(this.viewerLinkId).title = this.titles[slideNo];
   //NEW HREF
   if(typeof this.hrefs[slideNo] == "string" && this.hrefs[slideNo] != "" && document.getElementById(this.viewerLinkId))
      document.getElementById(this.viewerLinkId).href = this.hrefs[slideNo];
   //NEW CAPTION
   if(typeof this.captions[slideNo] == "string" && this.captions[slideNo] != "" && document.getElementById(this.captionDivId))
      document.getElementById(this.captionDivId).innerHTML = this.captions[slideNo];
   //NEW DESCRIPTION
   if(typeof this.descriptions[slideNo] == "string" && this.descriptions[slideNo] != "" && document.getElementById(this.descriptionDivId))
      document.getElementById(this.descriptionDivId).innerHTML = this.descriptions[slideNo];
   //CHANGE CLASS ON ACTIVE (now showing) THUMB DIV
   if(document.getElementById(this.thumbDivIdPrefix+slideNo)) {//if thumb div exists...
      var divArrLen = this.divsArray.length;
      for(d=0;d<divArrLen;d++){//loop over ALL divs
         if(this.divsArray[d].id.indexOf(this.thumbDivIdPrefix)==0){//filter only THUMB divs
            this.divsArray[d].className = (this.divsArray[d].id == this.thumbDivIdPrefix+slideNo) ? 
               this.thumbClassNameActive : this.thumbClassNameInactive ;
            }//end if
         }//end for
        
      }//end if thumb div exists

   }//end image change function

slideshow.prototype.advanceCounter = function() {
   this.slideCounter =  ( this.slideCounter+1 < this.images.length) ?  
      this.slideCounter + 1 : ( (this.loop==0)  ? -1 : 0 ) ;
   }

slideshow.prototype.previousSlideNo = function() {
   return (this.slideCounter-1 <0 ) ? 0 : this.slideCounter-1;
   }

slideshow.prototype.lastSlideNo = function() {
   return this.images.length-1;
   }

slideshow.prototype.start = function() {  //START
   if (typeof this.pmsstimer != "undefined")
      clearTimeout(this.pmsstimer);//keeps multiple timers from running
   this.advanceCounter();
   if(this.slideCounter > -1) {
      this.running = 1;
      this.imageChange(this.slideCounter);
         this.pmsstimer = setTimeout(this.self+".start()",this.delays[this.slideCounter]*1000);
      }
      else this.stop();
      return true;
   }

slideshow.prototype.stop = function(reset) { //STOP use 1; PAUSE use 0
   //reset counter (full stop only)
   if(reset > 0){
      this.slideCounter = -1;
      //change class on active thumb div (as in imageChange function)
      if(document.getElementById(this.thumbDivIdPrefix+"0")) {//if thumb div exists...
         var divArrLen = this.divsArray.length;
         for(d=0;d<divArrLen;d++){//loop over ALL divs
            if(this.divsArray[d].id.indexOf(this.thumbDivIdPrefix)==0){//filter only THUMB divs
               this.divsArray[d].className = (this.divsArray[d].id == this.thumbDivIdPrefix+"0") ? 
                  this.thumbClassNameActive : this.thumbClassNameInactive ;
               }//end if
            }//end for
         }//end if thumb div exists
      }//end if reset>0
   //Stop timer
   if (typeof this.pmsstimer != "undefined"){
      clearTimeout(this.pmsstimer);
      this.running = 0;
      }
   }

slideshow.prototype.pause = function() {  //TEMPORARY PAUSE (ie. onmouseover)
   if (typeof this.pmsstimer != "undefined" && this.running == 1)
      clearTimeout(this.pmsstimer);
   }
   
slideshow.prototype.resume = function() {  //RESUME (ie. onmouseout)
   if(this.running == 1)
      this.start();
   }

slideshow.prototype.goto = function(slno) {
   if (typeof this.pmsstimer != "undefined"){
      clearTimeout(this.pmsstimer);
      this.running = 0;
      }
   this.imageChange(slno);
   this.slideCounter = slno;//resets counter to this slidenumber
   }

slideshow.prototype.first = function() { 
   this.goto(0); 
   }

slideshow.prototype.last = function() { 
   this.goto(this.images.length-1); 
   }

slideshow.prototype.next = function() { 
   this.advanceCounter();
   this.goto(this.slideCounter); 
   }

slideshow.prototype.prev = function() { 
   if(this.slideCounter>0) this.slideCounter--; 
   this.goto(this.slideCounter); 
   }

slideshow.prototype.autostartOnload = function(objname) {
   if (window.onload)
      oldload = window.onload;
   window.onload = function() {
      oldload();
      eval(objname).autostart();
      }
   }

slideshow.prototype.autostart = function() {
   if(this.running == 0 && this.slideCounter == 0)
   setTimeout(this.self+".start()",this.delays[this.slideCounter]*1000);
   }

// /////////////////////////////////// TRANSITIONS /////////////////////////////////////////

// ///////////////////////////////// CROSSFADE //////////////////////////////////////////

slideshow.prototype.crossfade = function()
{
	//if the timer is not already going
	if(this.clock == null)
	{
		//copy the image object 
		this.obj = arguments[0];
		
		//copy the image src argument 
		this.src = arguments[1];
		
		//store the supported form of opacity
		if(typeof this.obj.style.opacity != 'undefined')
		{
			this.type = 'w3c';
		}
		else if(typeof this.obj.style.MozOpacity != 'undefined')
		{
			this.type = 'moz';
		}
		else if(typeof this.obj.style.KhtmlOpacity != 'undefined')
		{
			this.type = 'khtml';
		}
		else if(typeof this.obj.filters == 'object')
		{
			//weed out win/ie5.0 by testing the length of the filters collection (where filters is an object with no data)
			//then weed out mac/ie5 by testing first the existence of the alpha object (to prevent errors in win/ie5.0)
			//then the returned value type, which should be a number, but in mac/ie5 is an empty string
			this.type = (this.obj.filters.length > 0 && typeof this.obj.filters.alpha == 'object' && typeof this.obj.filters.alpha.opacity == 'number') ? 'ie' : 'none';
		}
		else
		{
			this.type = 'none';
		}
		
		//change the image alt text if defined
		if(typeof arguments[3] != 'undefined' && arguments[3] != '')
		{
			this.obj.alt = arguments[3];
		}
		
		//if any kind of opacity is supported
		if(this.type != 'none')
		{
			//create a new image object and append it to body
			//detecting support for namespaced element creation, in case we're in the XML DOM
			this.newimg = document.getElementsByTagName('body')[0].appendChild((typeof document.createElementNS != 'undefined') ? document.createElementNS('http://www.w3.org/1999/xhtml', 'img') : document.createElement('img'));

			//set positioning classname
			//this.newimg.className = 'idupe';

//REPLACED 3-1-10 with inline style
this.newimg.style.position = 'absolute';
this.newimg.style.visibility = 'hidden';
//NEW---version 20100413
if(this.forceWidth > 0)
   this.newimg.style.width = this.forceWidth + "px";


			//set src to new image src
			this.newimg.src = this.src

			//move it to superimpose original image
			this.newimg.style.left = this.getRealPosition(this.obj, 'x') + 'px';
			this.newimg.style.top = this.getRealPosition(this.obj, 'y') + 'px';
			
			//copy and convert fade duration argument 
			this.length = parseInt(arguments[2], 10) * 1000;
			
			//create fade resolution argument as 20 steps per transition
			this.resolution = parseInt(arguments[2], 10) * 20;
			
			//start the timer
			this.clock = setInterval(this.self+'.crossfadetimer()', this.length/this.resolution);
		}
		
		//otherwise if opacity is not supported
		else
		{
			//just do the image swap
			this.obj.src = this.src;
		}
		
	}
};


//crossfade timer function
slideshow.prototype.crossfadetimer = function()
{
	//decrease the counter on a linear scale
	this.count -= (1 / this.resolution);
	
	//if the counter has reached the bottom
	if(this.count < (1 / this.resolution))
	{
		//clear the timer
		clearInterval(this.clock);
		this.clock = null;
		
		//reset the counter
		this.count = 1;
		
		//set the original image to the src of the new image
		this.obj.src = this.src;
	}
	
	//set new opacity value on both elements
	//using whatever method is supported
	switch(this.type)
	{
		case 'ie' :
			this.obj.filters.alpha.opacity = this.count * 100;
                        //this.obj.filters.alpha.opacity = (this.count == 1 ? 0.9999999 : this.count) * 100;
			this.newimg.filters.alpha.opacity = (1 - this.count) * 100;
			break;
			
		case 'khtml' :
			this.obj.style.KhtmlOpacity = this.count;
			this.newimg.style.KhtmlOpacity = (1 - this.count);
			break;
			
		case 'moz' : 
			//restrict max opacity to prevent a visual popping effect in firefox
			this.obj.style.MozOpacity = (this.count == 1 ? 0.9999999 : this.count);
			this.newimg.style.MozOpacity = (1 - this.count);
			break;
			
		default : 
			//restrict max opacity to prevent a visual popping effect in firefox
			this.obj.style.opacity = (this.count == 1 ? 0.9999999 : this.count);
			this.newimg.style.opacity = (1 - this.count);
	}
	
	//now that we've gone through one fade iteration 
	//we can show the image that's fading in
	this.newimg.style.visibility = 'visible';
	
	//keep new image in position with original image
	//in case text size changes mid transition or something
	this.newimg.style.left = this.getRealPosition(this.obj, 'x') + 'px';
	this.newimg.style.top = this.getRealPosition(this.obj, 'y') + 'px';
	
	//if the counter is at the top, which is just after the timer has finished
	if(this.count == 1)
	{
		//remove the duplicate image
		this.newimg.parentNode.removeChild(this.newimg);
	}
};



//get real position method
slideshow.prototype.getRealPosition = function()
{
	this.pos = (arguments[1] == 'x') ? arguments[0].offsetLeft : arguments[0].offsetTop;
	this.tmp = arguments[0].offsetParent;
	while(this.tmp != null)
	{
		this.pos += (arguments[1] == 'x') ? this.tmp.offsetLeft : this.tmp.offsetTop;
		this.tmp = this.tmp.offsetParent;
	}
	
	return this.pos;
};


// //////////////////////////////////// CROSSWIPE ///////////////////////////////////////

slideshow.prototype.crosswipe = function ()
{
	//if the timer is not already going
	if(this.clock == null)
	{
		//copy the image object 
		this.obj = arguments[0];
		
		//get its dimensions
		this.size = { 'w' : this.obj.width, 'h' : this.obj.height };
		
		//copy the image src argument 
		this.src = arguments[1];
		
		//change the image alt text if defined
		if(typeof arguments[4] != 'undefined' && arguments[4] != '')
		{
			this.obj.alt = arguments[4];
		}

		//if dynamic element creation is supported
		if(typeof document.createElementNS != 'undefined' || typeof document.createElement != 'undefined')
		{
			//create a new image object and append it to body
			//detecting support for namespaced element creation, in case we're in the XML DOM
			this.newimg = document.getElementsByTagName('body')[0].appendChild((typeof document.createElementNS != 'undefined') ? document.createElementNS('http://www.w3.org/1999/xhtml', 'img') : document.createElement('img'));

			//set positioning classname
			//this.newimg.className = 'idupe';

//REPLACED 3-1-10 with inline style
this.newimg.style.position = 'absolute';
this.newimg.style.visibility = 'hidden';
//NEW---version 20100413
if(this.forceWidth > 0)
   this.newimg.style.width = this.forceWidth + "px";

			//set src to new image src
			this.newimg.src = this.src

			//move it to superimpose original image
			this.newimg.style.left = this.getRealPosition(this.obj, 'x') + 'px';
			this.newimg.style.top = this.getRealPosition(this.obj, 'y') + 'px';

			//set it to be completely hidden with clip
			this.newimg.style.clip = 'rect(0, 0, 0, 0)';

			//show the image 
			this.newimg.style.visibility = 'visible';

			//copy and convert fade duration argument 
			this.length = parseInt(arguments[2], 10) * 1000;

			//create fade resolution argument as 20 steps per transition
			this.resolution = parseInt(arguments[2], 10) * 20;

			//copy slide direction argument
			this.dir = arguments[3];

			//start the timer
			this.clock = setInterval(this.self+'.crosswipetimer()', this.length/this.resolution);
		}
		
		//otherwise if dynamic element creation is not supported
		else
		{
			//just do the image swap
			this.obj.src = this.src;
		}
		
	}
};


//crosswipe timer function
slideshow.prototype.crosswipetimer = function()
{
	//decrease the counter on a linear scale
	this.count -= (1 / this.resolution);
	
	//if the counter has reached the bottom
	if(this.count < (1 / this.resolution))
	{
		//clear the timer
		clearInterval(this.clock);
		this.clock = null;
		
		//reset the counter
		this.count = 1;
		
		//set the original image to the src of the new image
		this.obj.src = this.src;
	}
	
	//animate the clip of the new image
	//using the width and height properties we saved earlier
	this.newimg.style.clip = 'rect('
		+ ( (/bt|bltr|brtl/.test(this.dir)) ? (this.size.h * this.count) : (/che|cc/.test(this.dir)) ? ((this.size.h * this.count) / 2) : (0) )
		+ 'px, '
		+ ( (/lr|tlbr|bltr/.test(this.dir)) ? (this.size.w - (this.size.w * this.count)) : (/cve|cc/.test(this.dir)) ? (this.size.w - ((this.size.w * this.count) / 2)) : (this.size.w) )
		+ 'px, '
		+ ( (/tb|tlbr|trbl/.test(this.dir)) ? (this.size.h - (this.size.h * this.count)) : (/che|cc/.test(this.dir)) ? (this.size.h - ((this.size.h * this.count) / 2)) : (this.size.h) )
		+ 'px, '
		+ ( (/lr|tlbr|bltr/.test(this.dir)) ? (0) : (/tb|bt|che/.test(this.dir)) ? (0) : (/cve|cc/.test(this.dir)) ? ((this.size.w * this.count) / 2) : (this.size.w * this.count) ) 
		+ 'px)';
			
	//keep new image in position with original image
	//in case text size changes mid transition or something
	this.newimg.style.left = this.getRealPosition(this.obj, 'x') + 'px';
	this.newimg.style.top = this.getRealPosition(this.obj, 'y') + 'px';
	
	//if the counter is at the top, which is just after the timer has finished
	if(this.count == 1)
	{
		//remove the duplicate image
		this.newimg.parentNode.removeChild(this.newimg);
	}
};

