/*
 * $Log: xbMarquee.js,v $
 * Revision 1.13  2002/08/12 21:09:50  bc6ix
 * fix mismatched quote in ilayer for NN4
 *
 * Revision 1.12  2002/08/08 08:26:44  bc6ix
 * fix IE4 where parentNode not supported, use non standard parentElement instead
 *
 * Revision 1.11  2002/07/22 14:19:42  bc6ix
 * fix license path
 *
 * Revision 1.10  2002/07/11 11:20:56  bc6ix
 * work around Opera width bug
 *
 * Revision 1.9  2002/07/01 15:10:48  bc6ix
 * rework IE nowrap fix
 *
 * Revision 1.8  2002/06/29 03:37:40  bc6ix
 * fix wrapping problem in IE reported by Jeremy Hoppe
 *
 * Revision 1.7  2002/06/20 03:39:49  bc6ix
 * make xbMarquee invisible during loading
 *
 * Revision 1.6  2002/06/19 17:04:50  bc6ix
 * add percent height/width
 *
 * Revision 1.5  2002/06/15 06:31:28  bc6ix
 * add event handlers
 *
 * Revision 1.4  2002/06/09 05:41:43  bc6ix
 * add setInnerHTML() method
 *
 * Revision 1.3  2002/06/08 23:38:01  bc6ix
 * fix copyright date
 *
 * Revision 1.2  2002/06/06 20:36:42  bc6ix
 * Move navigator 4 layer initialization into start
 *
 * Revision 1.1  2002/06/06 17:58:38  bc6ix
 * xbMarquee Initial version
 *
 */

/* ***** BEGIN LICENSE BLOCK *****
 * Licensed under Version: MPL 1.1/GPL 2.0/LGPL 2.1
 * Full Terms at /xbProjects-license/mpl-tri-license.txt
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Netscape code.
 *
 * The Initial Developer of the Original Code is
 * Netscape Corporation.
 * Portions created by the Initial Developer are Copyright (C) 2002
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s): Doron Rosenberg <doron@netscape.com>
 *                 Bob Clary <bclary@netscape.com>
 *
 * ***** END LICENSE BLOCK ***** */

function xbMarquee(id, height, width, scrollAmount, scrollDelay, direction, behavior, html)
{
  this.id            = id;
  this.scrollAmount  = scrollAmount ? scrollAmount : 6;
  this.scrollDelay   = scrollDelay ? scrollDelay : 85;
  this.direction     = direction ? direction.toLowerCase() : 'left';  
  this.behavior      = behavior ? behavior.toLowerCase() : 'scroll';  
  this.name          = 'xbMarquee_' + (++xbMarquee._name);
  this.runId         = null;
  this.html          = html;

  if (typeof(height) == 'number')
  {
    this.height = height;
    this.heightUnit = 'px';
  }
  else if (typeof(height) == 'string')
  {
    this.height = parseInt('0' + height, 10);
    this.heightUnit = height.toLowerCase().replace(/^[0-9]+/, '');
  }
  else
  {
    this.height = 100;
    this.heightUnit = 'px';
  }

  if (typeof(width) == 'number')
  {
    this.width = width;
    this.widthUnit = 'px';
  }
  else if (typeof(width) == 'string')
  {
    this.width = parseInt('0' + width, 10);
    this.widthUnit = width.toLowerCase().replace(/^[0-9]+/, '');
  }
  else
  {
    this.width = 100;
    this.widthUnit = 'px';
  }

  // xbMarquee UI events
  this.onmouseover   = null;
  this.onmouseout    = null;
  this.onclick       = null;
  // xbMarquee state events
  this.onstart       = null;
  this.onbounce      = null;

  var markup = '';

  if (document.layers)
  {
    markup += '<ilayer id="' + this.id + 'container" name="' + this.id + 'container" height="' + height + '" width="' + width + '"  clip="' + width + ', ' + height + '">';
    markup += '<\/ilayer>';
  }
  else 
  {
    var isHorizontal = ('up,down'.indexOf(this.direction) == -1);
    markup         += '<div id="' + this.id + 'container" name="' + this.id + 'container" style="overflow: hidden; ';
    if (this.heightUnit != '%')
    {
      markup += 'height: ' + this.height + this.heightUnit + '; ';
    }
    if (this.widthUnit != '%')
    {
      markup += 'width: ' + this.width + this.widthUnit + '; ';
    }
    markup += '">';
    markup += '<div id="' + this.id + '" name="' + this.id + '" style="position:absolute; visibility: hidden;';
    if (!document.all && isHorizontal)
    {
      markup += 'white-space:nowrap;';
    }
    markup += '" ';
    markup += 'onmouseover="xbMarqueeDispatchUIEvent(event, \'' + this.name + '\', \'mouseover\')" ';
    markup += 'onmouseout="xbMarqueeDispatchUIEvent(event, \'' + this.name + '\', \'mouseout\')" ';
    markup += 'onclick="xbMarqueeDispatchUIEvent(event, \'' + this.name + '\', \'click\')" ';
    markup += '>';
    if (document.all && isHorizontal)
    {
      markup += '<nobr>';
    }
    markup += html;
    if (document.all && isHorizontal)
    {
      markup += '<\/nobr>';
    }
    markup += '<\/div>';
    markup += '<\/div>';
  }
  document.write(markup);

  window[this.name] = this;
}

xbMarquee._name = -1;

xbMarquee.prototype.start = function ()
{
  this.stop();

  if (!this.dirsign)
  {
    if (document.getElementById)
    {
      this.containerDiv = document.getElementById(this.id + 'container');
      this.div          = document.getElementById(this.id);
      this.styleObj     = this.div.style;
      if (this.heightUnit == '%')
      {
        this.containerDiv.style.height = this.containerDiv.parentNode.offsetHeight * (this.height/100) + 'px';
      }
      if (this.widthUnit == '%')
      {
        this.containerDiv.style.width = this.containerDiv.parentNode.offsetWidth * (this.width/100) + 'px';
      }

      this.styleObj.position = 'relative';
      this.styleObj.visibility = 'visible';
    }
    else if (document.all)
    {
      this.containerDiv = document.all[this.id + 'container'];
      this.div          = document.all[this.id];
      this.styleObj     = this.div.style;
      if (this.heightUnit == '%')
      {
        this.containerDiv.style.height = this.containerDiv.parentElement.offsetHeight * (this.height/100) + 'px';
      }
      if (this.widthUnit == '%')
      {
        this.containerDiv.style.width = this.containerDiv.parentElement.offsetWidth * (this.width/100) + 'px';
      }

      this.styleObj.position = 'relative';
      this.styleObj.visibility = 'visible';
    }
    else if (document.layers)
    {
      this.containerDiv = document.layers[this.id + 'container'];
      var markup = '';
      markup += '<layer id="' + this.id + '" name="' + this.id + '" top="0" left="0" ';
      markup += 'onmouseover="xbMarqueeDispatchUIEvent(event, \'' + this.name + '\', \'mouseover\')" ';
      markup += 'onmouseout="xbMarqueeDispatchUIEvent(event, \'' + this.name + '\', \'mouseout\')" ';
      markup += 'onclick="xbMarqueeDispatchUIEvent(event, \'' + this.name + '\', \'click\')" ';
      markup += '>';
      if ('left,right'.indexOf(this.direction) != -1)
      {
        markup += '<nobr>';
      }
      markup += this.html;
      if ('left,right'.indexOf(this.direction) != -1)
      {
        markup += '<\/nobr>';
      }
      markup += '<\/layer>';
      this.containerDiv.document.write(markup);
      this.containerDiv.document.close();
      this.div          = this.containerDiv.document.layers[this.id];
      this.styleObj     = this.div;
    }

    // Start must not run until the page load event has fired
    // due to Internet Explorer not setting the height and width of 
    // the dynamically written content until then
    switch (this.direction)
    {
    case 'down':
      this.dirsign = 1;
      this.startAt = this.styleObj.top = -1 * this._getInnerSize('height');
      this.stopAt  = this.height;
      break;

    case 'up':
      this.dirsign = -1;
      this.startAt = this.styleObj.top = this.height;
      this.stopAt  = -this._getInnerSize('height');
      break;

    case 'right':
      this.dirsign = 1;
      this.startAt = this.styleObj.left = -1 *this._getInnerSize('width');
      this.stopAt  = this.width;
      break;

    case 'left':
    default:
      this.dirsign = -1;
      this.startAt = this.width
      this.stopAt  = -this._getInnerSize('width');
      break;
    }
    this.newPosition          = this.startAt;
    this.styleObj.visibility = 'visible'; 
  }

  this.newPosition += this.dirsign * this.scrollAmount;

  if ( (this.dirsign == 1  && this.newPosition > this.stopAt) ||
       (this.dirsign == -1 && this.newPosition < this.stopAt) )
  {
    if (this.behavior == 'alternate')
    {
      if (this.onbounce)
      {
        // fire bounce when alternate changes directions
        this.onbounce();
      }
      this.dirsign = -1 * this.dirsign;
      var temp     = this.stopAt;
      this.stopAt  = this.startAt;
      this.startAt = temp;
    }
    else
    {
      // fire start when position is a start
      if (this.onstart)
      {
        this.onstart();
      }
      this.newPosition = this.startAt;
    }
  }
  
  switch(this.direction)
  {
    case 'up': 
    case 'down':
      this.styleObj.top = this.newPosition;
      break;

    case 'left': 
    case 'right':
    default:
      this.styleObj.left = this.newPosition;
      break;
  }

  this.runId = setTimeout(this.name + '.start()', this.scrollDelay);
};

xbMarquee.prototype.stop = function ()
{
  if (this.runId)
    clearTimeout(this.runId);
    
  this.runId = null;
};


xbMarquee.prototype.setInnerHTML = function (html)
{
  if (typeof(this.div.innerHTML) != 'string')
  {
    return;
  }

  var running = false;
  if (this.runId)
  {
    running = true;
    this.stop();
    this.dirsign = null;
  }
  this.html = this.div.innerHTML = html;
  if (running)
  {
    this.start();
  }
};

xbMarquee.prototype._getInnerSize = function (propName)
{
  var val = 0;

  if (document.layers)
  {
    // navigator 4
    val = this.styleObj.document[propName];
  }
  else if (typeof(this.styleObj[propName]) == 'number')
  {
    // opera
    // bug in Opera 6 width/offsetWidth. Use clientWidth
    if (propName == 'width' && typeof(this.div.clientWidth) == 'number')
      val = this.div.clientWidth;
    else
      val =  this.styleObj[propName];
  }
  else
  {
    //mozilla and IE
    switch (propName)
    {
    case 'height':
       if (typeof(this.div.offsetHeight) == 'number')
         val =  this.div.offsetHeight;
       if (val == 0)
         val =  this.height;
       break;
    case 'width':
       if (typeof(this.div.offsetWidth) == 'number')
         val = this.div.offsetWidth;
       if (val == 0)
         val =  this.width;
       break;
    }
  }

  return val;

};

xbMarqueeDispatchUIEvent = function (event, marqueeName, eventName)
{
  var marquee = window[marqueeName];
  var eventAttr = 'on' + eventName;
  if (!marquee)
  {
    return false;
  }

  if (!event && window.event)
  {
    event = window.event;
  }

  switch (eventName)
  {
  case 'mouseover':
  case 'mouseout':
  case 'click':
    if (marquee[eventAttr])
      return marquee['on' + eventName](event);
  }

  return false;
};


