// menu.js
//
// Written by Ben van Setten, Clemence van Santen (Settembre NL)


// Base object for menus
//
function Library() {
	this.timer_enter = 0;
	this.timer_leave = 0;
	this.hover = null;
	this.visit = null;
	this.menus = new Array();
}
var say = new Library();


// Environment configuration object
//
function Environment() {
	this.nav = navigator.userAgent.toLowerCase();
	this.db  = (document.compatMode && document.compatMode.toLowerCase() != 'backcompat') ?
		document.documentElement : (document.body || null);
	this.op  = !!(window.opera && document.getElementById);
	this.ie  = !!(this.nav.indexOf('msie') >= 0 && document.all && this.db && !this.op);
	this.iem = !!(this.nav.indexOf('msie') >= 0 && this.nav.indexOf('mac') >= 0);
	this.ie4 = !!(this.ie && !document.getElementById);
	this.ie7 = !!(document.documentElement && typeof document.documentElement.style.maxHeight != 'undefined');
	this.ie6 = !!(this.ie && !this.ie7);
	this.ns4 = !!(document.layers && typeof document.classes != 'undefined');
	this.ns6 = !!(typeof window.getComputedStyle != 'undefined'
		&& typeof document.createRange != 'undefined');
	this.swk = !!(navigator.vendor && navigator.vendor.indexOf("Apple") >= 0);
	this.w3c = !!(!this.op && !this.ie && !this.ns6 && document.getElementById);
	this.ce  = !!(document.captureEvents && document.releaseEvents && !this.ns6);
}
say.its = new Environment();


// Build menu
// 
function initiateMenu(rootID, baseID, baseClass) {
	if (!rootID) var rootID = 'menu';
	if (!baseID) var baseID = 'menu';
	if (!baseClass) var baseClass = baseID;
	var container;

	container = document.getElementById(rootID);
	if (!container) {
		container = document.createElement('div');
		if (document.all) {
			if (document.all[0]) {
				document.all[0].appendChild(container);
			}
		}
		else {
			say.its.db.appendChild(container);
		}
	}

	buildMenu(menu, container, baseID, baseClass);
}


// When mouse enters a menu item, show corresponding submenu and clean up others
//
function menuEnter(id, wait) {
	var item;
	if (wait == undefined) var wait = 1000;

	say.hover = id;

	// CSS style shows menu,
	// but when JS is active, menu should be hidden initially
	item = document.getElementById(id);
	if (item && item.style && !say.menus[id]) {
		item.style.visibility = 'hidden';
	}

	say.menus[id] = true;
	clearTimeout(say.timer_enter);
	say.timer_enter = setTimeout('menuOpen()', wait);
	menuClean();
}


// Prevent opening menu if mouseout occurs
//
function menuLeave(id, wait) {
	if (id = say.hover) {
		clearTimeout(say.timer_enter);
	}
}


// Make current menu visible
//
function menuOpen() {
	var	item = document.getElementById(say.hover);
	clearTimeout(say.timer_leave);
	say.timer_leave = setTimeout('menuClear()', 3000);
	if (item && item.style) {
		item.style.visibility = 'visible';
	}
}


// Clears all open menus
//
function menuClear() {
	var x, item;

	for (x in say.menus) {
		say.menus[x] = false;
		item = document.getElementById(x);
		if (item && item.style)	item.style.visibility = 'hidden';
	}
}


// Closes open menus, except those recognized as ancestors to the
// visited menu option (using hierarchic IDs to match the path).
//
function menuClean() {
	var x, item;
	var path = say.hover + '_';

	for (x in say.menus) {
		if (path.indexOf(x + '_') != 0) {
			say.menus[x] = false;
			item = document.getElementById(x);
			if (item && item.style)	item.style.visibility = 'hidden';
		}
	}
}


// Complete the menu
//
function buildMenu(any, container, baseID, baseClass, limit, level, parent, menuID) {
	if (!limit) var limit = 3;
	if (!level) var level = 0;
	if (level > limit) return false;
	if (!parent) var parent = container;
	if (!menuID) var menuID = baseID;
	var newMenu, newLine, newLink;
	var dupMenu;
	var lineID, linkID;
	var key, num, x, y;
	var wait = level ? '0' : '500';

	// Check existing menu or build menu from array data
	newMenu = document.getElementById(menuID);
	if (!newMenu) {
		newMenu = document.createElement('ul');
		newMenu.id = menuID;
		newMenu.className = baseClass + ' ' + baseClass + '_sub' + level;
		parent.appendChild(newMenu);
	}
	
	// List all submenus in an array (to tidy all menus properly in Explorer 7)
	if (level) {
		say.menus[menuID] = false; // False means 'currently not visible'
	}

	// Workaround for Explorer compatibility
	// Get submenu links regrouped by level to ensure correct display of overlaying menus
	if (say.its.ie && level) {
		levelID = baseID + '_level' + level;
		newLine = document.getElementById(levelID);
		if (!newLine) {
			newLine = document.createElement('div');
			newLine.style.position = 'absolute';
			newLine.style.top = '0px';
			newLine.style.left = '0px';
			newLine.style.zIndex = String(10 + level);
			container.appendChild(newLine);

			// Add submenu levels for CSS stylesheet compatibility
			for (num = 0; num < level; num++) {
				dupMenu = document.createElement('ul');
				dupMenu.className = baseClass + ' ' + baseClass + '_sub' + num;
				dupMenu.style.position = 'absolute';
				dupMenu.style.background = 'transparent';
				dupMenu.style.border = 'transparent';
				dupMenu.style.top = '0px';
				dupMenu.style.left = '0px';
				newLine.appendChild(dupMenu);
				newLine = document.createElement('li');
				newLine.style.position = 'absolute';
				newLine.style.background = 'transparent';
				newLine.style.border = 'transparent';
				newLine.style.top = '0px';
				newLine.style.left = '0px';
				dupMenu.appendChild(newLine);
			}
			newLine.id = levelID;
		}
		y = getY(newMenu) - getY(container);
		x = getX(newMenu) - getX(container);
		//y = newMenu.style.top + getY(newMenu) - getY(container);
		//x = newMenu.style.left + getX(newMenu) - getX(container);
		newMenu = parent.removeChild(newMenu);
		newMenu.style.position = 'absolute';

		// Explorer 6 does a weird displacemet
		if (say.its.ie6) {
			newMenu.style.top = String((level == 1 ? 24 : 0 ) + y) + 'px';
		}
		else {
			newMenu.style.top = String(y) + 'px';
		}

		newMenu.style.left = String(x) + 'px';
		newMenu.style.zIndex = String(10 + level);
		newLine.appendChild(newMenu);
	}

	// Make Safari users happy with a fancy transperancy thingy
	if (say.its.swk && level) {
		newMenu.style.opacity = '0.95';
	}

	// Check links in menu
	for (key = 0; key < any.length; key++) {
		num = (key < 99 ? '0' : '') + (key < 9 ? '0' : '') + String(key + 1);
		lineID = menuID + '_n' + num;
		linkID = menuID + '_m' + num;

		newLine = document.getElementById(lineID);
		if (!newLine) {
			newLine = document.createElement('li');
			newLine.id = lineID;
			newMenu.appendChild(newLine);
		}

		if (newLine.getElementsByTagName('a').length) {
			newLink = newLine.getElementsByTagName('a')[0];
		}
		else {
			newLink = document.createElement('a');
			if (any[key].href) newLink.href = any[key].href;
			if (any[key].text) newLink.innerHTML = any[key].text;
			newLine.appendChild(newLink);
		}

		newLink.onmouseover = new Function('',"menuEnter('" + linkID + "'," + wait + ")");
		newLink.onmouseout = new Function('',"menuLeave('" + linkID + "'," + wait + ")");

		if ((typeof(any[key]) == 'object') && (any[key].length)) {
			buildMenu(any[key], container, baseID, baseClass, limit, level + 1, newLine, linkID);
		}
	}

	return true;
}


// Get real X position
//
function getX(obj) {
	var x = 0;
	if (!obj) return false; 
	while (obj.offsetParent) {
		x += obj.offsetLeft;
		obj = obj.offsetParent;
	}
	return x;
}


// Get real Y position
//
function getY(obj) {
	var y = 0;
	if (!obj) return false; 
	while (obj.offsetParent) {
		y += obj.offsetTop;
		obj = obj.offsetParent;
	}
	return y;
}
