/* NOT-SO-USER-DEFINABLE PARAMETERS. */
var onesecond = 60, frames_per_second = 12;
var steps_per_frame = 1+Math.floor(onesecond/frames_per_second-0.5);
var framedelay_in_ms = 1+Math.floor(1000/frames_per_second-0.5);

var jsversn_1p1 = false;
var browserName = navigator.appName.substring(0,8);
var browserVer = parseFloat(navigator.appVersion);

if ((browserName == 'Netscape' && browserVer >= 3.0) ||
    (browserName == 'Microsof' && browserVer >= 4.0))
  jsversn_1p1 = true;


/* ** FUNCTIONS OF CLASS FADETEXTFORMAT ** */

function FadeTextFormat_compute_colorsteps()
{ // computes how much to change color between animation frames.
  this.colstepup.set_color_rgb((this.fgcol.r - this.bgcol.r)/this.time_fadeup,
                               (this.fgcol.g - this.bgcol.g)/this.time_fadeup,
                               (this.fgcol.b - this.bgcol.b)/this.time_fadeup);
  this.colstepdown.set_color_rgb((this.fgcol.r - this.bgcol.r)/this.time_fadedown,
                                 (this.fgcol.g - this.bgcol.g)/this.time_fadedown,
                                 (this.fgcol.b - this.bgcol.b)/this.time_fadedown);
}

function FadeTextFormat_set_colorstrings( textcolstr, backgroundcolstr)
{ // textcolstr and backgroundcolstr are strings of the form "#ffffff".
  this.fgcol.set_color_string( textcolstr);
  this.bgcol.set_color_string( backgroundcolstr);
  this.compute_colorsteps();
}

function FadeTextFormat_set_colorstyles( textcol, backgroundcol, textclassname,
					 preformat, postformat)
{
  // textcol and backroundcol are objects of class ColorStyle.
  // textclassname is name of class of foreground text; if no class, this should
  // just be "BODY".
  // preformat and postformat are only used in NS4: these are HTML tags to
  // put BEFORE and AFTER the DIV that encloses the text; this is to fix bugs in
  // NS4 for Linux/Unix that ignore some Style Sheet rules.  preformat and 
  // postformat should duplicate any style sheet rules ingored by NS4,
  // for example "<FONT SIZE=-1>" and "</FONT>" to duplicate "{font-size: 10pt}".

  // These only have effect in NS4.
  if (textclassname != null && textclassname != "" && textclassname != "BODY")
    {
      this.preformat = preformat+"<DIV CLASS=\""+textclassname+"\">";
      this.postformat = "</DIV>"+postformat;
    }
  else
    {
      this.preformat = preformat;
      this.postformat = postformat;
    }

  if (textcol == null || backgroundcol == null)
    return;

  this.fgcol.copy( textcol);
  this.bgcol.copy( backgroundcol);
  this.compute_colorsteps();
}

/* Constructor: */
function FadeTextFormat( time_initdelay, time_fadeup, time_display, time_fadedown)
{ // time_initdelay, time_fadeup, time_display, and time_fadedown are all
  // measured in units of 1/60 second.
  // If time_display >= 0, text will be displayed (after fade-up) for time_display
  // and then fade-down will begin automatically.  If time_display == -1, 
  // auto-fade-down is disabled, after text fades up it will remain on.
  this.fgcol = new ColorStyle();
  this.bgcol = new ColorStyle();
  this.colstepup   = new ColorStyle();
  this.colstepdown = new ColorStyle();
  this.preformat = "";
  this.postformat = "";

  this.time_initdelay = time_initdelay;
  this.time_fadeup = time_fadeup;
  this.time_display = time_display;
  this.time_fadedown = time_fadedown;
}

/* Member Functions of Class FadeTextFormat: */
FadeTextFormat.prototype.set_colorstyles = FadeTextFormat_set_colorstyles;
FadeTextFormat.prototype.set_colorstrings = FadeTextFormat_set_colorstrings;
FadeTextFormat.prototype.compute_colorsteps = FadeTextFormat_compute_colorsteps;

/* ** MEMBER FUNCTIONS OF CLASS FADETEXTAREA ** */

function getFadeTextArea( win, divid, layerid)
{ // Returns a reference to relevant HTML element: ilayer (for NS4), otherwise DIV.
  // divid is id (string) of text area's enclosing DIV within document. 
  // layerid is id (string) of text area's enclosing ilayer (for NS4).
  // In NS4, this function may return NULL if document is not yet loaded.
  if (document.all && divid != null && divid != '')  /* IE4 */
    return win.document.all[divid];
  else if (document.getElementById && divid != null && divid != '')  /* NS6 */
    return win.document.getElementById(divid);
  else if (document.layers && layerid != null && layerid != '') /* NS4 */
    return win.document.layers[layerid];
  else
    return null;
}

function FadeTextArea_set_format( fadetextformat)
{ this.format = fadetextformat; }

function FadeTextArea_set_content( content)
{ this.content = content; }

function FadeTextArea_animateframe()
{
  this.timeup = null;  // clear previous setTimeout value.

  if (this.animode == 1) // Fade Up
    {
      if (this.colindex < this.format.time_fadeup - steps_per_frame)
	this.colindex += steps_per_frame;
      else
	this.colindex = this.format.time_fadeup;

      this.redraw();

      if (this.colindex == this.format.time_fadeup)
	if (this.format.time_display >= 0)
	  { // We display for fixed time, then begin auto-fade down.
	    this.animode = 3; // fade down.
	    this.colindex = this.format.time_fadedown;
	    if (this.format.time_display > 0)
	      { // If time_display were 0, we would start auto-fade-down now.
		this.timeup =
		    setTimeout( this.myhome+".animateframe();",
				(this.format.time_display*1000)/onesecond);
		return;
	      }
	  }
	else // If time_display == -1, disable auto-fade-down.
	  this.animode = 2; // static on.
    }
  else if (this.animode >= 3) // Fade down.
    {
      if (this.colindex > steps_per_frame)
	this.colindex -= steps_per_frame;
      else
	this.colindex = 0;

      this.redraw();

      if (this.colindex == 0)
	{
	  if (this.animode == 3)
	    this.animode = 0; // hidden.
	  else
	    { // done fading down, start fade up with new text.
	      this.animode = 1; // Fade up
	      this.content = this.newcontent;
	      this.format = this.newformat;
	    }

	  if (this.onfadedown != null && this.onfadedown != "")
	    eval(this.onfadedown);
	}
    }

  if (this.animode == 1 || this.animode >= 3)
    setTimeout( this.myhome+".animateframe();", framedelay_in_ms);
}

function FadeTextArea_redraw()
{
  var colstep, newcol;  // ColorStyle objects.
  var lay1, lay2, nextlay, prevlay;  // layers

  if (this.animode == 1) // Fade up
    if (this.colindex < this.format.time_fadeup)
      colstep = this.format.colstepup;
    else
      newcol = this.format.fgcol;
  else if (this.animode >= 3) // Fade down
    if (this.colindex > 0)
      colstep = this.format.colstepdown;
    else
      newcol = this.format.bgcol;

  if (newcol == null)
    {
      newcol = new ColorStyle();

      newcol.set_color_rgb(Math.floor(this.format.bgcol.r+this.colindex*colstep.r+0.5),
			   Math.floor(this.format.bgcol.g+this.colindex*colstep.g+0.5),
			   Math.floor(this.format.bgcol.b+this.colindex*colstep.b+0.5));
    }

  if ((document.all || document.getElementById) &&
      this.animode == 1 && this.colindex <= steps_per_frame)
    { // If we are starting fade up: hide, change color, then show.
      this.style.visibility = "hidden";

      if (browserName == 'Netscape' &&
	  (this.innerHTML == null || this.innerHTML == ""))
	{ // Netscape 6 Preview v.1 has no innerHTML. Use DOM.
	  var newRange = this.mywin.document.createRange();
	  newRange.setStartBefore(this);
	  var strFrag = newRange.createContextualFragment(this.content);
	  while (this.hasChildNodes()) this.removeChild(this.lastChild);
	  this.appendChild(strFrag);
	}
      else if (this.innerHTML != this.content)
	this.innerHTML = this.content;
    }
  else if (document.layers) /* NS4 */
    { // In NS4, we use TWO layers (embedded within an ilayer.)
      // We always write to a HIDDEN layer (THIS PREVENTS SCREEN FLICKER)
      // then move that layer on top of prev. layer and expose it AFTER writing!
      lay1 = this.document.layers[0];
      lay2 = this.document.layers[1];

      if (lay2.hidden == true)
	{ nextlay = lay2; prevlay = lay1; }
      else
	{ // lay2 is visible.
	  nextlay = lay1; prevlay = lay2; 
	  if (nextlay.hidden == false) nextlay.hidden = true;
	}
    }

  if (this.animode == 1 ||     // Fade up or
      (this.animode >= 3 && this.colindex > 0)) // Fade down
    if (document.all || document.getElementById)
      this.style.color = newcol.colorstring;
    else if (document.layers && this.content != null)
      { // NS4: this is really a layer object. WRITE HIDDEN LAYER.
	nextlay.document.open();
	nextlay.document.write(this.format.preformat+
			       "<FONT COLOR=\"" + newcol.colorstring + "\">" +
			       this.content+"</FONT>"+this.format.postformat);
	nextlay.document.close();
      }

  if (document.all || document.getElementById)
    { // IE4 or NS6
      if (this.animode == 1 && this.colindex <= steps_per_frame)
	this.style.visibility = "visible"; // Starting fade up
      else if (this.animode >= 3 && this.colindex == 0)
	this.style.visibility = "hidden";  // Finishing fade down
    }
  else if (document.layers) // NS4
    {
      if (this.animode == 1 ||
	  (this.animode >= 3 && this.colindex > 0))
	{
	  nextlay.zIndex = 2;
	  prevlay.zIndex = 1;
	  nextlay.hidden = false; // EXPOSE LAYER
	  prevlay.hidden = true;
	  if (this.animode == 1 && this.colindex <= steps_per_frame)
	    this.hidden = false;  // First step in fade up.
	}
      else if (this.animode >= 3 && this.colindex == 0)
	{ // Last step in fade down.
	  this.hidden = true;
	  nextlay.hidden = true; 
	  prevlay.hidden = true;
	}
    }
}

function FadeTextArea_fadeup()
{
  // Mode 0 is hidden, 1 is fade up, 2 is visible, 3 is fade down
  if (this.animode == 0) // Static off
    {
      this.colindex = 0;
      this.animode = 1; // Fade up
      if (this.format.time_initdelay > 0) // delay before start of fade up
	this.timeup =
	    setTimeout(this.myhome+".animateframe();",
		       Math.floor((this.format.time_initdelay*1000)/onesecond));
      else // go now
	this.animateframe();
    }
  else if (this.animode == 2) // Static on
    {
      this.animode = 1; // Fade up
      this.animateframe();
    }
  else if (this.animode >= 3) // Was fading down, now mouse enters
    {
      this.animode = 1; // Fade up
      this.colindex =
	  Math.floor((this.colindex*this.format.time_fadeup)/
		     this.format.time_fadedown+0.5);
    }
}

function FadeTextArea_fadedown()
{
  if (this.timeup != null)
    {
      clearTimeout( this.timeup);
      this.timeup = null;
      if (this.animode == 1)
	this.animode = 0; // stopped delayed fadeup from starting
      else
	this.animode = 2; // prevented auto-fade-down
    }

  if (this.animode == 2) // Static
    this.colindex = this.format.time_fadedown;

  if (this.animode == 0 || this.animode == 2) // Static
    {
      this.animode = 3; // Fade down
      this.animateframe();
    }
  else if (this.animode == 1) // Was fading up, now mouse leaves
    {
      this.animode = 3; // Fade down
      this.colindex = 
	  Math.floor((this.colindex*this.format.time_fadedown)/
		     this.format.time_fadeup+0.5);
    }
}

function FadeTextArea_fadeup_afterfadedown( newform, newtext)
{
  if (this.timeup != null)
    {
      clearTimeout( this.timeup);
      this.timeup = null;
      if (this.animode == 1)
	this.animode = 0; // stopped delayed fadeup from starting
      else
	this.animode = 2; // prevented auto-fade-down
    }

  if (this.animode == 0) // Static off. Fade up normally.
    {
      this.content = newtext;
      this.format = newform;
      this.fadeup();
    }
  else
    {
      this.newcontent = newtext;
      this.newformat = newform;

      if (this.animode == 2) // Static on
	{
	  this.colindex = this.format.time_fadedown;
	  this.animode = 4; // Fade down, then up
	  this.animateframe();
	}
      else if (this.animode == 1) // Was fading up
	{
	  this.animode = 4; // Fade down, then up
	  this.colindex = 
	      Math.floor((this.colindex*this.format.time_fadedown)/
			 this.format.time_fadeup+0.5);
	}
      else
	this.animode = 4;
    }
}

function newFadeTextArea( winname, divid, layerid)
{ // This functions like "constructor" of FadeTextArea object (not true constructor.)
  // divid is id (string) of caption's enclosing DIV within document. 
  // layerid is id (string) of caption's enclosing ilayer (for NS4). 
  // Winname is name of window with TextArea in it (example: "window","parent".)
  // Returns reference to initialized object.
  var newarea, win;

  win = eval( winname);

  if (document.all && divid != null && divid != '')  /* IE4 */
    {
      newarea = win.document.all[divid];
      newarea.myhome = winname+".document.all."+divid;
    }
  else if (document.getElementById && divid != null && divid != '')
    {
      newarea = win.document.getElementById(divid);
      newarea.myhome = winname+".document.getElementById(\""+divid+"\")";
    }
  else if (document.layers && layerid != null && layerid != '') /* NS4 */
    {
      newarea = win.document.layers[layerid];
      if (newarea == null) return null; // In NS4, document not yet loaded.
      newarea.myhome = winname+".document.layers."+layerid;
    }

  newarea.mywin = win;

  // ANIMATION PROPERTIES.
  // Mode 0 is hidden, 1 is fade up, 2 is visible, 3 is fade down
  newarea.animode = 0;
  newarea.colindex = 0;
  newarea.content = "undefined";
  newarea.format = null;

  // Member functions.
  newarea.animateframe = FadeTextArea_animateframe;
  newarea.redraw = FadeTextArea_redraw;
  newarea.set_format = FadeTextArea_set_format;
  newarea.set_content = FadeTextArea_set_content;
  newarea.fadeup = FadeTextArea_fadeup;
  newarea.fadedown = FadeTextArea_fadedown;
  newarea.fadeup_afterfadedown = FadeTextArea_fadeup_afterfadedown;

  newarea.initialized = true;

  return newarea;
}

function fadeup( winname, divid, layerid)
{ // divid is id (string) of text area's enclosing DIV within document. 
  // layerid is id (string) of text area's enclosing ilayer (for NS4).
  // Winname is name of window with TextArea in it (example: "window","parent".)
  var areaobj, win;
  win = eval( winname);

  if (document.all && divid != null && divid != '')  /* IE4 */
    areaobj = win.document.all[divid];
  else if (document.getElementById && divid != null && divid != '')  /* NS6 */
    areaobj = win.document.getElementById(divid);
  else if (document.layers && layerid != null && layerid != '') /* NS4 */
    areaobj = win.document.layers[layerid];

  if (jsversn_1p1 == false) return;

  if (areaobj == null || areaobj.initialized == null)
    { // Not initialized. Initialize via pseudo-constructor.
      areaobj = newFadeTextArea( winname, divid, layerid);
      if (areaobj == null) return;  // In NS4, document not yet loaded.
    }

  areaobj.fadeup();
}

function fadedown( winname, divid, layerid)
{ // divid is id (string) of text area's enclosing DIV within document. 
  // layerid is id (string) of text area's enclosing ilayer (for NS4).
  // Winname is name of window with TextArea in it (example: "window","parent".)
  var areaobj, win;
  win = eval( winname);

  if (document.all && divid != null && divid != '')  /* IE4 */
    areaobj = win.document.all[divid];
  else if (document.getElementById && divid != null && divid != '')  /* NS6 */
    areaobj = win.document.getElementById(divid);
  else if (document.layers && layerid != null && layerid != '') /* NS4 */
    areaobj = win.document.layers[layerid];

  if (areaobj == null || areaobj.initialized == null || jsversn_1p1 == false) 
    return;

  areaobj.fadedown();
}

function fadeup_afterfadedown( winname, divid, layerid, newform, newtext)
{ // divid is id (string) of text area's enclosing DIV within document. 
  // layerid is id (string) of text area's enclosing ilayer (for NS4).
  // Winname is name of window with TextArea in it (example: "window","parent".)
  var areaobj, win;
  win = eval( winname);

  if (document.all && divid != null && divid != '')  /* IE4 */
    areaobj = win.document.all[divid];
  else if (document.getElementById && divid != null && divid != '')  /* NS6 */
    areaobj = win.document.getElementById(divid);
  else if (document.layers && layerid != null && layerid != '') /* NS4 */
    areaobj = win.document.layers[layerid];

  if (jsversn_1p1 == false) return;

  if (areaobj == null || areaobj.initialized == null)
    { // Not initialized. Initialize via pseudo-constructor.
      areaobj = newFadeTextArea( winname, divid, layerid);
      if (areaobj == null) return;  // In NS4, document not yet loaded.
    }

  areaobj.fadeup_afterfadedown( newform, newtext);
}

