﻿// JScript File

// Constructor for the class
function DynamicToolbar(listId, maxRows, backColor, alternateBackColor, dropColor, separatorColor)
{
  this._items = new Array();
  this._moreItems = new Array();
  this._dropItems = new Array();
  this._maxRows = maxRows;  
  this._backColor = backColor;
  this._alternateBackColor = alternateBackColor;

  // Grab the UL list element, store it, and add a dynamic property to it that references this class
  this._listElement = document.getElementById(listId);
  this._listElement.dynamicToolbar = this;
  
  var dropWidth = 0;
  var items = this._listElement.getElementsByTagName('LI');
  var item;
  var n;
  var i;
  var s;
  
  item = items[items.length - 1];
  // Assign mouseover and mouseout events to the More Items LI item, which must
  // be the last item in the array 
  item.onmouseover = function() { document.getElementById(listId).dynamicToolbar.onMenuOver(); };
  item.onmouseout  = function() { document.getElementById(listId).dynamicToolbar.onMenuOut(); };
  
  // Create some reusable functions for timers
  this._timerFunc  = function() { document.getElementById(listId).dynamicToolbar.onTimer(); };
  this._scrollFunc = function() { document.getElementById(listId).dynamicToolbar.onScroll(0); };
  
  // Create a dropping DIV which is dynamically hidden and shown when More Items is moused over  
  this._dropElement = document.createElement('DIV');
  this._dropElement.style.position = 'absolute';
  this._dropElement.style.display  = 'none';
  this._dropElement.className      = 'TbDrop';
  this._dropElement.onmouseover    = item.onmouseover;
  this._dropElement.onmouseout     = item.onmouseout;
  // Append it to the main document body
  this._listElement.parentNode.insertBefore(this._dropElement, this._listElement);
  
  // Create the UP button
  this._buttonUp                          = document.createElement('DIV');
  this._buttonUp.style.backgroundColor    = this._backColor;
  this._buttonUp.style.borderBottom       = '1px solid ' + separatorColor;
  this._buttonUp.style.backgroundPosition = 'top center';
  this._buttonUp.style.backgroundRepeat   = 'no-repeat';
  this._buttonUp.style.height             = 18;
  this._buttonUp.className                = 'TbScrollUp';
  this._buttonUp.unselectable             = 'on';
  this._buttonUp.onmousedown              = function() { document.getElementById(listId).dynamicToolbar.onScroll(-1); };
  this._buttonUp.onmouseup                = function() { document.getElementById(listId).dynamicToolbar.onScrollEnd(); };
  this._dropElement.appendChild(this._buttonUp);
  
  // Copy all the toolbar elements from the list to the dropdown div
  for (n = 0; n < items.length; n++)
  {     
    if (!items[n].attributes['dropped'])
    {
      this._items[this._items.length] = items[n];
      if (n == items.length - 1) break;
    }
    else
      items[n].style.display = 'none';    
    
    item = document.createElement('DIV');

    item.className = items[n].className;
    item.innerHTML = items[n].innerHTML;
    
    for (i = 0; i < item.childNodes.length; i++)
    {
      DynamicToolbar__stripBorders(item.childNodes[i]);
    }
    
    if (!items[n].attributes['dropped'])
    {
      this._moreItems[n] = item;
      this._dropElement.appendChild(item);
    }
    else
    {
      item.dropped = true;
      item.style.backgroundColor = dropColor;
      this._dropItems[this._dropItems.length] = item;
    }
          
    // Keep recording the largest toolbar item so we can set the width of the drop to it
    if (dropWidth < items[n].offsetWidth)
      dropWidth = items[n].offsetWidth;
  }
  // This way the drop will always be large enough to hold the largest toolbar item
  this._dropElement.style.width = dropWidth + 4;
  
  // Create the scroll DOWN button
  this._buttonDown                          = document.createElement('DIV');
  this._buttonDown.style.backgroundColor    = this._backColor;
  this._buttonDown.style.borderTop          = '1px solid ' + separatorColor;
  this._buttonDown.style.backgroundPosition = 'top center';
  this._buttonDown.style.backgroundRepeat   = 'no-repeat';
  this._buttonDown.style.height             = 18;
  this._buttonDown.className                = 'TbScrollDown';
  this._buttonDown.unselectable             = 'on';
  this._buttonDown.onmousedown              = function() { document.getElementById(listId).dynamicToolbar.onScroll(1); };
  this._buttonDown.onmouseup                = function() { document.getElementById(listId).dynamicToolbar.onScrollEnd(); };  
  this._dropElement.appendChild(this._buttonDown);

  for (n = 0; n < this._dropItems.length; n++)
  {
    this._dropElement.appendChild(item);
  }
  
  // Append a resize event to the document
  var func = function() { document.getElementById(listId).dynamicToolbar.onResize(); };
  var mousedown = null;
  
  if (window.attachEvent)
  {
    window.attachEvent('onresize', func);
    if (mousedown) document.body.attachEvent('ondragstart', mousedown);
  }
  else if (window.addEventListener)
  {
    window.addEventListener('resize', func, true);
    if (mousedown) window.addEventListener('dragstart', mousedown, true);
  }
  
  this.onResize();
  this.onTimer();
}

function DynamicToolbar__stripBorders(elem)
{
  var i = elem.style;
  if (i)
    i.border = '0px';
  
  i = elem.childNodes;
  if (i)
  {
    for (var n = 0; n < i.length; n++)
    {
      DynamicToolbar__stripBorders(i[n]);
    }
  }
}

function DynamicToolbar__computeVisibility()
{
  var dropItems = 0;
  var alt = 1;
  // Only display _scrollVisibleMax items in the list, and color them dynamically with alternating colors  
  for (var n = 0; n < this._moreItems.length; n++)
  {
    if (n < this._scrollPos || n - this._scrollPos >= this._scrollVisibleMax)
      this._moreItems[n].style.display = 'none';
    else
    {
      this._moreItems[n].style.display = '';
      this._moreItems[n].style.backgroundColor = (alt == 0) ? this._backColor : this._alternateBackColor;
      alt = (alt == 0);
      dropItems ++;
    }
  }

  this._buttonUp.className = ((this._scrollPos == this._showing) ? 'TbScrollUpDisabled':'TbScrollUp');
  this._buttonDown.className = ((this._scrollPos >= (this._moreItems.length - this._scrollVisibleMax)) ? 'TbScrollDownDisabled':'TbScrollDown');
  
  this._buttonUp.style.display = (this._moreItems.length - this._showing <= this._scrollVisibleMax) ? 'none':'';
  this._buttonDown.style.display = this._buttonUp.style.display;

  return dropItems + this._dropItems.length;
}

function DynamicToolbar_onMenuOver()
{
  if (this._timer != null)
  {
    window.clearTimeout(this._timer);
    this._timer = null;
  }
  
  // If we're already showing the drop menu, then don't recompute it, its already on screen
  if (this._dropElement.display == '') return;
    
  if (this._computeVisibility() == 0) return; // Nothing to show
   
  // Show the drop
  this._dropElement.style.display = '';
  
  // Position the drop so its fully visible
  var elem = this._items[this._items.length - 1];
  var x = this._items[0].offsetLeft;
  var y = elem.offsetHeight;
  while (elem)
  {
    x += elem.offsetLeft;
    y += elem.offsetTop;
    elem = elem.offsetParent;
  }
  if (x + this._dropElement.offsetWidth > document.body.clientWidth)
    x = document.body.clientWidth - this._dropElement.offsetWidth;
  
  if (y + this._dropElement.offsetHeight > document.body.clientHeight)
    y -= (this._dropElement.offsetHeight + this._items[0].offsetHeight);
    
  this._dropElement.style.left = x + 'px';
  this._dropElement.style.top = y + 1 + 'px'; 
}

function DynamicToolbar_onTimer()
{
  // Hide the drop
  this._dropElement.style.display = 'none';
  this._dropElement.style.left = -10000;
  this._timer = null;
}

function DynamicToolbar_onMenuOut()
{
  this.onScrollEnd();
  if (this._timer) window.clearTimeout(this._timer);
  this._timer = window.setTimeout(this._timerFunc, 250);
}

function DynamicToolbar_onResize()
{
  var n;  
  var currWidth = 0;
  var rows = 0;
  var more = this._items[this._items.length - 1];
  var top = null;
  var elem;
  
  // For each button after the first, determine if its presence would scroll the toolbar list
  // if it would scroll, then hide it and show it in the More Items drop
  n = 0;
  while (n < this._items.length)
  {
    this._items[n].style.display = '';
    if (top == null) top = this._items[n].offsetTop;
    
    if (this._items[n].offsetTop > top)
    {
      rows ++;
      if (rows >= this._maxRows)
      {
        break;
      }
      top = this._items[n].offsetTop;
    }
    n++;
  }
  
  n = this._items.length - 1;
  while (more.offsetTop > top)
  {
    n --;
    this._items[n].style.display = 'none';
    if (n == 0) break;
  }
  
  // Set the drop to the first visible item
  this._showing = n;
  this._scrollPos = n;
  
  // Make sure all the items after this item in the main toolbar is hidden
  for (;n < this._items.length - 1; n++)
    this._items[n].style.display = 'none';   
}

function DynamicToolbar_onScroll(direction)
{
  if (direction == 0) // Timer event
  {
    if (this._scrollInterval == null) // First timer triggered, start the interval
    {
      window.clearTimeout(this._scrollTimer);
      this._scrollTimer = null;
      this._scrollInterval = window.setInterval(this._scrollFunc, 120);
    }
    direction = this._scrollDirection;
  }
  else
  {
    this._scrollDirection = direction;
    this.onScrollEnd();
    this._scrollTimer = window.setTimeout(this._scrollFunc, 350);
  }
  
  direction = this._scrollPos + direction;
  
  if (direction < this._showing
   || direction > ((this._moreItems.length) - this._scrollVisibleMax))
    return;
  
  this._scrollPos = direction;
  this._computeVisibility();
}

function DynamicToolbar_onScrollEnd()
{
  if (this._scrollTimer)
    window.clearTimeout(this._scrollTimer);
  if (this._scrollInterval)
    window.clearInterval(this._scrollInterval);
    
  this._scrollInterval = null;
  this._scrollTimer = null;
}

// Prototypes
DynamicToolbar.prototype._items              = null;
DynamicToolbar.prototype._moreItems          = null;
DynamicToolbar.prototype._dropItems          = null;
DynamicToolbar.prototype._showing            = 0;
DynamicToolbar.prototype._scrollPos          = 0;
DynamicToolbar.prototype._backColor          = 'blue';
DynamicToolbar.prototype._alternateBackColor = 'green';
DynamicToolbar.prototype._listElement        = null;
DynamicToolbar.prototype._buttons            = null;
DynamicToolbar.prototype._dropElement        = null;
DynamicToolbar.prototype._buttonUp           = null;
DynamicToolbar.prototype._buttonDown         = null;
DynamicToolbar.prototype._timer              = null;
DynamicToolbar.prototype._timerFunc          = null;
DynamicToolbar.prototype._scrollTimer        = null;
DynamicToolbar.prototype._scrollInterval     = null;
DynamicToolbar.prototype._scrollFunc         = null;
DynamicToolbar.prototype._scrollDirection    = 0;
DynamicToolbar.prototype._scrollVisibleMax   = 6;
DynamicToolbar.prototype._maxRows            = 1;

DynamicToolbar.prototype.onMenuOver  = DynamicToolbar_onMenuOver;
DynamicToolbar.prototype.onMenuOut   = DynamicToolbar_onMenuOut;
DynamicToolbar.prototype.onResize    = DynamicToolbar_onResize;
DynamicToolbar.prototype.onTimer     = DynamicToolbar_onTimer;
DynamicToolbar.prototype.onScroll    = DynamicToolbar_onScroll;
DynamicToolbar.prototype.onScrollEnd = DynamicToolbar_onScrollEnd;

DynamicToolbar.prototype._computeVisibility = DynamicToolbar__computeVisibility;
