
/*** PopSlide (C)Stephen Chalmers

 Generates multiple automatic or manual controllable image slideshows, whose images can be clicked to display a titled enlargement in a popup div element or window.

 Info: http://scripterlative.com

 These instructions may be removed but not the above text.

 Please notify any suspected errors in this text or code, however minor.

* Popup divs can be customised by a stylesheet.
* Preserves image dimensions/aspect ratios.
* Provides optional Start, End, Pause, Next & Previous controls with direction changing.
* Automated Preloading.
* Very easy setup.

Installation
~~~~~~~~~~~~
Save this text/file as 'popslide.js' and copy it to a suitable folder of your website.

Within the <HEAD> section:

1) Insert these tags:

 <script type='text/javascript' src='popslide.js'></script>

(If popslide.js resides in a different folder, include the relative path)

2) Place the following example stylesheets either between <style> tags or include them in a css file.

a.popSlideLink:link,a.popSlideLink:visited{color:#f00;padding:2px;border:2px outset #888}
a.popSlideLink:hover{color:#000;background-color:#fff;border:2px inset #888}
.popSlideTitle{background-color:#bbb;color:#000;padding:10px}
.popSlideDiv{border:outset 4px #444;}

Configuration
~~~~~~~~~~~~~
In your HTML code, assign a NAME attribute to the image placeholder(s) that will display the
slideshow images.
Example: <img src='defaultpic.jpg' name='slideImg' .........>

Note: If the images are of varying sizes, the image placeholder mentioned above, should be placed
within a <div> whose dimensions are equal to or greater than the largest image.

The slideshow is initialised by a single function call to the PopSlide.show function.
In the <BODY> section, at a point below the target image placeholder(s), insert the following text:

<SCRIPT type='text/javascript'>

PopSlide.show('myShow1','slideImg', 4,

'thumb1.jpg', 'large1.jpg',
'thumb2.jpg', 'large2.jpg',
'thumb3.jpg', 'large3.jpg'
);

// Add more slideshows here if desired, providing a different name for each.
// Multiple slideshows can be specified to share the same target image holder.

</SCRIPT>

The parameters passed to PopSlide.show, must be replaced with your own values as explained next:

First parameter:
The name of the slideshow. This can be any unique name.

Second parameter:
The NAME attribute of the target image placeholder (not its ID if it has one)

Third parameter:
The period in seconds that each image displays in scan mode (Not in quotes).
If this value is 0, the slideshow will not scan by default, but can be started
using the Stop/Start button if provided.
If a manual-only slideshow is required, specify 0 and provide stepping controls as
detailed below. The same applies when only a single enlargeable image is being displayed.

All subsequent parameters are specified in groups of three: thumbnail image, large image, title.

There is no limit to the number of images that may be specified. 
If you do not want a slideshow, just specify one thumbnail/image pair in each function call, and set the period to 0.

All parameters must be separated by commas in the format shown.

There must be no comma following the last parameter.

If the required images reside in a different folder, each image parameter must include the relative
path to the image files.

Popup Type
~~~~~~~~~~
By default, div-based popups are used and recommended. To use window popups, add the following line within the <script> tags, BELOW the function call(s)

 PopSlide.useWindow=true;

-Popup Appearance- 

For authors with CSS knowledge, div-based popups can be styled using the stylesheet class names shown below.

.popSlideTitle{ Styles the spans that appear above and below the image }

.popSlideDiv{ Styles the div itself - typical use border,padding }

.popSlideLink{ A link pseudoclass that styles the 'close' link }  
 
-Controls-

Below is the code for slideshow control buttons consistent with the example above.
These controls are optional and not required for free-running slideshows.

<FORM>

 <input type='button' onclick='PopSlide.start("myShow1")'value='|<'>  <!-- Go to first image -->

 <input type='button' onclick='PopSlide.prev("myShow1")' value='<'>   <!-- Go to previous image/reverse scan -->

 <input type='button' onclick='PopSlide.next("myShow1")' value='>'>   <!-- Go to next image -->

 <input type='button' onclick='PopSlide.end("myShow1")'  value='>|'>  <!-- Go to last image -->

 <input type='button' onclick='this.value=(PopSlide.toggle("myShow1")?"Scan":"Stop")' value='Stop'>
 NOTE: If the slideshow defaults to manual mode (period specifed as a negative value), set the value of the
 above button to 'Scan' or whatever you prefer.

</FORM>

NOTE: The return value of PopSlide.toggle() can be used to toggle the text displayed by a toggle control, e.g.

<input type=button onclick='this.value=(PopSlide.toggle("anotherShow")?"Stop":"Scan")' value='Start'>

Equivalent controls in the form of hyperlinks.

<A HREF='#' onclick='return PopSlide.start("myShow1")'> |&lt; </A>
<A HREF='#' onclick='return PopSlide.prev("myShow1")'> &lt;Prev </A>
<A HREF='#' onclick='return PopSlide.next("myShow1")'> Next&gt; </A>
<A HREF='#' onclick='return PopSlide.end("myShow1")'> &gt;| </A>
<A HREF='#' onclick='PopSlide.toggle("myShow1");return false'> Stop/Scan </A>

Debugging
~~~~~~~~~
This script is very unlikely to conflict with others.
The most likely cause of errors will be incorrect/inconsistent naming of image placeholders, slideshows and images.
Ensure all necessary file paths are specified correctly.
Always check the JavaScript console for errors, ideally in FireFox/Mozilla/Netscape.
Ensure that your HTML is valid, at: http://validator.w3.org

GratuityWare
~~~~~~~~~~~~
This code is free for private non-commercial use. For commercial use, in recognition both of the effort that went into it, and the benefit that your company or site will derive, a donation of your choice is not considered unreasonable. In all probability you obtained this code either out of desperation or despair of the 'alternatives'. 'Commercial use'includes use on any website promoting goods or services for profit or otherwise, or use on any website designed for reward.

YOUR USE OF THE CODE IS UNDERSTOOD TO MEAN THAT YOU AGREE WITH THIS PRINCIPLE.

You may donate at www.scripterlative.com, stating the URL to which the donation applies.

** DO NOT EDIT BELOW THIS LINE **/

var PopSlide=/*2843295374657068656E204368616C6D657273*/
{
 imageSets:[], canCaption:false, direction:1,
 firstCall:true, winRef:0, mainDiv:null,
 x:0, y:0, lastSet:{pos:0,ref:null}, useWindow:!document.getElementById,

 show:function(showId, imgHolder, secs)
 {
  var set;

  if(this.firstCall)
  {
   this.firstCall=false;

   if( document.documentElement )
    this.dataCode=3;
   else
    if(document.body && typeof document.body.scrollTop!='undefined')
     this.dataCode=2;
    else
     if( typeof window.pageXOffset!='undefined' )
      this.dataCode=1;
  }

  var paramOffset=3, autoStart=(secs>0);

  if(typeof set=='undefined')
  {
   set=this.imageSets[showId]={};
   set.holder=imgHolder;
   set.smallImages=[];
   set.largeImages=[];

   set.pos=0;
   set.timer=null;
   set.showing=false;
   set.period=Math.max(Math.abs(secs),1);
   set.userPaused=false;
   
   for(var i=0,j=paramOffset; j<arguments.length; i++, j+=3)
   {
    set.smallImages[i]=new Image();
    set.smallImages[i].src=arguments[j];
    set.largeImages[i]=new Image();
    set.largeImages[i].src=arguments[j+1];
    set.largeImages[i].title=arguments[j+2];
   }

   if(autoStart)
    setTimeout("PopSlide.scan('"+showId+"')", secs*997);

   this.setImage(showId);
  }
  else
   alert('ID "'+showId+'" used more than once - please correct.');
 },

 popUpWin:function(showId)
 {
  if(this.winRef && this.winRef.closed==false)
   this.winRef.close();

  this.getDisplacement();

  var set=this.imageSets[showId], img=set.largeImages[set.pos], imgSrc=img.src;

  this.winRef=window.open('',img.title.replace(/\s/g,'_'),'titlebar=no,statusbar=no,width='+img.width+',height='+(img.height+50));

  this.winRef.moveTo(0,0);
  this.winRef.document.open();
  this.winRef.document.write('<html><head><title>'+img.title+'<\/title><style>body{margin:0;padding:0;text-align:center;font-weight:bold;color:#fff;background-color:#00f}a,a:visited{color:#fc0}<\/style><body onclose="opener.PopSlide.reset()">'+img.title+'<br><img src='+imgSrc+'><br><a href=# onclick="opener.PopSlide.reset();window.close();">Close</a><\/body><\/html>');
  this.winRef.document.close();
 },

 initPop:function(showId)
 {
  var set=this.imageSets[showId];

  if(this.lastSet.ref)
  {
   if( this.lastSet.ref==set )
   {
    if( this.lastSet.pos==set.pos )
     set.showing^=true;
    else
     set.showing=true;
   }
   else
    {
     this.lastSet.ref.showing=false;
     set.showing=true;
    }
  }
  else
   set.showing=true;

  if(set.showing)
   !this.useWindow ? this.popUp(showId) : this.popUpWin(showId);
  else
   if(!this.useWindow)
    this.removeDiv();
   else
    if(this.winRef && this.winRef.closed==false)
     this.winRef.close();
 

  this.lastSet.ref=set;
  this.lastSet.pos=set.pos;
 },

 popUp:function(showId)
 {
  var set=this.imageSets[showId], img=set.largeImages[set.pos], imgSrc=img.src;

  this.getDisplacement();

  if(this.mainDiv)
   this.removeDiv();

  this.mainDiv=document.createElement('div');

  var titleSpan=document.createElement('span'),
      footerSpan=document.createElement('span'),
      picHolder=document.createElement('img'),
      closeLink=document.createElement('a');

  this.mainDiv.style.width=picHolder.style.width=img.width+'px';
  this.mainDiv.style.position='absolute';
  this.mainDiv.style.top=this.y+'px';
  this.mainDiv.style.left=this.x+'px';
  this.mainDiv.className='popSlideDiv';
  
  titleSpan.appendChild(document.createTextNode(img.title)),

  footerSpan.style.fontWeight=titleSpan.style.fontWeight='bold';
  footerSpan.style.textAlign=titleSpan.style.textAlign='center';
  footerSpan.style.display=titleSpan.style.display='block';

  closeLink.href='#';
  closeLink.className='popSlideLink';
  closeLink.onclick=function(){PopSlide.removeDiv();PopSlide.reset();return false;}
  closeLink.appendChild(document.createTextNode('Close'));
  footerSpan.appendChild(closeLink);

  picHolder.src=imgSrc;
  this.mainDiv.appendChild(titleSpan);
  this.mainDiv.appendChild(picHolder);
  this.mainDiv.appendChild(footerSpan);
  document.body.appendChild(this.mainDiv);
  
  titleSpan.className='popSlideTitle';
  footerSpan.className='popSlideTitle';
 },

 reset:function()
 {
  if(this.lastSet.ref && this.lastSet.ref.showing )
  {
   this.lastSet.ref.showing=false;
   this.lastSet.pos=-1;
  }
 },
  
 removeDiv:function()
 {
  document.body.removeChild(this.mainDiv);
  this.mainDiv=null;
 },

 getDisplacement:function()
 {
  switch( this.dataCode )
  {
   case 3 : this.x = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
            this.y = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
            break;

   case 2 : this.x=document.body.scrollLeft;
            this.y=document.body.scrollTop;
            break;

   case 1 : this.x = window.pageXOffset; this.y=window.pageYOffset; break;
  }
 },

 setImage:function(showId)
 {
   var set=this.imageSets[showId], holder=document.images[set.holder],
       img=set.smallImages[set.pos];

   if(typeof img.width=='number' && img.width>0)
   {
    holder.width=img.width;
    holder.height=img.height;
   }

   holder.src=set.smallImages[set.pos].src;
   holder.title=holder.alt=set.largeImages[set.pos].title;
   holder.onclick=new Function("PopSlide.initPop('"+showId+"')");
   holder.onmouseover=new Function("PopSlide.imageSets['"+showId+"'].userPaused=true");
   holder.onmouseout=new Function("PopSlide.imageSets['"+showId+"'].userPaused=false");
 },

 toggle:function(showId)
 {
  var set=this.imageSets[showId];

  set.timer==null?PopSlide.scan(showId):PopSlide.stop(showId);

  return set.timer==null?false:true;
 },

 scan:function(showId)
 {
  var set=this.imageSets[showId];

  set.scanning=true;

  if(!set.showing && !set.userPaused)
   this.direction==1?this.next(showId):this.prev(showId);

  if(set.timer==null)
   set.timer=setInterval("PopSlide.scan('"+showId+"')", set.period*1000);

  return false;
 },

 stop:function(showId)
 {
  clearTimeout( this.imageSets[showId].timer );
  this.imageSets[showId].scanning=false;
  this.imageSets[showId].timer=null;
 },

 next:function(showId)
 {
  var set=this.imageSets[showId];

  this.direction=1;

  if(set.pos<set.smallImages.length-1)
   set.pos+=this.direction;
  else
   set.pos=0;

  this.setImage(showId);

  return false;
 },

 prev:function(showId)
 {
  var set=this.imageSets[showId];

  this.direction=-1;

  if(set.pos>0)
   set.pos+=this.direction;
  else
   set.pos=set.smallImages.length-1;

  this.setImage(showId);

  return false;
 },

 start:function(showId)
 {
  var set=this.imageSets[showId];

  set.pos=0;
  this.setImage(showId);

  return false;
 },

 end:function(showId)
 {
  var set=this.imageSets[showId];

  set.pos=set.smallImages.length-1;
  this.setImage(showId);

  return false;
 },

 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;
 }
 
}
