/*****************************************************
 * ypSlideOutMenu
 * 3/04/2001
 *
 * a nice little script to create exclusive, slide-out
 * menus for ns4, ns6, mozilla, opera, ie4, ie5 on
 * mac and win32. I've got no linux or unix to test on but
 * it should(?) work...
 *
 * --youngpup--
 *****************************************************/

function initMenus() {

  ypSlideOutMenu.currWidth = document.documentElement.offsetWidth;
  ypSlideOutMenu.Registry = [];
  ypSlideOutMenu.aniLen = 350;
  ypSlideOutMenu.hideDelay = 1000;
  ypSlideOutMenu.minCPUResolution = 10;
}
initMenus();

window.onresize =
  function (e) {

    if(ypSlideOutMenu.currWidth != document.documentElement.offsetWidth) {
      initMenus();
      setUpMenus();
      return false;
    }
  }

// constructor
function ypSlideOutMenu(id, dir, offset, padding) {
  this.ie  = document.all ? 1 : 0;
  this.ns4 = document.layers ? 1 : 0;
  this.dom = document.getElementById ? 1 : 0;
  this.HTML_ELEMENT = 1;

  if (this.ie || this.ns4 || this.dom) {

    this.id = id;
    this.dir = dir;
    this.orientation = dir == "left" || dir == "right" ? "h" : "v";
    this.dirType = dir == "right" || dir == "down" ? "-" : "+";
    var left, top, height, width;
    var link, pos, div, div_pos;
    link = document.getElementById(id + 'Link');
    pos = this.findPos(link);
    div = document.getElementById(id + 'Content');
    div_pos = this.findPos(div);
    height = div_pos['height'] + padding;
    width = 0;
    var children = div.childNodes;
    for(var i = 0; i < children.length; i++) {
      if(children[i].nodeType == this.HTML_ELEMENT) {
        var children2 = children[i].childNodes;
        for(var j = 0; j < children2.length; j++) {
          if(children2[j].nodeType == this.HTML_ELEMENT) {
            var child_pos = this.findPos(children2[j]);
            if(child_pos['width'] > width) {
              width = child_pos['width'] + padding;
            }
          }
        }
      }
    }

    top = (this.orientation == 'h' ? pos['top']
            : (this.dirType == '-'
            ? pos['top'] + pos['height'] + offset
            : pos['top'] - height - offset));
    left = (this.orientation == 'v' ? pos['left']
            : (this.dirType == '-'
            ? pos['left'] + pos['width'] + offset
            : pos['left'] - width - offset));

    this.dim = this.orientation == "h" ? width : height;
    this.hideTimer = false;
    this.aniTimer = false;
    this.open = false;
    this.over = false;
    this.startTime = 0;

    // add this menu object to an internal list of all menus
    ypSlideOutMenu.Registry[id] = this;

    var container = document.getElementById(this.id + 'Container');
    container.style.visibility = 'hidden';
    container.style.left = left + 'px';
    container.style.top = top + 'px';
    container.style.overflow = 'hidden';
    container.style.position = 'absolute';
    container.style.width = width + 'px';
    container.style.height = height + 'px';
    container.style.clip = 'rect(0px,' + width + 'px,' + height + 'px,0px)';
    var content = document.getElementById(this.id + 'Content');
    content.style.position = 'absolute';
    content.style.width = width + 'px';
    content.style.height = height + 'px';
    content.style.clip = 'rect(0px,' + width + 'px,' + height + 'px,0px)';

    this.load();
  }
}

ypSlideOutMenu.prototype.load = function() {
  var d = document;
  var lyrId1 = this.id + "Container";
  var lyrId2 = this.id + "Content";
  var obj1 = this.dom ? d.getElementById(lyrId1) : this.ie ? d.all[lyrId1] : d.layers[lyrId1];
  if (obj1) var obj2 = this.ns4 ? obj1.layers[lyrId2] : this.ie ? d.all[lyrId2] : d.getElementById(lyrId2);
  var temp;

  var menu = this;
  var timeout_function = function() { menu.load(); };
  if (!obj1 || !obj2) window.setTimeout(timeout_function, 100);
  else {
    this.container	= obj1;
    this.menu		= obj2;
    this.style		= this.ns4 ? this.menu : this.menu.style;
    this.homePos	= eval("0" + this.dirType + this.dim);
    this.outPos		= 0;
    this.accelConst	= (this.outPos - this.homePos) / ypSlideOutMenu.aniLen / ypSlideOutMenu.aniLen;

    // set event handlers.
    if (this.ns4) this.menu.captureEvents(Event.MOUSEOVER | Event.MOUSEOUT);
    this.menu.onmouseover = new Function("ypSlideOutMenu.showMenu('" + this.id + "')");
    this.menu.onmouseout = new Function("ypSlideOutMenu.hideMenu('" + this.id + "')");

    //set initial state
    this.endSlide();
  }
}

ypSlideOutMenu.showMenu = function(id) {
  var reg = ypSlideOutMenu.Registry;
  var obj = ypSlideOutMenu.Registry[id];

  if (obj.container) {
    obj.over = true;

    // close other menus.
    for (menu in reg) if (id != menu) ypSlideOutMenu.hide(menu);

    // if this menu is scheduled to close, cancel it.
    if (obj.hideTimer) { reg[id].hideTimer = window.clearTimeout(reg[id].hideTimer); }

    // if this menu is closed, open it.
    if (!obj.open && !obj.aniTimer) reg[id].startSlide(true);
  }
}

ypSlideOutMenu.hideMenu = function(id) {
  // schedules the menu to close after <hideDelay> ms, which
  // gives the user time to cancel the action if they accidentally moused out
  var obj = ypSlideOutMenu.Registry[id];
  if (obj.container) {
    if (obj.hideTimer) window.clearTimeout(obj.hideTimer);
    obj.hideTimer = window.setTimeout("ypSlideOutMenu.hide('" + id + "')", ypSlideOutMenu.hideDelay);
  }
}

ypSlideOutMenu.hideAll = function() {
  var reg = ypSlideOutMenu.Registry;
  for (menu in reg) {
    ypSlideOutMenu.hide(menu);
    if (menu.hideTimer) window.clearTimeout(menu.hideTimer);
  }
}

ypSlideOutMenu.hide = function(id) {
  var obj = ypSlideOutMenu.Registry[id];
  obj.over = false;

  if (obj.hideTimer) window.clearTimeout(obj.hideTimer);

  // flag that this scheduled event has occured.
  obj.hideTimer = 0;

  // if this menu is open, close it.
  if (obj.open && !obj.aniTimer) obj.startSlide(false);
}

ypSlideOutMenu.prototype.startSlide = function(open) {
  this[open ? "onactivate" : "ondeactivate"]();
  this.open = open;
  if (open) this.setVisibility(true);
  this.startTime = (new Date()).getTime();
  var menu = this;
  var timeout_function = function() { menu.slide(); };
  this.aniTimer = window.setInterval(timeout_function, ypSlideOutMenu.minCPUResolution);
}

ypSlideOutMenu.prototype.slide = function() {
  var elapsed = (new Date()).getTime() - this.startTime;
  if (elapsed > ypSlideOutMenu.aniLen) this.endSlide();
  else {
    var d = Math.round(Math.pow(ypSlideOutMenu.aniLen-elapsed, 2) * this.accelConst);
    if (this.open && this.dirType == "-") d = -d;
    else if (this.open && this.dirType == "+") d = -d;
    else if (!this.open && this.dirType == "-")	d = -this.dim + d;
    else d = this.dim + d;
    this.moveTo(d);
  }
}

ypSlideOutMenu.prototype.endSlide = function() {
  this.aniTimer = window.clearTimeout(this.aniTimer);
  this.moveTo(this.open ? this.outPos : this.homePos);
  if (!this.open) this.setVisibility(false);
  if ((this.open && !this.over) || (!this.open && this.over)) {
    this.startSlide(this.over);
  }
}

ypSlideOutMenu.prototype.setVisibility = function(bShow) {
  var s = this.ns4 ? this.container : this.container.style;
  s.visibility = bShow ? "visible" : "hidden";
}
ypSlideOutMenu.prototype.moveTo = function(p) {
  this.style[this.orientation == "h" ? "left" : "top"] = this.ns4 ? p : p + "px";
}
ypSlideOutMenu.prototype.getPos = function(c) {
  return parseInt(this.style[c]);
}

// events
ypSlideOutMenu.prototype.onactivate = function() { };
ypSlideOutMenu.prototype.ondeactivate = function() { };

ypSlideOutMenu.prototype.findPos = function (el) {
  var pos = new Object();

  if (document.getBoxObjectFor) {
    var bo = document.getBoxObjectFor(el);
    pos['top'] = bo.y;
    pos['width'] = bo.width;
    pos['left'] = bo.x;
    pos['height'] = bo.height;
  } else {
    if (el.getBoundingClientRect) {
      var rect = el.getBoundingClientRect();
      pos['top'] = rect.top - 2;
      pos['width'] = rect.right - rect.left;
      pos['left'] = rect.left - 1;
      pos['height'] = rect.bottom - rect.top;
    } else {
      pos['width'] = el.offsetWidth;
      pos['height'] = el.offsetHeight;
      pos['left'] = 0;
      pos['top'] = 0;
      while(el && el != document.body) {
        pos['left'] += el.offsetLeft;
        pos['top'] += el.offsetTop;
        el = el.offsetParent;
      }
    }
  }
  return pos;
}
