//====================================================
// Create a slideShow object for each slide show you
// want to have on the page.
//
// Constructor arguments:
//   Required:
//     Name of image from IMG tag
//     Delay (milliseconds)
//     True to autostart, false otherwise
//     "images"
//       List of image URLs
//   Optional:
//     "form"
//       Name of form from FORM tag
//       Prefix of form gadget names
//     "captions"
//       List of captions
//     "links"
//       List of link URLs
//     "popup"
//       String of popup window attributes such as:
//            "toolbar=no,location=no,directories=no," +
//              "status=yes,menubar=no,scrollbars=yes," +
//              "resizable=yes,width=500,height=400"
//     "startstop"
//       Start label
//       Stop label
//
// Each slideShow object has these methods:
//   Init() - Method to initialize
//   Start() - Method to start
//   Pause() - Method to pause
//   StartPause() - Method to start or pause
//   Faster() - Method to speed up
//   Slower() - Method to slow down
//   Change() - Method to change slide
//   Display() - Method to display next/prev slide
//   Next() - Method to display next slide
//   Prev() - Method to display prev slide
//   Link() - Display a link
//
// Each slideShow object has these properties:
//
//   ** bAllOk - true if no errors in slide show
//   ** bAuto - true to autostart
//   ** bRunning - true if slide show is running
//   ** sImg - Name in IMG tag
//   ** iDelay - Delay in milliseconds
//   ** iIndex - Index into goSlideShows[] array
//    * sForm - Name in FORM tag
//    * sGadget - Gadget prefix
//   ** sImages[] - Array of image URLs
//   ** iImages - Number of image URLs
//   ** sCaps[] - Array of captions
//   ** iCaps - Number of captions (might be zero)
//   ** sLinks[] - Array of link URLs
//   ** iLinks - Number of link URLs (might be zero)
//    * sPopup - Popup window options
//   ** iCurImg - Index of current image
//   ** oSlides[] - Array of preloaded images
//    * sStart - Label for start/stop button
//    * sStop - Label for start/stop button
//
//   ## bInit - true if page is fully loaded
//   ## oImg - Reference to image object
//    # oForm - Reference to form object
//    # oCap - Reference to caption textarea/text box
//    # oStartStop - Reference to start/stop button
//    # oDelay - Reference to delay text box
//
//   @@ iTimerId - setTimeout() timer ID
//
//   ** Required, created in constructor
//    * Optional, created in constructor
//   ## Required, created in Init() method
//    # Optional, created in Init() method
//   @@ Required, created in Change() method
//
// The goSlideShows[] array keeps track of the slideShow
// objects. It contains:
//   goSlideShows[n] - Array of slideShow objects
//   goSlideShows.Init() - Method to initialize
//     all slide shows (call from onload)
//====================================================


//====================================================
// AllSlideShowInit function
//    (goSlideShows.Init())
// Call this method from the <body> onload to
// initialize all of the slide shows on the page.
// It simply calls the Init() method of each of the
// slide shows.
//====================================================
function AllSlideShowInit ()
{
  // Copy goSlideShows reference so we can use a shorter name
  var xo = goSlideShows;

  // Initialize each slide show
  for (var xi = 0 ; xi < xo.length ; ++xi)
    if (xo[xi].bAllOk) xo[xi].Init ();
}

//====================================================
// slideShowInit() - Initialize slide show
//    (slideShow.Init())
//    Called by goSlideShows.Init()
// This function is called once for each slide show.
// It is called as a method, so "this" refers to
//   the slideShow object.
// The slideShow objects are created in the head
//   section, so the FORM tag had not been processed.
//   The constructor cannot verify that the form exists or
//   initialize things based on what the form
//   contains, so we do it now after the page has
//   finished loading.
//====================================================
function slideShowInit ()
{
  var xs;   // For temporary strings

  // bAllOk was true or we wouldn't have been called.
  // Change it to false - We'll change it back to true
  // if everything goes well...
  this.bAllOk = false;

  // Find the image object
  if (!document.images[this.sImg]) {
      alert ("Slide show image '" + this.sImg + "' does not exist");
      return;
  }
  // Save reference to image object
  this.oImg = document.images[this.sImg];

  //------------------------------------------------------
  // Form processing (if form fields specified)
  //------------------------------------------------------
  if (this.sForm)
  {
    // Find the form
    if (!document.forms[this.sForm]) {
      alert ("Slide show form '" + this.sForm + "' does not exist");
      return;
    }
    // Save reference to form object
    this.oForm = document.forms[this.sForm];

    // Initialize start/pause button
    // Name: sGadget + "Start"
    xs = this.sGadget + "Start";
    if (this.oForm[xs]) {    // If start button found
      this.oStartStop = this.oForm[xs];
      if (this.sStart) this.oStartStop.value = this.sStart;
    }

    // Initialize caption to caption of first image
    // Textarea/text box name: sGadget + "Caption"
    xs = this.sGadget + "Caption";
    if (this.oForm[xs] && this.iCaps > 0) {
      this.oCap = this.oForm[xs];       // Reference to textarea
      this.oCap.value = this.sCaps[0];  // Set 1st caption
    }

    // Initialize "delay" text box if there is one
    // Text box name: sGadget + "Delay"
    xs = this.sGadget + "Delay";
    if (this.oForm[xs]) {
      this.oDelay = this.oForm[xs];
      this.oDelay.value = this.iDelay / 1000;  // Seconds
    }
  }
  // End of form processing

  // Guess everything's OK!
  this.bInit = this.bAllOk = true;

  // Autostart if requested
  if (this.bAuto) {   // Autostart
    var xs = "goSlideShows[" + this.iIndex + "].Start();"
    this.iTimerId = setTimeout (xs, this.iDelay);
  }
}

//====================================================
// slideShow.Start() method - Start slide show
//====================================================
function slideShowStart ()
{
  // Return if slide show is already running
  if (this.bRunning) return;

  // For Netscape 2 and IE 3
  if (!document.images) {
    alert ("Sorry, your browser doesn't support this slide show.");
    return;
  }

  if (!this.bAllOk) {
    alert ("Sorry, there's something wrong with this slide show.");
    return;
  }

  if (!this.bInit) {
    alert ("Please try again after the page has completely loaded.");
    return;
  }

  // Start the slide show
  this.bRunning = true;
  if (this.oStartStop && this.sStop)  // Change label of start/stop button
    this.oStartStop.value = this.sStop;
  this.Change();       // Change to next slide
}

//====================================================
// slideShow.Pause() method
//====================================================
function slideShowPause ()
{
  // Return if the slide show is not running
  if (!this.bRunning) return;

  // Pause slide show
  clearTimeout (this.iTimerId);
  this.bRunning = false;
  if (this.oStartStop && this.sStart)  // Change label of start/stop button
    this.oStartStop.value = this.sStart;
}

//====================================================
// slideShow.StartPause() method
//
// If the slide show is running, pauses it.
// Otherwise, starts it.
//====================================================
function slideShowStartPause ()
{
  if (this.bRunning) this.Pause();
  else this.Start();
}

//====================================================
// slideShow.Faster() method
// Speeds up slide show by decreasing delay.
//====================================================
function slideShowFaster ()
{
  if (!this.bAllOk) return;  // If initialization errors

  // Update delay value
  if (this.iDelay > 1000)
    this.iDelay -= 1000;    // Subtract 1 second
  else
    this.iDelay -= 100;     // Subtract .1 second
  if (this.iDelay < 100)
    this.iDelay = 100;  // Must be .1 sec or higher

  // Display new delay value
  if (this.oDelay)
    this.oDelay.value = "" + (this.iDelay / 1000.0);
}
//====================================================
// slideShow.Slower() method
// Slows slide show by increasing delay.
//====================================================
function slideShowSlower ()
{
  if (!this.bAllOk) return; // If initialization errors

  // Update delay value
  if (this.iDelay < 1000)
    this.iDelay += 100;      // Add .1 second
  else
    this.iDelay += 1000;     // Add 1 second

  // Display new delay value
  if (this.oDelay)
    this.oDelay.value = "" + (this.iDelay / 1000.0);
}

//====================================================
// slideShow.Change() method
// Advances to next slide and sets new timeout
//====================================================
function slideShowChange ()
{
  // Just return if errors or if the slide show is paused
  if (!this.bAllOk || !this.bRunning) return;

  // Display next image
  this.Display (1);

  // Call setTimeout for next change
  var xs = "goSlideShows[" + this.iIndex + "].Change();"
  this.iTimerId = setTimeout (xs, this.iDelay);
}

//====================================================
// slideShow.Display() method
// Displays next or previous slide
// Argument: 1 to advance or -1 to back up
//====================================================
function slideShowDisplay (ziAddVal)
{
  // Select next image to display
  this.iCurImg += ziAddVal;   // Add/subtract 1
  if (this.iCurImg < 0) this.iCurImg = this.iImages - 1;
  this.iCurImg %= this.iImages;

  // Change the image
  this.oImg.src = this.oSlides[this.iCurImg].src;

  // Change the caption if we're doing captions
  if (this.oCap && this.iCaps > 0)
    this.oCap.value = this.sCaps[this.iCurImg];
}

//====================================================
// slideShow.Next() method
// Advances to next slide
//====================================================
function slideShowNext ()
{
  // Stop the slide show (go into manual mode)
  this.Pause();

  // Display next slide
  this.Display (1);
}

//====================================================
// slideShow.Prev() method
// Redisplay previous slide
//====================================================
function slideShowPrev ()
{
  // Stop the slide show (go into manual mode)
  this.Pause();

  // Display previous slide
  this.Display (-1);
}

//====================================================
// slideShow.Link() method
// Display a link URL
//
// Optional argument: "new" or frame name
//====================================================
function slideShowLink (zsTarget)
{
  // Ignore call if slide show has errors
  if (!this.bAllOk) return;

  // Get optional argument
  var xsTarget = "window";
  if (arguments.length >= 1) xsTarget = zsTarget;

  // Get URL for current image
  var xsUrl = "";
  if (this.iCurImg < this.iLinks)
    xsUrl = this.sLinks[this.iCurImg];
  if ("" == xsUrl) return;

  // If "new", open a new page
  if ("new" == xsTarget) {
    if (this.sPopup)
      var xoWin = window.open (xsUrl, "", this.sPopup);
    else
      var xoWin = window.open (xsUrl, "");
    xoWin.focus();
    return;
  }

  // Otherwise, open here
  eval (xsTarget + ".location.href = xsUrl");
}

//====================================================
// Constructor function for slideShow object
//   (See argument list above)
//====================================================
function slideShow (zsImg,     // Name in IMG tag
                    ziDelay,   // Delay, millisecs
                    zbAuto)    // True to autostart
{
  this.bAllOk = false;  // Will become true if all OK
  var xi;               // For loop counters

  // Methods
  this.Init = slideShowInit;
  this.Start = slideShowStart;
  this.Pause = slideShowPause;
  this.StartPause = slideShowStartPause;
  this.Faster = slideShowFaster;
  this.Slower = slideShowSlower;
  this.Change = slideShowChange;
  this.Display = slideShowDisplay;
  this.Next = slideShowNext;
  this.Prev = slideShowPrev;
  this.Link = slideShowLink;

  // Create goSlideShows array if 1st slide show
  if (!window.goSlideShows) {
    goSlideShows = new Array();
    goSlideShows.Init = AllSlideShowInit;
        // Init() method initializes all slide
        // shows on the page
  }

  // Add new slideShow to goSlideShows array
  this.iIndex = goSlideShows.length;
  goSlideShows[this.iIndex] = this;

  // Return if browser doesn't support image objects
  if (!document.images) return;

  // Examine arguments
  var xbArgsOk = true;  // Will become false if errors in arguments
  xiNumArgs = arguments.length;  // Number of arguments
  if (xiNumArgs >= 6 &&
      typeof zsImg  == "string" && zsImg != "" &&
      typeof ziDelay == "number" &&
      typeof zbAuto == "boolean")
  {
    this.sImg = zsImg;       // Name in IMG tag
    this.iDelay = ziDelay;   // Delay, milliseconds
    if (this.iDelay < 100) this.iDelay = 100;
    this.bAuto = zbAuto;     // Autostart flag
  } else {
    xbArgsOk = false;
  }

  var xsType = "";    // Type of arg being processed
  var xiArgIx = 3;    // Index of current argument
  var xsArg;          // Current argument
  this.sImages = new Array();    // For image URLs
  this.iImages = 0;              // Number of image URLs
  this.sCaps = new Array();      // For captions
  this.iCaps = 0;                // Number of captions
  this.sLinks = new Array();     // For link URLs
  this.iLinks = 0;               // Number of link URLs

  while (xbArgsOk && xiArgIx < xiNumArgs) {
    xsArg = arguments[xiArgIx++];  // Next argument
    if (typeof xsArg != "string") xbArgsOk = false;
    else {
      if (xsArg == "images" || xsArg == "captions" || xsArg == "links")
        xsType = xsArg;

      else if (xsArg == "form") {
        xsType = "";
        if (xiNumArgs < xiArgIx + 2 ||
            typeof arguments[xiArgIx] != "string" ||
            typeof arguments[xiArgIx+1] != "string" ||
            arguments[xiArgIx] == "" ||
            arguments[xiArgIx+1] == "")
        xbArgsOk = false;
        else {
          this.sForm = arguments[xiArgIx++];
          this.sGadget = arguments[xiArgIx++];
        }
      }

      else if (xsArg == "startstop") {
        xsType = "";
        if (xiNumArgs < xiArgIx + 2 ||
            typeof arguments[xiArgIx] != "string" ||
            typeof arguments[xiArgIx+1] != "string" ||
            arguments[xiArgIx] == "" ||
            arguments[xiArgIx+1] == "")
        xbArgsOk = false;
        else {
          this.sStart = arguments[xiArgIx++];
          this.sStop = arguments[xiArgIx++];
        }
      }

      else if (xsArg == "popup") {
        xsType = "";
        if (xiNumArgs < xiArgIx + 1 ||
            typeof arguments[xiArgIx] != "string")
        xbArgsOk = false;
        else this.sPopup = arguments[xiArgIx++];
      }

      // Not one of "images", "captions", ...
      else {
        if (xsType == "images") this.sImages[this.iImages++] = xsArg;
        else if (xsType == "captions") this.sCaps[this.iCaps++] = xsArg;
        else if (xsType == "links") this.sLinks[this.iLinks++] = xsArg;
        else xbArgsOk = false;
      }
    }
  }
  if (this.iImages < 2) xbArgsOk = false;   // Must have at least 2 images
  if (this.iCaps > 0) {
    while (this.iCaps < this.iImages)
      this.sCaps[this.iCaps++] = "No caption supplied";
  }
  if (this.iLinks > 0) {
    while (this.iLinks < this.iImages)
      this.sLinks[this.iLinks++] = "";
  }
  if (!xbArgsOk) {
    alert ("Incorrect arguments passed to\n" +
           "slideShow constructor");
    return;
  }

  // Build remaining properties
  this.iCurImg = 0;           // Image currently displayed

  // Preload images
  this.oSlides = new Array(); // Array of preloaded images
  for (xi = 0 ; xi < this.iImages ; ++xi) {
    this.oSlides[xi] = preloadImg (this.sImages[xi]);
  }

  // Everything is OK so far
  this.bAllOk = true;        // Everything's fine
  this.bRunning = false;     // Slide show is not yet running
}
