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';
  }

  this.onmouseover   = null;
  this.onmouseout    = null;
  this.onclick       = null;

  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;position:relative; ';
    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;
    }

    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) {
        this.onbounce();
      }
      this.dirsign = -1 * this.dirsign;
      var temp     = this.stopAt;
      this.stopAt  = this.startAt;
      this.startAt = temp;
    } else {
      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) {
    val = this.styleObj.document[propName];
  } else if (typeof(this.styleObj[propName]) == 'number') {
    if (propName == 'width' && typeof(this.div.clientWidth) == 'number')
      val = this.div.clientWidth;
    else
      val =  this.styleObj[propName];
  } else {
    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;
};