/*****************************************************
* 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... 
*
* Revised:
* - 08/29/2002 : added .hideAll()
* - 04/15/2004 : added .writeCSS() to support more 
*                than 30 menus.
*
* --youngpup--
*****************************************************/
ypSlideOutMenu.Registry = [];
ypSlideOutMenu.aniLen = 500;
ypSlideOutMenu.hideDelay = 300;
ypSlideOutMenu.minCPUResolution = 10;
ypSlideOutMenu.baseZindex = 100;
// constructor
function ypSlideOutMenu(id, dir, left, top, width, height)
{
	this.nestedMenus = false; //set this to true to enable menus within menus
	this.ie = document.all ? 1 : 0;
	this.ns4 = document.layers ? 1 : 0;
	this.dom = document.getElementById ? 1 : 0;
	if (this.ie || this.ns4 || this.dom) {
		this.id = id;
		this.dir = dir;
		this.orientation = dir == "left" || dir == "right" ? "h" : "v";
		this.dirType = dir == "left" || dir == "up" ? "-" : "+";
		this.dim = this.orientation == "h" ? width : height;
		this.homePos = this.orientation == "h" ? left : top;
		this.hideTimer = false;
		this.aniTimer = false;
		this.open = false;
		this.over = false;
		this.startTime = 0;
		this.gRef = "ypSlideOutMenu_"+id;
		eval(this.gRef+"=this");
		ypSlideOutMenu.Registry[id] = this;
		this.setContentCSS(this.id + "Content", left, top, width, height);
		this.load(left,top);
	}
}
ypSlideOutMenu.prototype.setContentCSS = function(contentId, left, top, width, height) {
	var d = document;
	var obj = this.dom ? d.getElementById(contentId) : this.ie ? d.all[contentId] : d.layers[contentId];
	var style = this.ns4 ? obj : obj.style;
	style.display = "block";
	style.position = "absolute";
	style.zIndex = ypSlideOutMenu.baseZindex;
	ypSlideOutMenu.baseZindex += 10;
	this.width = width;
	this.height = height;
	style.overflow = "hidden";
//	style.clip = 'rect(0 ' + this.width + 'px ' + this.height + 'px 0)';
}
ypSlideOutMenu.prototype.createMoveableNode = function(obj) {
/* 
	Wrap our menu in a span tag so we can move the content seperately from the menu box itself. THis may create problems if the calling document relies on the menu content being a direct child of the menu node.
*/
	obj.innerHTML = "<span id='moveable"+this.id+"'>" + obj.innerHTML + "</span>";
	this.moveable = document.getElementById('moveable'+this.id);
	this.moveable.style.position = "relative";
	this.moveable.style.display = "block";
	this.moveable.style.left = '0';
	this.moveable.style.top = '0';
//	this.moveable.style.width = this.moveable.offsetWidth + 'px';
/*
	In DOM-compliant browsers, we can ignore the supplied width and height, and get the height and width of the menu from offsetWidth and offsetHeight. This should allow the menu to resize fluidly when items are added or removed, or if the browser font size changes.
	Need to check this in Mozilla and on MacOS.
*/
	if (this.dom) {
		this.width = this.moveable.offsetWidth;
		this.height = this.moveable.offsetHeight;
	}
}
ypSlideOutMenu.prototype.load = function(left,top) {
	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;
	if (!obj1 || !obj2) {
		window.setTimeout(this.gRef + ".load()", 100);
	} else {
		this.container = obj1;
		this.menu = obj2;
		this.createMoveableNode(this.menu);
		this.dim = this.orientation == "h" ? this.width : this.height;
/*
Recalculate the height/width and set the left/top positions according to the new position. Only works if display is 'block' so must set the style first.
If the menu is opening from the left or upwards, we need to move it across/down
in order to avoid an annoying flash of content on the lefthand side or at the top
when it first opens.
*/
		left = this.dirType == "-" && this.orientation == "h" ? left + this.dim: left;
		top = this.dirType == "-" && this.orientation == "v" ? top + this.dim : top;
		this.style = this.ns4 ? this.menu : this.menu.style;
		this.style.left = this.ns4 ? left : left + "px";
		this.style.top = this.ns4 ? top : top + "px";
		this.accelConst = this.dim / ypSlideOutMenu.aniLen / ypSlideOutMenu.aniLen; 
		// set event handlers.
		if (this.ns4) {
			this.menu.captureEvents(Event.MOUSEOVER | Event.MOUSEOUT);
			this.container.captureEvents(Event.MOUSEOVER | Event.MOUSEOUT);
		}
		this.container.onmouseover = new Function("ypSlideOutMenu.showMenu('" + this.id + "')");
		this.container.onmouseout = new Function("ypSlideOutMenu.hideMenu('" + this.id + "')");
		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;
		for (menu in reg) if (id != menu && !ypSlideOutMenu.Registry[menu].over) ypSlideOutMenu.hide(menu);
		if (obj.hideTimer) { reg[id].hideTimer = window.clearTimeout(reg[id].hideTimer) }
		if (!obj.open && !obj.aniTimer) reg[id].startSlide(true);
	}
}
ypSlideOutMenu.hideMenu = function(id)
{
	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];
	if (obj.hideTimer) window.clearTimeout(obj.hideTimer);
	obj.hideTimer = 0;
	if (obj.open && !obj.aniTimer) obj.startSlide(false);
	obj.over = false;
}
ypSlideOutMenu.prototype.startSlide = function(open) {
	this[open ? "onactivate" : "ondeactivate"]();
	this.setDim(open ? 0: this.dim);
	this.moveContent(open ? -1*this.dim : 0);
	this.open = open;
	if (this.menu.style.overflow == 'visible') this.menu.style.overflow = "hidden";
	if (open) {
		this.setVisibility(true);
	} 
	this.startTime = (new Date()).getTime(); 
	this.aniTimer = window.setInterval(this.gRef + ".slide()", ypSlideOutMenu.minCPUResolution);
}
ypSlideOutMenu.prototype.slide = function() {
	var elapsed = (new Date()).getTime() - this.startTime;
	if (elapsed > ypSlideOutMenu.aniLen) {
		this.endSlide();
	} else {
	// position of the top left corner of the menu box. Left and up menus will move this
	// to expand and collapse the menu.
		var p = this.homePos;
	// dimension of the menu box. Changes from this.dim to zero as elapsed goes from
	// zero to aniLen.
		var d = Math.round(Math.pow(ypSlideOutMenu.aniLen-elapsed, 2) * this.accelConst);
	// position of the menu content. Used to slide text around if the direction is down
	// or right.
		var pc = 0;
	// menu opening up/left
		if (this.open && this.dirType == "-") {
			p = this.homePos + d;
			d = this.dim - d;
//			this.cropContent(d);
	// menu opening down/right
		}else if (this.open && this.dirType == "+") {
			pc = -1 * d;
			d = this.dim - d;
	//menu closing up/left
		}else if (!this.open && this.dirType == "-") {
			p = this.homePos + this.dim -d;
//			this.cropContent(d);
		}else {
	// menu closing down/right
			pc = d - this.dim;
		}
		this.moveContent(pc);
		this.setDim(d);
		this.moveTo(p);
	}
}
ypSlideOutMenu.prototype.endSlide = function() {
	this.aniTimer = window.clearTimeout(this.aniTimer);
	this.setDim(this.open ? this.dim : 0);
//	this.moveContent(this.open ? 0 : -1*this.dim);
	if (!this.open) {
		this.setVisibility(false);
	} else {
		if (this.nestedMenus) this.menu.style.overflow = "visible";	
//		this.moveable.style.clip = 'rect(0 1000px 1000px 0)';
	}
	if ((this.open && !this.over) || (!this.open && this.over)) {
		this.startSlide(this.over);
	}
}
ypSlideOutMenu.prototype.setVisibility = function(bShow) { 
	var s = this.ns4 ? this.menu : this.menu.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.moveContent = function(p) { 
	this.moveable.style[this.orientation == "h" ? "left" : "top"] = this.ns4 ? p : p + "px";
}
ypSlideOutMenu.prototype.cropContent = function(p) { 
	this.moveable.style.clip = this.orientation == 'h' ? 'rect(0 ' + p + 'px auto 0)' :'rect(0 auto ' + p + 'px 0)';
}
ypSlideOutMenu.prototype.setDim = function(p) {
	this.style[this.orientation == "h" ? "width" : "height"] = this.ns4 ? p : p + "px";
}
ypSlideOutMenu.prototype.getPos = function(c) {
	return parseInt(this.style[c]);
}
ypSlideOutMenu.prototype.onactivate = function() { }
ypSlideOutMenu.prototype.ondeactivate = function() { }