//======================================================================
// JavaScript for object movies.
// Copyright 2000-2001, John Strait.
// You may use it as you wish -- just retain this notice.
// If you use this script on your own website, I would like you to add
// a link to The Panorama Factory website.
//----------------------------------------------------------------------
//
// For each object movie you must create a set of images of your object.
// Use a turntable and tripod to make the set of photographs spaced
// equally around 360 degrees.  The images must be in clockwise order.
//
// All image files must be the same size (width by height) and you
// must name the files in a systematic way so that they are numbered
// starting at 0.  For example, komodo/k0.jpg, komodo/k1.jpg, etc.
// The file names are generated by joining a "head" (komodo/k) with
// the image number and a "tail" (.jpg).
//
// You should create an additional image file that will be displayed
// while the script is loading the object images.  This image must
// have the same size as the object images.
//
//
// To embed this script in your html page:
//
// 1. Put the file PFObj.js in the same directory as your html file.
//
// 2. Insert this into your html file right before the body tag:
//      <script language="JavaScript" src="PFObj.js"></script>
//
// 3. Modify the body tag to add:
//      onload="PFObjInit()"
//
// 4. Include an html img tag where you want each object movie to appear.
//    Customize the values marked with ** in the html img tag.
//
//    <img src="komodo/loading.gif"     ** displayed while loading the images
//      name="komodo"                   ** must be unique on this page
//      alt="move your mouse in circles around Komodo"  ** tool tip text
//      onload="PFObj(...               ** SEE BELOW
//      WIDTH="224"                     ** image width
//      HEIGHT="165">                   ** image height
//
// 5. The onload=PFObj(... is used to setup the object movie.  PFObj has
//    9 parameters, 4 required and 5 optional:
//      PFObj(image, head, tail, count, initial,
//                      autorotate, mousecontrol, xcenter, ycenter);
//    Where:
//      image        The Image object (identified by the name= value of the
//                   img tag).  It must have a unique name property.
//                      Required parameter.
//      head         First part of image file name.
//                      Required parameter.
//      tail         Last part of image file name.
//                      Required parameter.
//      count        Number of images.  Use a positive number if the images
//                   were captured in clockwise order and a negative number
//                   if they were captured in counter-clockwise order.
//                      Required parameter.
//      initial      Initial file number.
//                      Default if omitted = 0.
//      autorotate   Auto-rotation frame rate in milliseconds.  >0 for
//                   clockwise, <0 for counter-clockwise, =0 for no rotation.
//                      Default if omitted = 0.
//      mousecontrol 0  Move the mouse in circles around the object (relative)
//                   1  Move the mouse in circles around the object (absolute)
//                   2  Move the mouse left and right (relative)
//                   3  Move the mouse left and right (absolute)
//                   4  Move the mouse up and down across the image (absolute)
//                   5  Move the mouse up and down across the image (absolute)
//                  -1  Disable the mouse.
//                      Default if omitted = 0.
//      xcenter      Rotation center of image expressed as a fraction of
//                   image width.  For example, 0.5 puts rotation center
//                   in the middle and 0.3 puts it a little to the left.
//                      Default if omitted = 0.5.
//      ycenter      Rotation center of image expressed as a fraction of
//                   image height.  For example, 0.5 puts rotation center
//                   in the middle and 0.7 puts it a little below the middle.
//                      Default if omitted = 0.5.
//    For example:
//      onload="PFObj(document.komodo, 'komodo/k', '.jpg', 40, 3, 200, 2)"
//    Or:
//      onload="PFObj(teapot, 'teapot/t', '.jpg', 37)"
//----------------------------------------------------------------------
//
// Modification history.
//
// 5.7.2001     J Strait.
// Try again to fix the problem with IE 5.0 that prevented the page from
// working the second time you visit it.
//
// 5.5.2001     J Strait.
// Fix problem with IE 5.0 that prevented the page from working the second
// time you visit it.
//
// 5.2.2001     J Strait.
// Major rewrite.
// 1. Converted to a .js file so that the JavaScript doesn't need to be
//    embedded in the .html file.
// 2. Simplified the parameters that need to be added to the img tag.
// 3. Added mousecontrol parameter to the PFObj function.
// 4. Added xcenter and ycenter parameters to the PFObj function.
// 5. Protected global names by prefixing with PF or PFObj.
// 6. Corrected problems with Netscape 6.
// 7. Corrected problems with scrolling.
// 8. Corrected problems with window resizing.
//======================================================================


//======================================================================
// User-callable functions.
//======================================================================


function PFObj(image, head, tail, count, initial,
                        autorotate, mousecontrol, xcenter, ycenter)
//----------------------------------------------------------------------
// Create a new object movie animation.
//
// See file header comments for parameter descriptions.
//----------------------------------------------------------------------
{
  if (!document.PFObjMovies[image.name]) {
    if (!initial) initial = 0;
    if (!autorotate) autorotate = 0;
    if (!mousecontrol) mousecontrol = 0;
    if (!xcenter) xcenter = 0.5;
    if (!ycenter) ycenter = 0.5;
    new PFObjMovie(image, head, tail, count, initial,
                        autorotate, mousecontrol, xcenter, ycenter);
    PFObjShow();
  }
}


function PFObjMouseControl(image, mousecontrol)
//----------------------------------------------------------------------
// Change mousecontrol.
//
// image        The Image object.  It must have a unique name property.
// mousecontrol Mouse control option.
//----------------------------------------------------------------------
{
  var t;

  t = document.PFObjMovies[image.name];
  if (t) {
    t.mousecontrol = mousecontrol;
  }
}


function PFObjAutoRotate(image, autorotate)
//----------------------------------------------------------------------
// Start autorotation.
//
// image        The Image object.  It must have a unique name property.
// autorotate   Auto-rotation frame rate in milliseconds.  >0 for
//              clockwise, <0 for counter clockwise, =0 for no rotation.  
//----------------------------------------------------------------------
{
  var t;

  t = document.PFObjMovies[image.name];
  if (t) {
    if (t.running) {
      clearInterval(t.intervalcode);
      t.running = false;
    }
    if (autorotate != 0) {
      t.running = true;
      if (autorotate > 0) {
        t.intervalcode = setInterval("PFObjAuto('" +  image.name + "', 1)", autorotate);
      } else {
        t.intervalcode = setInterval("PFObjAuto('" +  image.name + "', -1)", -autorotate);
      }
    }
  }
}


//======================================================================
// Private functions.
//======================================================================


var PFisNav = false;
var PFisNav6 = false;
var PFisIE = false;
var PFshowing = false;

document.PFObjMovies = new Array(); // array of object movie Images


// Figure out which browser is running.

if ((navigator.appName.indexOf("Netscape") != -1) &&
    (parseInt(navigator.appVersion) >= 4)) {
  PFisNav = true;
  PFisNav6 = parseInt(navigator.appVersion) >= 5;
} else if ((navigator.appName.indexOf("Microsoft") != -1) &&
           (parseInt(navigator.appVersion) >= 4)) {
  PFisIE = true;
} else {
}


function PFObjMovie(image, head, tail, count, initial,
                        autorotate, mousecontrol, xcenter, ycenter)
//----------------------------------------------------------------------
// Construct a new object movie animation.
// 1. Set up event handling (for Navigator).
// 2. Find center of image for mouse tracking.
// 3. Load all the images into a local array so that animation is zippy.
//
// See file header comments for parameter descriptions.
//----------------------------------------------------------------------
{
  var p;
  var i;
  var clockwise;

  if ((count != 0) && (PFisNav || PFisIE)) {
    document.PFObjMovies[image.name] = this;
    this.image = image;
    this.oimages = new Array();
    if (count > 0) {
      this.count = count;
      clockwise = true;
    } else {
      this.count = -count;
      clockwise = false;
    }
    this.current = initial;
    this.istart = initial;
    this.xstart = 0;
    this.astart = 0;
    this.moving = false;
    this.loading = true;
    this.autorotate = autorotate;
    this.mousecontrol = mousecontrol;
    this.running = false;
    if ((this.mousecontrol & 6) == 0) {
      this.xcenter = xcenter;
      this.ycenter = ycenter;
    } else {
      this.xcenter = 0;   // force origin to corner
      this.ycenter = 0;   // force origin to corner
    }
  }

  if (PFisNav || PFisIE) {
    // Load all the images into a local array so that animation is zippy.

    if (clockwise) {
      for (i = 0; i < this.count; i++) {
        this.oimages[i] = new Image();
        this.oimages[i].src = head + i + tail;
        this.oimages[i].onload = PFObjShow;
      }
    } else {
      for (i = 0; i < this.count; i++) {
        this.oimages[i] = new Image();
        this.oimages[i].src = head + (this.count - 1 - i) + tail;
        this.oimages[i].onload = PFObjShow;
      }
    }
  }
}


function PFObjSetupXYWH(t)
//----------------------------------------------------------------------
// Setup x, y, w, h for an object movie.
//
// t            The object movie.
//----------------------------------------------------------------------
{
  if (PFisIE) {

    // Find origin and size of image.

    t.x = t.xcenter * t.image.offsetWidth;
    t.y = t.ycenter * t.image.offsetHeight;
    t.w = t.image.offsetWidth;
    t.h = t.image.offsetHeight;
  } else if (PFisNav6) {

    // Find origin and size of image.

    t.x = t.image.offsetLeft + t.xcenter * t.image.offsetWidth;
    t.y = t.image.offsetTop + t.ycenter * t.image.offsetHeight;
    t.w = t.image.offsetWidth;
    t.h = t.image.offsetHeight;
  } else if (PFisNav) {

    // Find origin and size of image.

    t.x = t.image.x + t.xcenter * t.image.width;
    t.y = t.image.y + t.ycenter * t.image.height;
    t.w = t.image.width;
    t.h = t.image.height;
  }
}

function PFObjShow()
//----------------------------------------------------------------------
// Show the current image if all images have been loaded.  Otherwise
// schedule another call to PFObjShow() on a timer event. 
//----------------------------------------------------------------------
{
  var name;
  var t;

  for (name in document.PFObjMovies) {
    t = document.PFObjMovies[name];
    if (t.loading) {
      t.loading = false;
      var n = 0;
      var i;
      for (i = 0; i < t.count; i++) {
        if (!t.oimages) t.loading = true;
        else if (!t.oimages[i]) t.loading = true;
        else if (!t.oimages[i].complete) t.loading = true;
        else n++;
      }
    }
    if (!t.loading) {
      t.image.src = t.oimages[t.current].src;
      if ((t.autorotate != 0) && !t.running) {
        t.running = true;
        if (t.autorotate > 0) {
          t.intervalcode = setInterval("PFObjAuto('" +  name + "', 1)", t.autorotate);
        } else {
          t.intervalcode = setInterval("PFObjAuto('" +  name + "', -1)", -t.autorotate);
        }
        t.autorotate = 0;
      }
    } else {
      setTimeout("PFObjShow()", 1000);  // in case .onload = PFObjShow doesn't work (IE)
    }
  }
}


function PFObjAuto(name, step)
//----------------------------------------------------------------------
// Show the next image in auto rotate mode. 
//----------------------------------------------------------------------
{
  var t;

  t = document.PFObjMovies[name];
  t.current += step;
  while (t.current < 0) t.current += t.count;
  while (t.current >= t.count) t.current -= t.count;
  PFObjShow();
}


function PFObjStartMove(e)
//----------------------------------------------------------------------
// Record the starting position of a mouse movement. 
//----------------------------------------------------------------------
{
  var t, x, y;

  if (PFisIE || PFisNav) {
    if (PFisIE) {
      t = document.PFObjMovies[window.event.srcElement.name];
    } else {
      t = document.PFObjMovies[e.target.name];
    }
  }

  if (t && (t.mousecontrol >= 0)) {
    if (PFisIE) {
      t.xstart = window.event.offsetX;
      t.ystart = window.event.offsetY;
    } else {
      t.xstart = e.pageX;
      t.ystart = e.pageY;
    }

    PFObjSetupXYWH(t);
    if ((t.mousecontrol & 6) == 2) {

      // horizontal.

      t.astart = (Math.PI * 2) * (t.xstart - t.x) / t.w;
    } else if ((t.mousecontrol & 6) == 4) {

      // vertical.

      t.astart = (Math.PI * 2) * (t.ystart - t.y) / t.h;
    } else {

      // circles.

      t.astart = Math.atan2(
        (t.xstart - t.x) / t.w,
        (t.ystart - t.y) / t.h);
    }
    t.moving = !isNaN(t.astart);
    t.istart = t.current;
    if (t.moving && t.running) {
      clearInterval(t.intervalcode);
      t.running = false;
    }
  }
}


function PFObjStopMove(e)
//----------------------------------------------------------------------
// Note that the mouse is no longer moving over the image. 
//----------------------------------------------------------------------
{
  var t;

  if (PFisIE || PFisNav) {
    if (PFisIE) {
      t = window.event.srcElement;
    } else {
      t = e.target;
    }
    t = document.PFObjMovies[t.name];
  }

  if (t && (t.mousecontrol >= 0)) {
    if (t.running) {
      clearInterval(t.intervalcode);
      t.running = false;
    }
    t.moving = false;
  }
}


function PFObjDoMove(e)
//----------------------------------------------------------------------
// Process mouse movement over the image.  Find the appropriate image
// and display it. 
//----------------------------------------------------------------------
{
  var t;

  if (PFisIE || PFisNav) {
    if (PFisIE) {
      t = window.event.srcElement;
    } else {
      t = e.target;
    }
    t = document.PFObjMovies[t.name];
  }

  if (t && (t.mousecontrol >= 0)) {
    if (t.running) {
      clearInterval(t.intervalcode);
      t.running = false;
    }
    if (!t.moving) PFObjStartMove(e);
    if (t.moving) {
      if (PFisIE) {
        t.xcurrent = window.event.offsetX;
        t.ycurrent = window.event.offsetY;
      } else {
        t.xcurrent = e.pageX;
        t.ycurrent = e.pageY;
      }

      PFObjSetupXYWH(t);
      if ((t.mousecontrol & 6) == 2) {

        // horizontal.

        t.acurrent = (Math.PI * 2) * (t.xcurrent - t.x) / t.w;
      } else if ((t.mousecontrol & 6) == 4) {

        // vertical.

        t.acurrent = (Math.PI * 2) * (t.ycurrent - t.y) / t.h;
      } else {

        // circles.

        t.acurrent = Math.atan2(
          (t.xcurrent - t.x) / t.w,
          (t.ycurrent - t.y) / t.h);
      }

      if (!isNaN(t.astart) && !isNaN(t.acurrent)) {
        var i;

        if (t.mousecontrol & 1) {

          // absolute.

          i = Math.floor(t.count - 1 - t.count * t.acurrent / (Math.PI * 2));
        } else {

          // relative.

          i = t.istart - Math.round(t.count * (t.acurrent - t.astart) / (Math.PI * 2));
        }
        while (i < 0) i += t.count;
        while (i >= t.count) i -= t.count;
       if (i != t.current) {
          t.current = i;
          PFObjShow();
        }
      }
    }
  }
}


function PFObjInit()
//----------------------------------------------------------------------
// Initialize the object movies.
//----------------------------------------------------------------------
{
  document.onmouseover = PFObjStartMove;
  document.onmouseout = PFObjStopMove;
  document.onmousemove = PFObjDoMove;
 
  if (PFisNav) {

    // Set up event handling.

    document.captureEvents(Event.MOUSEOVER | Event.MOUSEOUT | Event.MOUSEMOVE);
  }
}

