﻿var objActiveSection = null;
var objActiveTimeout = null;
var preloadImg1, preloadImg2, preloadImg3;

function doLeftMenu() {
	
	// Test for DOM compatibility
	if (document.getElementById&&document.getElementsByTagName) {

		// Initialise menu
		addMenuItems();
	}
}

function addMenuItems() {
	
	// Get root element of menu
	var oldRoot = document.getElementById('menuRoot')
	var newRoot = document.createElement('div')
	
	// Get arrays of child <h3> and <ul> tags
	var objH3s = oldRoot.getElementsByTagName('h3');
	var objULs = oldRoot.getElementsByTagName('ul');
	
	// Loop through section headers
	var i = 0;
	while (i<objH3s.length) {
		
		// Clone <h3> and <ul> elements
		var objNewH3 = objH3s[i].cloneNode(true);
		var objNewUL = objULs[i].cloneNode(true);
		
		// Add mouse event to <h3> tag to make relevant sub-menu appear on hover
		objNewH3.onmouseover = makeH3Active;

		// Add focus and blur events for <a> tags for keyboard users
		var objAs = objNewUL.getElementsByTagName('a');
		var j;
		for(j=0;j<objAs.length;j++) {
			objAs[j].onfocus = makeAActive;
			objAs[j].onblur = makeInactive;
		}
		
		// Create a wrapper div to surround <h3> and <ul> elements
		var objDiv = document.createElement('div');
		
		// Add header and sub-menu to wrapper <div>, then add this to new menu wrapper
		objH3Root = addCornerDivs(objNewH3, 'h3')
		objH3Root.onmouseout = mouseOut;
		objDiv.appendChild(objH3Root);
		objDiv.appendChild(addCornerDivs(objNewUL, 'ul'));
		
		// Add another div for bottom shadow on <h3>
		var objDivS = document.createElement('div');
		objDivS.className = 'shadow';
		objDiv.appendChild(objDivS);
		
		newRoot.appendChild(objDiv);
		i += 1;
	}
	
	// Insert newRoot as child of oldRoot's parent
	newRoot.className = 'menuJsOn';
	oldRoot.parentNode.insertBefore(newRoot, oldRoot)
	oldRoot.parentNode.removeChild(oldRoot)
	
	// Add event to clear active menu when user leaves page
	window.onunload = makeInactive;
	
	// Pre-load background images
	if (document.images) {
        preloadImg1 = new Image(400,100);
        preloadImg1.src = '/images/common/sub-menu-h2.png';
        preloadImg2 = new Image(1000,1000);
        preloadImg2.src = '/images/common/sub-menu.png';
        preloadImg2 = new Image(1000,1000);
        preloadImg2.src = '/images/common/sub-menu-arrow.png';
    }
}

function addCornerDivs(el, clName) {
    var objDiv1 = document.createElement('div');
    var objDiv2 = document.createElement('div');
    var objDiv3 = document.createElement('div');
    objDiv1.appendChild(el);
    objDiv2.appendChild(objDiv1);
    objDiv3.appendChild(objDiv2);
    objDiv3.className = clName;
    return objDiv3;
}

// Called when the mouse is moved over an <h3> header
function makeH3Active() {

	// Get root div that contains h3 and ul
	var objRoot = this.parentNode.parentNode.parentNode.parentNode;

	// Activate sub-menu
	makeActive(objRoot);
}

// Called when focus is set to a submenu <a> tag using the keyboard
function makeAActive() {

	// Get root div for this menu section
	var objRoot = this.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;

	// Activate sub-menu
	makeActive(objRoot);
}

function makeActive(objRoot) {
	
	// Clear any existing Timeouts for other active menus, and make the
	// menu inactive immediately
	if(objActiveTimeout!=null) {
		clearTimeout(objActiveTimeout);
		makeInactive()
	}
	
	// Give container <div> class name 'active' and store a reference to it
	objRoot.className = 'active';
	objActiveSection = objRoot;
	
	// Find an <ul> which is also a child of the same root div
	var elUl = objRoot.getElementsByTagName('ul')[0];
	
	// Get the root that contains just the ul
	var objUlRoot = elUl.parentNode.parentNode.parentNode;
	
	// Check for 'adjusted' class on <ul>
	if (elUl.className!='adjusted') {

	    // Adjust the width of the <ul> container to fit the text inside
	    adjustToContentWidth(objUlRoot);
	    elUl.className = 'adjusted';
	}
	
	// Get height of <ul> container
	var h = objUlRoot.clientHeight;
	
	// Set element to default position and see if it currently disappears
	// off the bottom of the screen
	objUlRoot.style.top = '-8px';
	var dy = getYBDiff(objUlRoot)-50;
	if (dy + 8<0) {

		// Element currently partly below bottom of screen - move it up
		// the page - first check how much room there is above element
		var dyT = getYTDiff(objUlRoot);
		if (dy+dyT < 0) {

			// Element would go off top of screen if we moved it up by
			// this amount - reduce amount so top of element appears at
			// top of screen
			dy = -dyT;
		}
		
		// Can't move the <ul> up by more than its height + 16 px, or it
		// appears disconnected from the header
		if (dy < -(h - 16)) {dy = -(h - 16)}
		objUlRoot.style.top = (dy + 8) + 'px';

	}
							
	// Add mouse events to make sub-menu appear / disappear
	objUlRoot.onmouseover = ulMouseOver;
	objUlRoot.onmouseout = mouseOut;
}

// Adjusts the width of the <ul> container to fit the text inside
function adjustToContentWidth(elRoot) {
	
	// Get first child <li> element
	var elCh = elRoot.getElementsByTagName('li')[0];
	
	// Amount to decrease width of <ul> by - start at zero
	var dy = 0;
	
	// Loop through child elements of <ul> tag
	while (elCh!=null) {
		
		// Is next node an element?
		if(elCh.nodeType==1) {
			
			// Yes - is it a <li>?
			if (elCh.nodeName=='LI') {

				// Yes - get width of <li> tag
				var elChW = elCh.offsetWidth;
				var elChCh = elCh.firstChild;
				while (elChCh!=null) {

					// Is next node an element?
					if(elChCh.nodeType==1) {

						// Yes - is it an <a>?
						if (elChCh.nodeName=='A') {
							
							// Yes - get width of <a> tag
							var elChChW = elChCh.offsetWidth;
							
							// Calculate difference between widths of <a> and <li>
							var dyNew = elChW - elChChW;
							
							// Is this less than the previous stored width? (Or is
							// previous stored width = 0)?
							if ((dy==0&&dyNew!=0)||dyNew<dy) {
								
								// Yes - store this width instead
								dy = dyNew;
							}
						}
					}
					elChCh = elChCh.nextSibling;
				}
			}
		}
		elCh = elCh.nextSibling;
	}
	
	// If width difference was found, reduce width of <ul> tag
	// (+20px determined by trial and error to stop lines wrapping)
	if (dy > 0) {
		elRoot.style.width = ((elRoot.offsetWidth - dy) + 20) + 'px';
	}
}

function mouseOut() {
	objActiveTimeout = setTimeout('makeInactive()',25);
}

function ulMouseOver() {
	if(objActiveTimeout!=null) {
		clearTimeout(objActiveTimeout);
	}
}

function makeInactive() {
	if (objActiveSection!=null) {
		objActiveSection.className = '';
		objActiveSection = null;
	}
}

// Find the position of the top of an element relative to the top of the page
function getTop(el) {
	var y = 0;
	if (el.offsetParent&&el.clientHeight) {
		do {
			y += el.offsetTop;
		} while (el = el.offsetParent);
	}
	return y;
}

// Find the position of the bottom of an element relative to the top of the page
function getBottom(el) {
	return el.clientHeight + getTop(el);
}

// Find the bottom of the current viewport + scroll position relative to the top of the page
function getViewportHeight() {
	if (typeof window.innerHeight != 'undefined') {
		return window.innerHeight;
	} else if (typeof document.documentElement != 'undefined'
     && typeof document.documentElement.clientHeight !=
     'undefined' && document.documentElement.clientHeight != 0) {
		return document.documentElement.clientHeight;
	} else {
		return 0;
	}
}
function getScrollTop() {
	if (typeof window.pageYOffset != 'undefined') {
		return window.pageYOffset;
	} else if (typeof document.body.scrollTop != 'undefined'
	 && document.body.scrollTop != 0) {
		return document.body.scrollTop;
	} else if (typeof document.documentElement.scrollTop != 'undefined') {
		return document.documentElement.scrollTop;
	} else {
		return -1;
	}
}

// Find the position of the bottom of an element relative to the bottom
// of the viewport
function getYBDiff(el) {
	var ey = getBottom(el);
	var y = getViewportHeight();
	var dy = getScrollTop();
	if (ey!=0&&y!=0&&dy!=-1) {
		
		// All variables returned sensible values
		return y + dy - ey;
	} else {
		return 0;
	}
}

// Find the position of the top of an element relative to the top
// of the viewport
function getYTDiff(el) {
	var ey = getTop(el);
	var dy = getScrollTop();
	if (ey!=0&&dy!=-1) {
		
		// All variables returned sensible values
		return ey - dy;
	} else {
		return 0;
	}
}