// Initialize the Site Map. 
// This function loops through all li elements that contain a child h3 tag (signifying it as a sub-menu element) and 
// 1) gives the li element a unique id
// 2) adds a link to the h3 tag and assigns an onclick event to toggle open/close state of the sub-menu (ul sibling to h3)
// 3) Assigns the saved open/close state to each sub-menu
// It then builds the Show/Hide All links
function initList(id)
{
	var newString = getCookie('openElements'); // Retrieve saved open/closed states of each sub-menu
	openElements = newString.split(':'); // Convert cookie string to global array
	var mapList = document.getElementById(id);
	var h3s = mapList.getElementsByTagName('H3'); // H3 elements signify submenus
	var li;
	var a;
	var linkText;
	if (h3s.length > 0) {
		for (var i=0; i < h3s.length; i++) {
			if (h3s[i] && h3s[i].parentNode.nodeName == 'LI') {
				// Access parent li element of h3 element
				li = h3s[i].parentNode; 
				// Assign unique id to each sub-menu li tag
				li.setAttribute('id','list' + i);
				h3s[i].className = 'header';
				// Assign saved open/closed state to sub-menu
				if (inArray(li.id,openElements)) {
					openList(li);
				} else {
					closeList(li);
				}
				// Build new link tag and insert it as a child to the h3 element
				a = document.createElement('a');
				linkText = document.createTextNode(h3s[i].firstChild.nodeValue); // Assumes h3 element has only one child text node
				a.appendChild(linkText);
				a.setAttribute('href','#');
				a.onclick = function(){toggle(this.parentNode.parentNode); return false;};
				h3s[i].replaceChild(a,h3s[i].firstChild);
			}
		}
	}
	// Create "open/close all" links and place them above the Site Map
	h3 = document.createElement('h3');
	a_show = document.createElement('a');
	linkText = document.createTextNode('Show All');
	a_show.appendChild(linkText);
	a_show.setAttribute('href','#');
	a_show.onclick = function(){toggleAll(id,'show'); return false;};
	a_show.id = 'show-all';
	a_hide = a_show.cloneNode(a_show);
	a_hide.firstChild.nodeValue = 'Hide All';
	a_hide.onclick = function(){toggleAll(id,'hide'); return false;};
	a_hide.id = 'hide-all';
	h3.appendChild(a_show);
	h3.appendChild(document.createTextNode(' '));
	h3.appendChild(a_hide);
	h3.id = 'toggle-all';
	mapList.parentNode.insertBefore(h3,mapList);
}

// Once the Site Map is initialized, toggle() opens and closes individual menus
function toggle(li)
{
	if (li.className && li.className == 'open') {
		closeList(li);
		removeOpenElement(li.id,openElements);
	} else if (li.className && li.className == 'closed') {
		openList(li);
		addOpenElement(li.id,openElements);
	}
	// Save state of open sub-menus
	setCookie("openElements",openElements.join(":"));
}

// Opens or closes all sub-menus at once
function toggleAll(id,mode)
{
	var mapList = document.getElementById(id);
	var h3s = mapList.getElementsByTagName('H3');
	var li;
	var linkText;
	if (h3s.length > 0) {
		for (var i=0; i < h3s.length; i++) {
			if (h3s[i] && h3s[i].parentNode.nodeName == 'LI') {
				li = h3s[i].parentNode; 
				if (mode == 'show') {
					openList(li);
					addOpenElement(li.id,openElements);
				} else {
					closeList(li);
					removeOpenElement(li.id,openElements);
				}
			}
		}
		// Save state
		setCookie("openElements",openElements.join(":"));
	}
}

// Adds the li id to the list of open sub-menus
function addOpenElement(element,array)
{
	if (!inArray(element,array)) {
		array[array.length] = element;
		return true;
	}
	return false;
}

// Removes the li id from the list of open sub-menus
// The use of splice() limits support to modern browsers
function removeOpenElement(element,array)
{
	for (var i = 0; i < array.length; i++) {
		if (array[i] == element) {
			array.splice(i,1);
			return true;
		}
	}
	return false;
}

// Simple function to test presence of an element in an array
function inArray(element,array)
{
	for (var i = 0; i < array.length; i++) {
		if (array[i] == element) {
			return true;
		}
	}
	return false;
}

// Sets a sub-menu state to open; invoked by initList() and toggle()
function openList(li)
{
	li.className = 'open';
	return true;
}

// Sets a subm-menu state to closed; invoked by initList() and toggle()
function closeList(li)
{
	li.className = 'closed';
	return true;
}

// Gets cookie value; invoked by getCookie()
// Source: Javascript and DHTML Cookbook (O'Reilly)
function getCookieVal(offset)
{
	var endstr = document.cookie.indexOf(";",offset);
	if (endstr == -1) {
		endstr = document.cookie.length;
	}
	return unescape(document.cookie.substring(offset,endstr));
}

// Gets cookie information
// Source: Javascript and DHTML Cookbook (O'Reilly)
function getCookie(name)
{
	var arg = name + "=";
	var alen = arg.length;
	var clen = document.cookie.length;
	var i = 0;
	while (i < clen) {
		var j = i + alen;
		if (document.cookie.substring(i,j) == arg) {
			return getCookieVal(j);
		}
		i = document.cookie.indexOf(" ",i) + 1;
		if (i == 0) break;
	}
	return "";
}

// Sets cookie information
// Source: Javascript and DHTML Cookbook (O'Reilly)
function setCookie(name,value,expires,path,domain,secure) {
	document.cookie = name + "=" + escape(value) + 
		((expires) ? "; expires=" + expires : "") +
		((path) ? "; path=" + path : "") +
		((domain) ? "; domain=" + domain : "") +
		((secure) ? "; secure=" + secure : "");
}

