// Functions for drop-down navigation

// Note: level=0, currentMenus[0] and mouseOverLevel(0) all relate to
// the menu containing the children-of-the-rootpage

var currentMenus=new Array();
var checkMenuPID = false;

function showMenu(menu, level) {
  // drop down the selected menu
	if (!level) level=1;
	hideMenu(level); // retract other dropped-down menus
	menu=$(menu);
	if (!menu) return;
	menu.setStyle('visibility', 'visible');
	currentMenus[level]=menu;
	startCheckMenu();
}

function hideMenu(level) {
	// Retract the currently dropped-down menu(s) from 'level' on upwards.
	// After executing this function, currentMenus[level] is unset
	if (!level) level=0;
	while (currentMenus.length>level) {
		var menu=currentMenus.pop();
		if (menu) menu.setStyle('visibility', 'hidden');
	}
	while(currentMenus.length>0 && !currentMenus.getLast()) {
		currentMenus.pop();
	}
	if (currentMenus.length===0) startCheckMenu(false);
}

// Periodically check whether the mouse is still over the area, and retract
// the menu if it isn't
function startCheckMenu(enable) {
	if (typeof(enable)=='undefined') enable=true;
	if (enable) {
		if (!checkMenuPID) checkMenuPID = setInterval('checkMenu()', 200);
	} else {
		if (checkMenuPID) clearInterval(checkMenuPID);
		checkMenuPID = false;
	}
}
function checkMenu() {
	// check whether the mouse is in a menu area, and retract the menu otherwise
	if (currentMenus.length>mouseOverLevel.length) {
		hideMenu(mouseOverLevel.length);
	}
}

// Track whether the mouse is over a tracking area for menu's of certain levels
var mouseOverLevel = new Array();
function noteMouseIn(id, level) { // called if the mouse enters a tracking area
	if (!level) level=0;
	while(mouseOverLevel.length<=level) mouseOverLevel.push(new Hash());
	mouseOverLevel[level][id]=1;
}

var msgCount=0;
function noteMouseOut(id, level) {// called if the mouse leaves a tracking area
	if (!level) level=0;
	if (mouseOverLevel.length>level) mouseOverLevel[level].erase(id);
	while(mouseOverLevel.length>0 && mouseOverLevel.getLast().getLength()===0) {
		mouseOverLevel.pop();
	}
}

// Function for keyboard navigation
function processNavKey(el0, event, horizontal) {
	if (!el0 || !el0.id || !el0.id.match(/^navlink(\d+)_/)) {
		return false;
	}
	var pageLevel=parseInt(RegExp.$1);
	el0=$(el0);
	var dir;
	switch(event.keyCode) {
	case 27: // Escape
		hideMenu(0);
		return false;
	case 37: // Arrow left
		dir = (horizontal?'prev':'up');
		break;
	case 38: // Arrow up
		dir = (horizontal?'up':'prev');
		break;
	case 39: // Arrow right
		dir = (horizontal?'next':'down');
		break;
	case 40: // Arrow down
		dir = (horizontal?'down':'next');
		break;
	case 9: // Tab key
		dir = (event.shiftKey ? 'prev2' : 'next2');
		break;
	default:
		return true;
	}
	// Find a nav link relative to the given nav link
	var menu, nextEl, els, i;
	switch(dir) {
	case 'up':
		menu=el0.getParent('[id^=menu]');
		if (!menu) return false; 
		nextEl=$(menu.id.replace(/^menu/, 'navlink'));
		break;
	case 'down':
      menu=$(el0.id.replace(/^navlink/, 'menu'));
      if (!menu) return false;
		nextEl=menu.getElement('[id^=navlink]');
      break;
	case 'next':
	case 'prev':
		menu=el0.getParent('[id^=menu]');
		if (!menu) menu=el0.getParent('[id^=navigationTable]');
		if (!menu) return false;
		els=menu.getElements('[id^=navlink'+pageLevel+'_]');
		i=els.indexOf(el0)+(dir=='next'?1:-1);
		if (i<0 || i>=els.length) { // Try going 'up', but on failure wraparound
			menu=el0.getParent('[id^=menu]');
			if (menu) {
				nextEl=$(menu.id.replace(/^menu/, 'navlink'));
				break;
			}
			i=(i+els.length)%els.length;
		}
		nextEl=els[i];
		break;
	case 'next2':
	case 'prev2':
		menu=el0.getParent('[id^=navigationTable]');
		if (!menu) return false;
		els=menu.getElements('[id^=navlink]');
		i=els.indexOf(el0)+(dir=='next2'?1:-1);
		if(i<0 || i>=els.length) return true; // continue with normal tabbing
		nextEl=els[i];
		break;
   default:
      break;
	}
	if (!nextEl) return false;
	nextEl.focus();
	nextEl.onmouseover();
	return false;
}

