
function WM_checkIn(WM_id) { 

/*
WM_checkIn()
Takes the ID of a positioned HTML element and returns an object reference.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Taylor
Author Email: taylor@wired.com
Author URL: http://www.taylor.org/

Usage: WM_checkIn('id')
*/

  // First we initialize all the variables.
  var theObj,ss,sr,i,j,WM_layers=new Array();
  // This chunk handles the IE portion of the checkIn code.
  if (document.all) {
    // This checks to see if the inline style declaration has 
    // a position property associated with it. If not, it will 
    // scan the global stylesheets for the ID.
    if((document.all[WM_id].style.position != 'absolute') && (document.all[WM_id].style.position != 'relative')){
      // This little loop I'm very proud of, because it's kinda 
      // slick and I wrote it all myself. It loops through all 
      // global stylesheets and all the rules in each stylesheet, 
      // tests for the selected ID, then returns that as the object.
      for (ss=0 ; ss < document.styleSheets.length; ss++) {
        for (sr=0 ; sr < document.styleSheets(ss).rules.length; sr++) { 
          if (document.styleSheets(ss).rules(sr).selectorText == '#' + WM_id) {
            theObj = document.styleSheets(ss).rules(sr).style;
            break;
          }
        }
      }
    } else {
      // This works the same as in the light version, so you can 
      // use inline styles.
      theObj = document.all[WM_id].style;
    }
  } else if(document.layers) {
    // Now we're in Netscapeland. The main problem here 
    // is finding the object in a maze of hierarchy.
    // I wish I could say that I'm proud of this code, 
    // because it's really slick. Unfortunately, I ripped 
    // it off from Macromedia Dreamweaver's drag layer code 
    // (with permission, of course :-) 
    // Dreamweaver/Configuration/Behaviors/Actions/Drag Layer.htm 
    // It works wonderfully and solves the problem.
    WM_layers = new Array();
    with (document) {
      for (i=0; i<layers.length; i++) WM_layers[i]=layers[i]; {
        for (i=0; i<WM_layers.length; i++) {
          if (WM_layers[i].document && WM_layers[i].document.layers) {
            for (j=0; j<WM_layers[i].document.layers.length; j++) {
              WM_layers[WM_layers.length] = WM_layers[i].document.layers[j];
            }
            if(WM_layers[i].name == WM_id){
              // So if the code matches the name of the layer, 
              // return the reference. 
              theObj = WM_layers[i];
            }
          }
        }
      }
    }
  }
  return theObj;
}


function WM_moveTo(daObject, endLeft, endTop, numSteps, delay, endFunction) {

/*

WM_moveTo()

Moves an object from its current location to a new location and optionally fires a function when it's done.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Nadav Savio
Author Email: nadav@wired.com

Usage: WM_moveTo('objectName', endingLeft, endingTop, numberOfSteps, delayBetweenSteps, 'functionToFire()'); 

*/

  // Declare variables.
  var leftInc, topInc, daObj = new Object;
  // The first time through, create document.WM.WM_moveTo
  if (typeof document.WM == 'undefined'){
    document.WM = new Object;
    document.WM.WM_moveTo = new Object;
  } else if (typeof document.WM.WM_moveTo == 'undefined') {
    document.WM.WM_moveTo = new Object;
  }
  // Store endFunction to execute when the move is finished.
  if(endFunction) document.WM.WM_moveTo.endFunction = endFunction;
  // Get a good object reference (call it daObj) from WM_checkIn().
  // But if we've already done so, don't check it in again.
    if (daObject == "sameObj") {
      daObj = document.WM.WM_moveTo.daObj;
    } else {
      daObj = WM_checkIn(daObject);
      document.WM.WM_moveTo.daObj = daObj;
    }
  // If this is the last step, go to the end point and run endFunction.
  if (numSteps == 1) {
    daObj.left = endLeft;
    daObj.top = endTop;
    // If an endFunction was set, execute it and then delete it.
    if(document.WM.WM_moveTo.endFunction) {
      daFunction = document.WM.WM_moveTo.endFunction;
      document.WM.WM_moveTo.endFunction = '';
      eval(daFunction);
    }
  } else {
    // Otherwise, figure out how far to move.
    leftInc = (endLeft - parseInt(daObj.left)) / numSteps;
    topInc = (endTop - parseInt(daObj.top)) / numSteps;
    // Then move, decrement numSteps, and do it all again.
    daObj.left = parseInt(daObj.left) + leftInc;
    daObj.top = parseInt(daObj.top) + topInc;
    numSteps--;
    setTimeout ('WM_moveTo(\'sameObj\', ' + endLeft + ', ' + endTop + ', ' + numSteps + ', ' + delay + ')', delay);
  }
}



function WM_swapLayerBgcolor() {
/*
WM_swapLayerBgcolor() 
Changes the background color of one or more DIVs or SPANs. 

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Shvatz
Author Email: shvatz@wired.com

Usage: WM_swapLayerBgcolor('layerName1','newColor1',
'layerName2','newColor2', ...);

Requires: WM_checkIn()
*/

  // Make sure the browser supports DHTML.
  if(document.layers || document.all)
    with(WM_swapLayerBgcolor)
      // Loop through all arguments, two at a time.
      for(i = 0; i < (arguments.length - 1); i += 2)
  // Get an object reference and set the 
  // bgcolor according to the DOM.
  if(document.layers) 
    WM_checkIn(arguments[i]).document.bgColor = arguments[i+1];
  else if(document.all)
    WM_checkIn(arguments[i]).backgroundColor = arguments[i+1];
}


function WM_position2element() {
/*
WM_position2element()
Author: Taylor
Author Email: taylor@wired.com
Author URL: http://www.taylor.org/
URL: http://www.hotwired.com/webmonkey/code_library/dhtml/wm_position2element/
This action positions one DHTML element a specified number of 
pixels away from another, based on the left, top, right, or 
bottom of the bounding box of each element. To use it, you must 
choose the element to position and the element to position against;
specify which side of each element's bounding box to base the 
positioning on; and supply the number of pixels difference between 
the two. Optionally, you can choose the browser window as the 
element to position against by using the string "window".

You can only position either the left or the top of an element 
on each function call, not both at once, so multiple calls will 
be necessary if you want to offset the positioned element in two 
dimensions at once. This also only updates the element once, so 
if you want elements to follow each other in formation you'll 
need to call the function multiple times.

Usage: WM_position2element(elementPositioned, 
left|top|right|bottom, differenceInPixels, 
elementPositionedAgainst|window, left|top|right|bottom);
*/

  // First we set up our variables. posE is short for positionEE 
  // and posR is short for positionER.
  var posE,posR,mod;
  with(WM_position2element);
  posE = WM_checkIn(arguments[0]);
  // This block of code takes the string 'window' and makes it mean 
  // the browser window. This is handled in very different ways by 
  // Netscape and IE, so this block of code is rather long.
  if (arguments[3] == 'window') {
    if (document.all){
      posR = document.body;;
      posR.left = 0;
      posR.top = 0;
      // For some reason IE was adding four pixels. 
      // I subtracted it here.
      posR.width = document.body.offsetWidth - 4;
      posR.height = document.body.offsetHeight - 4;
    } else if (document.layers) {
      posR = document;
      posR.left = 0;
      posR.top = 0;
      posR.width = this.window.innerWidth;
      posR.height = this.window.innerHeight;
      // You need to set the width and height manually for Netscape. 
      // You can do this based on its clip.
      posE.width = posE.clip.width;
      posE.height = posE.clip.height;
    } 
  } else {
    // This is for positioning your element based on another element.
    // First, the standard checkIn procedure to conditionalize around 
    // the differences in the DOMs. You can replace this with any 
    // function that returns an object reference to a DHTML object.
    posR = WM_checkIn(arguments[3]);
    // Netscape doesn't know the object's width, only its 
    // clip.width, so I construct all that here.
    if (document.layers) {
      posE.width = posE.clip.width;
      posE.height = posE.clip.height;
      posR.width = posR.clip.width;
      posR.height = posR.clip.height;
    }
  }
  // This is where the faux properties are constructed. Right and 
  // bottom are equal to width and height, but I still use them, 
  // because it's easier to construct references to them based on 
  // the arguments later on.
  posE.right = parseInt(posE.width);
  posE.bottom = parseInt(posE.height);
  posR.right = parseInt(posR.left) + parseInt(posR.width);
  posR.bottom = parseInt(posR.top) + parseInt(posR.height);
  // This is where all that conditional work comes into play - the 
  // algorithm for the actual positioning. This is also where the 
  // difference between left and right or top and bottom is handled, 
  // through the setting of the mod[ifier] variable.
  if((arguments[1] == 'left') || (arguments[1] == 'right')) {
    if(arguments[1] == 'left') mod = 0;
    if(arguments[1] == 'right') mod = posE.right * -1;
    posE.left = parseInt(posR[arguments[4]]) + parseInt(arguments[2]) + mod;
  }
  if((arguments[1] == 'top') || (arguments[1] == 'bottom')) {
    if(arguments[1] == 'top') mod = 0;
    if(arguments[1] == 'bottom') mod = posE.bottom * -1;
    posE.top = parseInt(posR[arguments[4]]) + parseInt(arguments[2]) + mod;
  }
}


function WM_netscapeCssFix() {
  /*
    Source: Webmonkey Code Library
    (http://www.hotwired.com/webmonkey/javascript/code_library/)

    Author: Taylor
    Author Email: taylor@wired.com
    Author URL: http://www.taylor.org/
    */

  // This part was inspired by Matthew_Baird@wayfarer.com
  // It gets around another unfortunate bug whereby Netscape 
  // fires a resize event when the scrollbars pop up. This 
  // checks to make sure that the window's available size 
  // has actually changed.
  if (document.WM.WM_netscapeCssFix.initWindowWidth != window.innerWidth || document.WM.WM_netscapeCssFix.initWindowHeight != window.innerHeight) {
    document.location = document.location;
  }
}

function WM_netscapeCssFixCheckIn() {
  // This function checks to make sure the version of Netscape 
  // in use contains the bug; if so, it records the window's 
  // width and height and sets all resize events to be handled 
  // by the WM_netscapeCssFix() function.
  if ((navigator.appName == 'Netscape') && (parseInt(navigator.appVersion) == 4)) {
    if (typeof document.WM == 'undefined'){
      document.WM = new Object;
    }
    if (typeof document.WM.WM_scaleFont == 'undefined') {
      document.WM.WM_netscapeCssFix = new Object;
      document.WM.WM_netscapeCssFix.initWindowWidth = window.innerWidth;
      document.WM.WM_netscapeCssFix.initWindowHeight = window.innerHeight;
    }
    window.onresize = WM_netscapeCssFix;
  }
}

WM_netscapeCssFixCheckIn()

function WM_scaleFont(targetSize, initialFontSize, fontUnit) {

/*
WM_scaleFont()
Author: Taylor
Author Email: taylor@wired.com
Author URL: http://www.taylor.org/
Package URL: http://www.hotwired.com/webmonkey/

WM_scaleFont() scales the fonts on the page depending on 
the width of the window. It's very useful for creating a 
page that's designed to fit within a window without scrolling. 
For the whole effect to work well, use relative units 
(em, ex, %) for all your CSS positioning and for 
image and DIV sizes.

Usage: Internet Explorer requires the body tag to be loaded 
before you can determine the width, and Netscape needs to call 
the function in the head to write out the style tag. So you 
need to insert two calls: one in a script tag in the head, 
after any style sheets, and the other in a script tag right 
after the body. 
*/

  // This checks for the existence of the document objects and 
  // properties where we store the passed variables.
  if (typeof document.WM == 'undefined'){
    document.WM = new Object;
  }
  if (typeof document.WM.WM_scaleFont == 'undefined') {
    document.WM.WM_scaleFont = new Object;
    document.WM.WM_scaleFont.screenTarget = targetSize;
    document.WM.WM_scaleFont.targetBodyFontSize = initialFontSize;
    document.WM.WM_scaleFont.fontUnit = fontUnit;
  }
  // The actual screen width is gotten here.
  if (document.all) {
    var screenWidth = document.body.offsetWidth;
  } else if (document.layers) {
    var screenWidth = window.innerWidth;
  }
  // This one line is the core of the routine. It takes the 
  // targeted font size and divides it by the actual width 
  // times the targeted width.
  var scaledFont = parseInt(document.WM.WM_scaleFont.targetBodyFontSize) * (screenWidth / document.WM.WM_scaleFont.screenTarget);
  // Now this new font size is applied to the body. 
  // For IE, it changes the body's style declaration and 
  // sets things up such that on resize this function is 
  //called again. For Netscape, it writes out a style tag 
  // in the head, and then depends on WM_netscapeCssFix() 
  // to reload the page if it's been resized. 
  if (document.all) {
    document.body.style.fontSize = scaledFont + document.WM.WM_scaleFont.fontUnit;
    window.onresize = WM_scaleFont;
  } else if(document.layers) {
    var netscapeScaleReturn = '<style type="text/css">\nBODY {font-size: ' + scaledFont + document.WM.WM_scaleFont.fontUnit + '}\n</style>';
    document.writeln(netscapeScaleReturn);
  }
}


function WM_preloadImages() {

/*
WM_preloadImages()
Loads images into the browser's cache for later use.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Nadav Savio
Author Email: nadav@wired.com

Usage: WM_preloadImages('image 1 URL', 'image 2 URL', 'image 3 URL', ...);
*/

  // Don't bother if there's no document.images
  if (document.images) {
    if (typeof(document.WM) == 'undefined'){
      document.WM = new Object();
    }
    document.WM.loadedImages = new Array();
    // Loop through all the arguments.
    var argLength = WM_preloadImages.arguments.length;
    for(arg=0;arg<argLength;arg++) {
      // For each arg, create a new image.
      document.WM.loadedImages[arg] = new Image();
      // Then set the source of that image to the current argument.
      document.WM.loadedImages[arg].src = WM_preloadImages.arguments[arg];
    }
  }
}


// set hidden/visible vars for Netscape 4 compatibility
if (document.layers) {
  var hidden = "hide";
  var visible = "show";
} else {
  var hidden = "hidden";
  var visible = "visible";
}
var toggle = "toggle";

function WM_changeVisibility() {
/*
WM_changeVisibility()
Changes whether a layer is visible or hidden.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Nadav Savio
Author Email: nadav@wired.com

usage: WM_changeVisibility('targetLayer1',[visible|hidden|toggle],'targetLayer2',[visible|hidden|toggle],...,'targetLayerN',[visible|hidden|toggle])

*/

  if (document.layers || document.all) {
    var inc, endInc=arguments.length;
    // run through the args (objects) and set the visibility of each
    for (inc=0; inc<endInc; inc+=2) {
      // get a good object reference
      var daObj = WM_checkIn(arguments[inc]);
      if (arguments[inc+1] == hidden) {
        // hide the object
        daObj.visibility = hidden;
      } else if (arguments[inc+1] == visible) {
        // show the object
        daObj.visibility = visible;
      } else if (arguments[inc+1] == toggle) {
        // toggle the object's visibility
        if (daObj.visibility == visible) {
          daObj.visibility = hidden;
        } else if (daObj.visibility == hidden) {
          daObj.visibility = visible;
        }
      }
    }
  }
}


/*
BrowserDetector()
Parses User-Agent string into useful info.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Richard Blaylock
Author Email: blaylock@wired.com

Usage: var bd = new BrowserDetector(navigator.userAgent);
*/


// Utility function to trim spaces from both ends of a string
function Trim(inString) {
  var retVal = "";
  var start = 0;
  while ((start < inString.length) && (inString.charAt(start) == ' ')) {
    ++start;
  }
  var end = inString.length;
  while ((end > 0) && (inString.charAt(end - 1) == ' ')) {
    --end;
  }
  retVal = inString.substring(start, end);
  return retVal;
}

function BrowserDetector(ua) {

// Defaults
  this.browser = "Unknown";
  this.platform = "Unknown";
  this.version = "";
  this.majorver = "";
  this.minorver = "";

  uaLen = ua.length;

// ##### Split into stuff before parens and stuff in parens
  var preparens = "";
  var parenthesized = "";

  i = ua.indexOf("(");
  if (i >= 0) {
    preparens = Trim(ua.substring(0,i));
        parenthesized = ua.substring(i+1, uaLen);
        j = parenthesized.indexOf(")");
        if (j >= 0) {
          parenthesized = parenthesized.substring(0, j);
        }
  }
  else {
    preparens = ua;
  }

// ##### First assume browser and version are in preparens
// ##### override later if we find them in the parenthesized stuff
  var browVer = preparens;

  var tokens = parenthesized.split(";");
  var token = "";
// # Now go through parenthesized tokens
  for (var i=0; i < tokens.length; i++) {
    token = Trim(tokens[i]);
        //## compatible - might want to reset from Netscape
        if (token == "compatible") {
          //## One might want to reset browVer to a null string
          //## here, but instead, we'll assume that if we don't
          //## find out otherwise, then it really is Mozilla
          //## (or whatever showed up before the parens).
        //## browser - try for Opera or IE
    }
        else if (token.indexOf("MSIE") >= 0) {
      browVer = token;
    }
    else if (token.indexOf("Opera") >= 0) {
      browVer = token;
    }
        //'## platform - try for X11, SunOS, Win, Mac, PPC
    else if ((token.indexOf("X11") >= 0) || (token.indexOf("SunOS") >= 0) ||
(token.indexOf("Linux") >= 0)) {
      this.platform = "Unix";
        }
    else if (token.indexOf("Win") >= 0) {
      this.platform = token;
        }
    else if ((token.indexOf("Mac") >= 0) || (token.indexOf("PPC") >= 0)) {
      this.platform = token;
        }
  }

  var msieIndex = browVer.indexOf("MSIE");
  if (msieIndex >= 0) {
    browVer = browVer.substring(msieIndex, browVer.length);
  }

  var leftover = "";
  if (browVer.substring(0, "Mozilla".length) == "Mozilla") {
    this.browser = "Netscape";
        leftover = browVer.substring("Mozilla".length+1, browVer.length);
  }
  else if (browVer.substring(0, "Lynx".length) == "Lynx") {
    this.browser = "Lynx";
        leftover = browVer.substring("Lynx".length+1, browVer.length);
  }
  else if (browVer.substring(0, "MSIE".length) == "MSIE") {
    this.browser = "IE";
    leftover = browVer.substring("MSIE".length+1, browVer.length);
  }
  else if (browVer.substring(0, "Microsoft Internet Explorer".length) ==
"Microsoft Internet Explorer") {
    this.browser = "IE"
        leftover = browVer.substring("Microsoft Internet Explorer".length+1,
browVer.length);
  }
  else if (browVer.substring(0, "Opera".length) == "Opera") {
    this.browser = "Opera"
    leftover = browVer.substring("Opera".length+1, browVer.length);
  }

  leftover = Trim(leftover);

  // # Try to get version info out of leftover stuff
  i = leftover.indexOf(" ");
  if (i >= 0) {
    this.version = leftover.substring(0, i);
  }
  else
  {
    this.version = leftover;
  }
  j = this.version.indexOf(".");
  if (j >= 0) {
    this.majorver = this.version.substring(0,j);
    this.minorver = this.version.substring(j+1, this.version.length);
  }
  else {
    this.majorver = this.version;
  }


} // function BrowserCap




function WM_changeLinks(oldHref, newHref) {

/*
WM_changeLinks()
Changes all instances of one link to another.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Nadav Savio
Author Email: nadav@wired.com

Usage: WM_changeLinks('oldHref','newHref'); 
*/

  for (daLink = 0; daLink < document.links.length; daLink++) {
    if (document.links[daLink].href == oldHref) {
      document.links[daLink].href = newHref;
    }
  }
}

/*
WM_swapLayerBgcolor() 
Changes the background color of one or more DIVs or SPANs. 

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Shvatz
Author Email: shvatz@wired.com

Usage: WM_swapLayerBgcolor('layerName1','newColor1',
'layerName2','newColor2', ...);

Requires: WM_checkIn()
*/

function WM_swapLayerBgcolor() {
  // Make sure the browser supports DHTML.
  if(document.layers || document.all)
    with(WM_swapLayerBgcolor)
      // Loop through all arguments, two at a time.
      for(i = 0; i < (arguments.length - 1); i += 2)
  // Get an object reference and set the 
  // bgcolor according to the DOM.
  if(document.layers) 
    WM_checkIn(arguments[i]).document.bgColor = arguments[i+1];
  else if(document.all)
    WM_checkIn(arguments[i]).backgroundColor = arguments[i+1];
}


/*

Netscape 4 Cursor Position Template

Captures the cursor position for Netscape 4 when a mouse event fires and creates an IE 4-style window.event object to store the position.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Nadav Savio
Author Email: nadav@wired.com

Usage: Copy and paste the code into your document.

*/

if(!window.event && window.captureEvents) {
  // set up event capturing for mouse events (add or subtract as desired)
  window.captureEvents(Event.MOUSEOVER|Event.MOUSEOUT|Event.CLICK|Event.DBLCLICK);
  // set window event handlers (add or subtract as desired)
  window.onmouseover = WM_getCursorHandler;
  window.onmouseout = WM_getCursorHandler;
  window.onclick = WM_getCursorHandler;
  window.ondblclick = WM_getCursorHandler;
  // create an object to store the event properties 
  window.event = new Object;
}


function WM_getCursorHandler(e) {
  // set event properties to global vars (add or subtract as desired)
  window.event.clientX = e.pageX;
  window.event.clientY = e.pageY;
  window.event.x = e.layerX;
  window.event.y = e.layerY;
  window.event.screenX = e.screenX;
  window.event.screenY = e.screenY;
  // route the event back to the intended function
  if ( routeEvent(e) == false ) {
    return false;
  } else {
    return true;
  }
}



function WM_imageSwap(daImage, daSrc){
  var objStr,obj;
  /*
    WM_imageSwap()
    Changes the source of an image.

    Source: Webmonkey Code Library
    (http://www.hotwired.com/webmonkey/javascript/code_library/)

    Author: Shvatz
    Author Email: shvatz@wired.com

    Usage: WM_imageSwap(originalImage, 'newSourceUrl');

    Requires: WM_preloadImages() (optional, but recommended)
    Thanks to Ken Sundermeyer (ksundermeyer@macromedia.com) for his help
    with variables in ie3 for the mac. 
    */

  // Check to make sure that images are supported in the DOM.
  if(document.images){
    // Check to see whether you are using a name, number, or object
    if (typeof(daImage) == 'string') {
      // This whole objStr nonesense is here solely to gain compatability
      // with ie3 for the mac.
      objStr = 'document.' + daImage;
      obj = eval(objStr);
      obj.src = daSrc;
    } else if ((typeof(daImage) == 'object') && daImage && daImage.src) {
      daImage.src = daSrc;
    }
  }
}


function SM_dailyBgColor (sunday,monday,tuesday,wednesday,thursday,friday,saturday) {

/*
SM_dailyBgColor()
This function automatically changes the page's background color each day of the week.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Sean McManus
Author Email: sean@liquidizer.demon.co.uk
Author URL: http://www.liquidizer.demon.co.uk/

Usage: SM_dailyBgColor ("mondaycolor", "tuesdaycolor", "wednesdaycolor", "thursdaycolor", "fridaycolor", "saturdaycolor", "sundaycolor"); 
*/

  cols=new Object();
  cols[0]=sunday;
  cols[1]=monday;
  cols[2]=tuesday;
  cols[3]=wednesday;
  cols[4]=thursday;
  cols[5]=friday;
  cols[6]=saturday;

  today=new Date();
  day=Math.round(today.getDay());
  document.bgColor=cols[day];
}


// -----------------------------------------------------------------
// Function    : IsFormComplete
// Language    : JavaScript
// Description : Checks if all elements in a form have a non-blank value
// Copyright   : (c) 1998 Shawn Dorman
// http://www.goodnet.com/~sdorman/web/IsFormComplete.html
// -----------------------------------------------------------------
// Ver    Date    Description of modification
// --- ---------- --------------------------------------------------
// 1.0 08/31/1996 Original write
// 1.1 09/30/1998 CHG: Use standard header format
// -----------------------------------------------------------------
// Source: Webmonkey Code Library
// (http://www.hotwired.com/webmonkey/javascript/code_library/)
// -----------------------------------------------------------------

function IsFormComplete(FormName)
{
var x       = 0
var FormOk  = true

while ((x < document.forms[FormName].elements.length) && (FormOk))
   {
     if (document.forms[FormName].elements[x].value == '')
     { 
        alert('Please enter the '+document.forms[FormName].elements[x].name +' and try again.')
        document.forms[FormName].elements[x].focus()
        FormOk = false 
     }
     x ++
   }
return FormOk
}

// -----------------------------------------------------------------
// Function    : IsEmailValid
// Language    : JavaScript
// Description : Checks if given email address is of valid syntax
// Copyright   : (c) 1998 Shawn Dorman
// http://www.goodnet.com/~sdorman/web/IsEmailValid.html
// -----------------------------------------------------------------
// Ver    Date    Description of modification
// --- ---------- --------------------------------------------------
// 1.0 09/04/1996 Original write
// 1.1 09/30/1998 CHG: Use standard header format
// -----------------------------------------------------------------
// Source: Webmonkey Code Library
// (http://www.hotwired.com/webmonkey/javascript/code_library/)
// -----------------------------------------------------------------

function IsEmailValid(FormName,ElemName)
{
var EmailOk  = true
var Temp     = document.forms[FormName].elements[ElemName]
var AtSym    = Temp.value.indexOf('@')
var Period   = Temp.value.lastIndexOf('.')
var Space    = Temp.value.indexOf(' ')
var Length   = Temp.value.length - 1   // Array is from 0 to length-1

if ((AtSym < 1) ||                     // '@' cannot be in first position
    (Period <= AtSym+1) ||             // Must be atleast one valid char btwn '@' and '.'
    (Period == Length ) ||             // Must be atleast one valid char after '.'
    (Space  != -1))                    // No empty spaces permitted
   {  
      EmailOk = false
      alert('Please enter a valid e-mail address!')
      Temp.focus()
   }
return EmailOk
}


/*
MD_random() 
This function returns a random integer between two numbers. 

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Michael Daines
Author Email: mdaines@shaw.wave.ca

Usage: MD_random(number1, number2) returns a random integer between the values specified.
*/

function MD_random(r1, r2) {
  if (r2 > r1) return (Math.round(Math.random()*(r2-r1))+r1);
  else return (Math.round(Math.random()*(r1-r2))+r2);
}


/*
WM_setCookie(), WM_readCookie(), WM_killCookie()
A set of functions that eases the pain of using cookies.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Nadav Savio
Author Email: nadav@wired.com
*/


// This next little bit of code tests whether the user accepts cookies.
var WM_acceptsCookies = false;
if(document.cookie == '') {
    document.cookie = 'WM_acceptsCookies=yes'; // Try to set a cookie.
    if(document.cookie.indexOf('WM_acceptsCookies=yes') != -1) {
	WM_acceptsCookies = true; 
    }// If it succeeds, set variable
} else { // there was already a cookie
  WM_acceptsCookies = true;
}


function WM_setCookie (name, value, hours, path, domain, secure) {
    if (WM_acceptsCookies) { // Don't waste your time if the browser doesn't accept cookies.
	var not_NN2 = (navigator && navigator.appName 
		       && (navigator.appName == 'Netscape') 
		       && navigator.appVersion 
		       && (parseInt(navigator.appVersion) == 2))?false:true;

	if(hours && not_NN2) { // NN2 cannot handle Dates, so skip this part
	    if ( (typeof(hours) == 'string') && Date.parse(hours) ) { // already a Date string
		var numHours = hours;
	    } else if (typeof(hours) == 'number') { // calculate Date from number of hours
		var numHours = (new Date((new Date()).getTime() + hours*3600000)).toGMTString();
	    }
	}
	document.cookie = name + '=' + escape(value) + ((numHours)?(';expires=' + numHours):'') + ((path)?';path=' + path:'') + ((domain)?';domain=' + domain:'') + ((secure && (secure == true))?'; secure':''); // Set the cookie, adding any parameters that were specified.
    }
} // WM_setCookie


function WM_readCookie(name) {
    if(document.cookie == '') { // there's no cookie, so go no further
	return false; 
    } else { // there is a cookie
	var firstChar, lastChar;
	var theBigCookie = document.cookie;
	firstChar = theBigCookie.indexOf(name);	// find the start of 'name'
	var NN2Hack = firstChar + name.length;
	if((firstChar != -1) && (theBigCookie.charAt(NN2Hack) == '=')) { // if you found the cookie
	    firstChar += name.length + 1; // skip 'name' and '='
	    lastChar = theBigCookie.indexOf(';', firstChar); // Find the end of the value string (i.e. the next ';').
	    if(lastChar == -1) lastChar = theBigCookie.length;
	    return unescape(theBigCookie.substring(firstChar, lastChar));
	} else { // If there was no cookie of that name, return false.
	    return false;
	}
    }	
} // WM_readCookie

function WM_killCookie(name, path, domain) {
  var theValue = WM_readCookie(name); // We need the value to kill the cookie
  if(theValue) {
      document.cookie = name + '=' + theValue + '; expires=Fri, 13-Apr-1970 00:00:00 GMT' + ((path)?';path=' + path:'') + ((domain)?';domain=' + domain:''); // set an already-expired cookie
  }
} // WM_killCookie


/*
Webmonkey GET Parsing Module
Language: JavaScript 1.0

The parsing of GET queries is fundamental
to the basic functionality of HTTP/1.0.
This module parses GET with JavaScript 1.0.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Patrick Corcoran
Author Email: patrick@taylor.org
*/

function createRequestObject() {
  
  FORM_DATA = new Object();
    // The Object ("Array") where our data will be stored.
  
  separator = ',';
    // The token used to separate data from multi-select inputs
  
  query = '' + this.location;
    // Get the current URL so we can parse out the data.
    // Adding a null-string '' forces an implicit type cast
    // from property to string, for NS2 compatibility.
    
  query = query.substring((query.indexOf('?')) + 1);
    // Keep everything after the question mark '?'.
  
  if (query.length < 1) { return false; }  // Perhaps we got some bad data?
  
  keypairs = new Object();
  numKP = 1;
    // Local vars used to store and keep track of name/value pairs
    // as we parse them back into a usable form.
    
  while (query.indexOf('&') > -1) {
    keypairs[numKP] = query.substring(0,query.indexOf('&'));
    query = query.substring((query.indexOf('&')) + 1);
    numKP++;
      // Split the query string at each '&', storing the left-hand side
      // of the split in a new keypairs[] holder, and chopping the query
      // so that it gets the value of the right-hand string.
  }

  keypairs[numKP] = query;
    // Store what's left in the query string as the final keypairs[] data.
  
  for (i in keypairs) {
    keyName = keypairs[i].substring(0,keypairs[i].indexOf('='));
      // Left of '=' is name.
    keyValue = keypairs[i].substring((keypairs[i].indexOf('=')) + 1);
      // Right of '=' is value.
    while (keyValue.indexOf('+') > -1) {
      keyValue = keyValue.substring(0,keyValue.indexOf('+')) + ' ' + keyValue.substring(keyValue.indexOf('+') + 1);
        // Replace each '+' in data string with a space.
    }
    
    keyValue = unescape(keyValue);
      // Unescape non-alphanumerics
      
    if (FORM_DATA[keyName]) {
      FORM_DATA[keyName] = FORM_DATA[keyName] + separator + keyValue;
        // Object already exists, it is probably a multi-select input,
        // and we need to generate a separator-delimited string
        // by appending to what we already have stored.
    } else {
      FORM_DATA[keyName] = keyValue;
        // Normal case: name gets value.
    }
  }

  return FORM_DATA;
}

FORM_DATA = createRequestObject();
  // This is the array/object containing the GET data.
  // Retrieve information with 'FORM_DATA [ key ] = value'.


/*
Webmonkey Array Enhancements

JavaScript 1.2, which only works in Netscape 
4.0, adds several fundamental methods to the 
array object. A few of these very useful 
methods are included here in a form that 
can be used by 3.0 browsers.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Thau!
Author Email: thau@wired.com
*/

// copy
//
// Copies the contents of an array into a temp 
// array and returns the copy.
//
// It doesn't alter the original array, but be 
// careful if the array contains references to 
// objects instead of just strings or numbers. 
// References to objects will be copied as 
// references. This means that if you change 
// an object in the original array, it will 
// also be changed in the new array.
//
function copy()
{
  var loop;
  var temp_array = new Array();
  for (loop = 0; loop < this.length; loop++)
  {
    temp_array[loop] = this[loop];
  }
  return temp_array;
}

Array.prototype.copy = copy;

// pop
//
// Removes the last element of an array and 
// returns that element. 
//
function pop()
{
  var last_item = this[this.length-1];
  this.length--;
  return last_item;
}

Array.prototype.pop = pop;

// push
//
// Adds an element to the end of an array and 
// returns the new length of the array. This 
// method changes the length of the array. 
//
function push(the_item)
{
  this[this.length] = the_item;
  return this.length;
}

Array.prototype.push = push;

// concat
//
// Joins two arrays and returns a new array. 
// It doesn't alter the original arrays, but be 
// careful if the arrays contain references to 
// objects instead of just strings or numbers. 
// References to objects will be copied as 
// references. This means that if you change 
// an object in the original arrays, it will 
// also be changed in the new array.
//
function concat(second_array)
{
  var first_array = this.copy();
  
  for (loop = 0; loop<second_array.length; loop++)
  {
    first_array[first_array.length] = second_array[loop];
  }
  return first_array;
}

Array.prototype.concat = concat;

// shift
//
// Removes the first element of an array and 
// returns that element.
//
function shift()
{
  var new_value = this[0];
  var orig_length = this.length;
  for (loop = 0; loop<this.length-1; loop++)
  {
    this[loop] = this[loop+1];
  }
  this.length--;
  return new_value;
}

Array.prototype.shift = shift;

// unshift
//
// Adds an element to the beginning of an array and 
// returns the new length of the array.
//
function unshift(the_item)
{
  for (loop = this.length-1 ; loop >= 0; loop--)
  {
    this[loop+1] = this[loop];
  }
  this[0] = the_item;
  return this.length;
}

Array.prototype.unshift = unshift;

// permute
//
// Randomly reorders the elements of an 
// array and returns the new, reordered array. 
// The original array remains unchanged.
// 
function permute(the_array)
{

  var temp_array = this.copy();
  var new_array = new Array();
  var random_num = 0;
  for (loop = 0; loop < this.length; loop++)
  {
    random_num = Math.round(Math.random() * (temp_array.length-1));
    new_array[loop] = temp_array[random_num];
    temp_array[random_num] = temp_array[temp_array.length-1];
    temp_array.length--;
  }
  return new_array;
}

Array.prototype.permute = permute;


/*
Plugin Detector()

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Nadav Savio
Author Email: webmonkey@giantant.com

*/

// this is where we write out the VBScript for MSIE Windows
var WM_startTagFix = '</';
var msie_windows = 0;
if ((navigator.userAgent.indexOf('MSIE') != -1) && (navigator.userAgent.indexOf('Win') != -1)){
  msie_windows = 1;
  document.writeln('<script language="VBscript">');
  document.writeln('\'This will scan for plugins for all versions of Internet Explorer that have a VBscript engine version 2 or greater.');
  document.writeln('\'This includes all versions of IE4 and beyond and some versions of IE 3.');
  document.writeln('Dim WM_detect_through_vb');
  document.writeln('WM_detect_through_vb = 0');
  document.writeln('If ScriptEngineMajorVersion >= 2 then');
  document.writeln('  WM_detect_through_vb = 1');
  document.writeln('End If');
  document.writeln('Function WM_activeXDetect(activeXname)');
  document.writeln('  on error resume next');
  document.writeln('  If ScriptEngineMajorVersion >= 2 then');
  document.writeln('     WM_activeXDetect = False');
  document.writeln('     WM_activeXDetect = IsObject(CreateObject(activeXname))');
  document.writeln('     If (err) then');
  document.writeln('        WM_activeXDetect = False');
  document.writeln('     End If');
  document.writeln('   Else');
  document.writeln('     WM_activeXDetect = False');
  document.writeln('   End If');
  document.writeln('End Function');
  document.writeln(WM_startTagFix+'script>');
}

function WM_pluginDetect(plugindescription, pluginxtension, pluginmime, activeXname){

  //This script block will test all user agents that have a real plug-in array

  //(i.e. Netscape) and set the variables, otherwise it directs the routine

  // to WM_activeXDetect to detect the activeX control.

  

  // First define some variables
  var i,plugin_undetectable=0,detected=0, daPlugin=new Object();


  // Then we check to see if it's an MSIE browser that you can actually

  // check for the plugin in question. 

  if (msie_windows && WM_detect_through_vb){
      plugin_undetectable = 0;
  } else {
      plugin_undetectable = 1;
  }



  // If it has a real plugins or mimetypes array, we look there for the plugin first

  if(navigator.plugins) {
      numPlugins = navigator.plugins.length;
      if (numPlugins > 1) {
	  if (navigator.mimeTypes && navigator.mimeTypes[pluginmime] && navigator.mimeTypes[pluginmime].enabledPlugin && (navigator.mimeTypes[pluginmime].suffixes.indexOf(pluginxtension) != -1)) { // seems like we have it, let's just make sure and check the version (if specified)
	      if ((navigator.appName == 'Netscape') && (navigator.appVersion.indexOf('4.0') != -1)) { // stupid, stupid Netscape can't handle the references to navigator.plugins by number, sooo...
		  for(i in navigator.plugins) {
		      if ((navigator.plugins[i].description.indexOf(plugindescription) != -1) || (i.indexOf(plugindescription) != -1)) { // some versions of quicktime have no description. feh!
			  detected=1;
			  break;
		      }
		  }
	      } else {
		  for (i = 0; i < numPlugins; i++) {
		      daPlugin = navigator.plugins[i];
		      if ((daPlugin.description.indexOf(plugindescription) != -1) || (daPlugin.name.indexOf(plugindescription) != -1)) {
			  detected=1;
			  break;
		      }
		  }
	      }

	      // Mac weirdness
      if (navigator.mimeTypes[pluginmime] == null) {
		  detected = 0;
	      }
	  }
	  return detected;
      } else if((msie_windows == 1) && !plugin_undetectable){
	  return WM_activeXDetect(activeXname);
      } else { 		
	  return 0;
      }
  } else {
      return 0;
  }
}


// this next function just makes it easy to detect the common plugins

function WM_easyDetect(whichPlugin) {

    // this function just makes it easy to do basic plug-in detection without

    // knowing all the mimetypes and activeX names and such
    var isItThere = 0;
    if( (whichPlugin == 'flash') || (whichPlugin == 'Flash') ) {
	isItThere = WM_pluginDetect('Flash', 'swf', 'application/x-shockwave-flash', 'ShockwaveFlash.ShockwaveFlash');
    } else if( (whichPlugin == 'director') || (whichPlugin == 'Director') ) {
	isItThere = WM_pluginDetect('Shockwave', 'dcr', 'application/x-director', 'SWCtl.SWCtl.1');
    } else if( (whichPlugin == 'quicktime') || (whichPlugin == 'Quicktime') || (whichPlugin == 'QuickTime') ) {
	isItThere = WM_pluginDetect('QuickTime', 'mov', 'video/quicktime', '');
    } else if( (whichPlugin == 'realaudio') || (whichPlugin == 'Realaudio') || (whichPlugin == 'RealAudio') ) {
	isItThere = (WM_pluginDetect('RealPlayer', 'rpm', 'audio/x-pn-realaudio-plugin', 'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)')) || (WM_pluginDetect('RealPlayer', 'rpm', 'audio/x-pn-realaudio-plugin','rmocx.RealPlayer G2 Control')) || (WM_pluginDetect('RealPlayer', 'rpm', 'audio/x-pn-realaudio-plugin','RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)')) || (WM_pluginDetect('RealPlayer', 'rpm', 'audio/x-pn-realaudio-plugin','RealVideo.RealVideo(tm) ActiveX Control (32-bit)'))
    } else {

	alert('You need to tell me which plug-in to look for, like so:\n\n' + '          WM_easyDetect(\'flash\')\n\n' + '          WM_easyDetect(\'director\')\n\n' + '          WM_easyDetect(\'quicktime\')\n\n' + '          WM_easyDetect(\'realaudio\')');
    }
    return isItThere;
}


/*
JavaScript Error Trapping and Logging

This library module enables suppression of
JavaScript errors in a way that allows errors
to be hidden from view, logged to a server
log file for further review, and optionally
displayed in the window.status area if desired.

Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)

Author: Patrick Corcoran
Author email: patrick@taylor.org
*/

trapErrors = true;
  // Setting this to false will turn off JS error suppression,
  // setting the browser to its normal behavior.
  // Useful for debugging during development.
  
logErrors = true;
  // Setting this to false will stop errors from being logged.
  // Useful when working offline or without CGI.
  
showErrorAsStatusMessage = false;
  // Setting this to true will cause the browser to display
  // the error message as the window.defaultStatus text,
  // resulting in a quieter, but not invisible, error message.
  // Sometimes this can be a more pleasant way to debug JavaScript.

logNumErrors = 3;
  // Number of JS errors per page to enter into log before calling it quits.
  // Large values aren't recommended ... if you're getting a lot
  // of errors per pageview, then you're probably in a nasty loop.

logScriptLoc = "path to your cgi script goes here";
  // The script must reside within the htdocs tree
  // or in a server-aliased directory like /cgi-bin,
  // since the error message is sent via HTTP.

scriptName = "JS Err Log";
  // Optional: This can be any string of text used to identify the script.

logComment = "Testing";
  // Optional: A short comment may be supplied here.

// You may want to separate the remainder of the script from
// the preceding portion so that you can call the same
// error trapping code with different variable settings from
// different HTML pages without repeating a lot of code.

MSIE = (navigator.userAgent.indexOf('MSIE') > -1) ? ( true ) : ( false );
  // Is this browser a Microsoft Internet Explorer browser?

if (!MSIE) { originalErrorHandler = window.onerror; }
  // Read and store value of current window.onerror property for later restoring.
  // But exclude MSIE because it won't allow us to read the window.onerror property.
  
originalDefaultStatus = window.defaultStatus;
  // Read and store value of current window.defaultStatus property for later restoring.
  
numErrorEvents = 0;
  // Number of Errors we've experienced so far for this pageview.


function handleErrors(msg, errUrl, line) {

  if (logErrors || showErrorAsStatusMessage) {
    
    if (numErrorEvents < logNumErrors) {
      
      errImage = new Array(logNumErrors);
        // This will hold all of our Image() objects we will create
        // to pass error data to the server.
      
      d = new Date();
        // We append a new Date() object to the end of every GET string
        // to ensure that the URL is always unique, and therefore not
        // subject to the disk cache frustrations of MSIE.
      
      sn = (scriptName) ? ('&scr=' + escape(scriptName)) : ('');
      lc = (logComment) ? ('&comm=' + escape(logComment)) : ('');
        // Escape the data from the optional scriptName and logComment variables if necessary.
              
      if (MSIE) {
        // window.onerror in MSIE doesn't pass msg, errUrl, line values
        // automatically like Netscape does, so we must approximate them.
        errUrl = this.location;    
        msg = 'Unspecified JS Error';  
        line = 'MSIE';          
      } else {
        line = 'line ' + line;
      }
      
      if (logErrors) {
        
        errLogEntry = logScriptLoc + '?url=' + escape(errUrl) + '&msg=' + escape(msg) + '&line=' + escape(line) + sn + lc + '&d=' + escape(d);
          // Build a GET string from the data we have pieced together about the error event.
  
        errImage[numErrorEvents] = new Image();  
        errImage[numErrorEvents].src = errLogEntry;
          // The Image() object is essentially the only Object
          // in NS3, NS4, and MSIE that can have its URL refreshed
          // without reloading the page, so we use it as a background data
          // carrier for client->server communication.  We set the new URL equal
          // to our GET string, which will get parsed by the CGI on the server.
          // The CGI will return empty/garbage data, but we don't care,
          // since the image we're loading here isn't for display.
      }
      
      if (showErrorAsStatusMessage) { window.defaultStatus = 'JavaScript Error: ' + msg + ' in ' + line; }
      
      numErrorEvents++;
    }
  }
  
  return trapErrors;
}

function restoreWindowToPreviousState() {
  // Set window.onerror and window.defaultStatus
  // to their initial state when leaving the page.
  if (!MSIE) { window.onerror = originalErrorHandler; }
  window.defaultStatus = originalDefaultStatus;
}

window.onUnload = restoreWindowToPreviousState;

window.onerror = handleErrors;

