/*************************************************************
* DESCRIPTION:  Functions for the equinoxtraining.org/courses.html page
* APPLICATION:  www.equinoxtraining.org/courses.html page
* AUTHOR:		John Abbott
* DATE:			2 Jan 2007
* VERSION:		1.0
* FILE NAME:	assests/scripts/courses.js
* FUNCTIONS:	initalisePage
				setInitialDisplay
				hideDetailsAll
				registerCseTitleMouseOver
				registerCseDivMouseOut
				cseDivMouseOut
				cseTitleMouseOver
				writeDisableLinkButton
				disableDynamicDisplay
				getEventElement
				hideCseDetails
				showCseDetails
				getCseTitleElement
				getCseDivElements
				getCseDivElement
				removeDisableLinkButton
* PURPOSE:		These scripts are to hide the amount of detail on the 
page and only reveal it by a mouseover of the course title element.
* WARNING:		Makes extensive use of DOM manipulation and CSS.  Care 
must be taken when altering html elements or changing attributes because 
this may break some scripts.
'**************************************************************/
/*
OVERVIEW:  Control of the display is exercised using JavaScript to 
manipulate CSS.  Each course is enclosed in a Div element, has a title
 formed by an h3 element and details in an UL list element.  Setting and 
 removing a style attribute, defined in body.css, on the course Div element
 results in the LI elements being shown or hidden.  The default condition is 
 to show all the data.  Hiding the LI is done by adding the style attribute 
 to the course Div. An onmouseover event  set on the H3 title elements
 results in the LI elements being shown.  An onmouseout event on the course 
 Div element causes the removal of the style element and, thus, the display 
 of the data.*/

/*-----------INITIALISATION SCRIPTS--------------------------*/
function initalisePage() {
	//Perform a browser compliance check.  Do nothing if the browser
	//is not able to support DOM manipulation.
	if (document.getElementById) {
		//Call the function to hide the data and register the mouse events.
		setInitialDisplay();
	}
return;
}

function setInitialDisplay() {
/*Hides the unwanted LI elements and registers the onmouseover events
to the H3 course title elements.  Registers the onmouseout events to
the course Div elements.*/
	//Get an array of the course Div Elements.
	var cseDivElements = getCseDivElements();
	//Loop the array elements
	for (var i = 0; i < cseDivElements.length; i++) {
		//Setting the style attribute to hide the LI elements
		hideCseDetails(cseDivElements[i]);
		//Get an array of the H3 course title elements
		var cseTitleElement = getCseTitleElement(cseDivElements[i]);
		//Register the onmouseover/onmouseout events
		registerCseTitleMouseOver(cseTitleElement);
		registerCseDivMouseOut(cseDivElements[i]);
	} //Loop to the next course Div element.
return;
}
/*---------------END INITIALISATION SCRIPTS-------------------*/

/*--------------------PRIME FUNCTIONS-------------------------*/

function hideDetailsAll() {
/*Loops through an array of all the course Div elements
and hides the unwanted LI elements.*/
	//Get an array of all the course Div Elements.
	var cseDivElements = getCseDivElements();
	//Loop through the array.
	for (var i = 0; i < cseDivElements.length; i++) {
		//Hide the LI element for the given course.
		hideCseDetails(cseDivElements[i]);
	} //Loop to the next course Div element.
return;
}

//Register mouseover event on the H3 title element.
//ARGUMENT:  The H3 course title element object.
function registerCseTitleMouseOver(cseTitleElement) {
	cseTitleElement.onmouseover = cseTitleMouseOver;
return;
}

/*Register the onmouseout event to the course Div Element.
ARGUMENT:  The course DIV element object.*/
function registerCseDivMouseOut(cseDivElement) {
	cseDivElement.onmouseout = cseDivMouseOut;
return;
}

function cseDivMouseOut(e) {
//ARGUMENT:  e = event object passed automatically in Modzilla based browsers.

/*This function is called on the mouse moving out of an element in the course
Div element or the Div element itself.  The function performs two tasks:  Removing 
the hover status visual cues from the H3 title element and hiding the LI elements.

Removing the hover status cues is achieved by removing the style attribute on the H3 
element.  Hiding the LI elements is achieved by removing the style attribute on the 
course Div element.
*/
	//Reference the element that fired the event.
	var element = getEventElement(e);
	//Find the element that the mouse has gone to.  Browser differences.
	var lastElement = (window.event)?window.event.toElement : e.relatedTarget;
	//RegExp to identify the H3 element.
	var re = /^h3$/i;
	//Test to see if the firing element is a child of the H3 title element
	if (re.test(element.parentNode.nodeName)) {
		//and if so, reconfigure the element value the the H3 title element.
		element = element.parentNode;
	}
	//When the H3 title element fired the event check to see if it has the 'clear'
	//attribute value and if so set the clear thus removing the other classNames
	//attached to the element.
	if (re.test(element.nodeName)) {
		re = /clear/i;
		if (re.test(element.className)) {
			element.className = "clear";
		}
		//otherwise just remove all style class names.
		else {
			element.className = "";
		}
	}
	//set the RegExp to look for the img tag.
	re = /^img$/i;
	/*Only hide the LI elements if the mouse has moved to:
		Outside the browser window (null)
		Outside the maincontent Div border
		Into an image element. (RegExp test)
	*/
	if (lastElement == null || lastElement.className == "maincontent" || re.test(lastElement.nodeName)) {
		//Get the reference to the course Div element by sending the element object reference that 
		//fired the event.
		var cseDivElement = getCseDivElement(element);
		//Send the course Div object reference to the function to hide the LI elements.
		hideCseDetails (cseDivElement);
	}
return;
}

function cseTitleMouseOver(e) {
/*ARGUMENT:  (e) is the event object passed automatically to Modzilla browsers.

This function is the event handler for mouseover events on the H3 course title 
element.  It is fired when the mouse moves into the H3 element or one of its 
children in the DOM tree.  It performs 2 functions.  Firstly, it performs a classic
mouseover background change to give visual cues to the user.  Secondly, it reveals
the LI elements to show the course details.  The rollover visual cues are achieved by
setting the style attribute name to 'titlemouseover'.  This invokes the styling specified
in the 'body.css' file.  Revelation of the LI elements is achieved by calling the 
showCseDetails function and passing it the course Div object reference.
*/
	//Get the element that fired the event.
	var element = getEventElement(e);
	//See if a child fired the event
	if (element.parentNode.nodeName.toLowerCase() == "h3") {
		//and set the object reference to the H3 element if it did.
		element = element.parentNode;
	}
	//Check for an attribute class value of 'clear', used to clear the floats, so it can be retained.
	if (element.className.indexOf("clear") != -1 || element.parentNode.className.indexOf("clear") != -1) {
		//set the class attribute value to invoke both styles.
		element.className = "clear titlemouseover"
	}
	else {
		//or just the one style to show the rollover visual cues.
		element.className = "titlemouseover";
	}
	/*call a function to hide all the details to correct the case where the onmouseout function
	has not been processed quickly enough resulting in the details being left displayed.*/
	hideDetailsAll();
	//Call the function to display the LI elements for the course title that fired the event,
	//passing the course Div element (parentNode of the H3 element).
	showCseDetails (element.parentNode);
return;
}

function writeDisableLinkButton() {
/*This function called from withing the html page, puts a button on the page to allow
users to dispense with the dynamic display and have a static one instead.  Tabbed browsing
 is not possible with this page as it uses H3 elements to control the display.  These elements
 cannot be given focus with the tab key.  This provides alternative access to the information 
 if use of the mouse is not desired.*/
 
	document.write('<p><button value="fulldisplay" tabindex="10" onclick="disableDynamicDisplay();">' +
	'Full Display</button>' +
	' For viewing without a mouse, click the button to get a full, static display of course information.</p>');

return;
}

function disableDynamicDisplay() {
/*This function is called by activating the button displayed at the bottom of the page 
by the function 'writeDisabledLinkButton()'.  It has no arguments.  It performs 4 tasks.
It reveals all the course information, disables the onmouseout event, disables the 
onmouseover event and removes the static display button.  The page becomes a static page.*/
	//Get a collection of all the course Div Element objects
	var cseDivElements = getCseDivElements();
	//loop through the array of course Div Elements
	for (var i = 0; i < cseDivElements.length; i++) {
		//Display the full list of LI elements.
		showCseDetails(cseDivElements[i]);
		//Remove the onmouseout event from the course Div element
		cseDivElements[i].onmouseout = null;
		//Remove the onmouseover event from the H3 course title element
		getCseTitleElement(cseDivElements[i]).onmouseover = null;
	} //Loop to the next course Div Element object
	//Get rid of the button as it has performed its function.
	removeDisableLinkButton();
return false;
}

/*-------------------SUB-FUNCTIONS------------------------*/

function getEventElement(e) {
/*PURPOSE: Identifies element firing an event.
ARGUMENTS: (e) = Automatically generated event object - Browser specific.
RETURNS:  the object firing the event.
COMMENTS:  Browser differences exist.  IE has a global 'event' element, whilst 
Modzilla based browser do not.  They automatically send the object firing the event 
to the function registered as the event handler.
*/
	//Conditional variable.  If the 'event' object exists (IE) then take 
	//the src property.  Otherwise get the target property of the object 
	//passed to the function when the event fired.
	var eventElement = (window.event)?window.event.srcElement : e.target;
//return the element that fired the event.
return eventElement;
}

function hideCseDetails(cseDivElement) {
/*PURPOSE:  Sets the value of the class argument for the given element
ARGUMENTS:  cseDivElement.  The course DIV element object reference.
RETURNS:  None.
COMMENTS:  Sets the class property value to 'hidelist' who's styles are 
defined in body.css.  These inculed 'display: none'.
*/
	cseDivElement.className = "hidelist";
return;
}

function showCseDetails (cseDivElement) {
/*PURPOSE:  Sets the vale of the class argument for the given element.
ARGUMENTS:  cseDivElement.  The course DIV element object reference.
RETURNS:  None.
COMMENTS:  Sets the class property value to nothing.  This allows the LI 
elements to be displayed.
*/
	cseDivElement.className = "";
return;
}

function getCseTitleElement (cseDivElement) {
/*PURPOSE:  To find the H3 course title element
ARGUMENTS:  cseDivElement.  The object reference for the course DIV element object
RETURNS:  Reference to the H3 course title object
COMMENTS:  Is required for browser incompatibilities.  Modzilla based browsers put
a #text element (nodeType == 3) on every element.  IE does not.
*/
	//Put the firstChild element into a local variable
	var cseTitleElement = cseDivElement.firstChild;
	//if the node is a text node (3) go for the sibling node.
	if (cseTitleElement.nodeType == 3) {
		cseTitleElement = cseTitleElement.nextSibling;
	}
// send back the H3 element reference.
return cseTitleElement;
}

function getCseDivElements() {
/*PURPOSE:  To find all the course DIV elements
ARGUMENTS:  None
RETURNS:  A collection/array of all the course DIV elements
COMMENTS:  Identifys all DIV elements.  Finds the DIV element with 
the class property value of 'maincontent' and then uses reference to this
object to get the DIV elements that are children of the 'maincontent' DIV.
WARNINGS:  Uses the class attribute value of 'maincontent' to 
identify a DIV element.  Changes to the class name or use of the 
class name on other elements may break the script.  Also, adding DIV elements 
as children of the 'maincontent' DIV could break the script.
*/
	//Get a collection of all the DIVs in the document
	var allDivs = document.getElementsByTagName("div");
	var divMainContent;
	var cseDivElements;
	checkAllDivs : //Label for reference in the break command.
	//Loop through all the DIV elements
	for (var i = 0; i < allDivs.length; i++) {
		//Populate a local variable with all the attributes for that DIV
		//IE has a full list.  Modzilla only those with values.
		var divAttributes = allDivs[i].attributes;
		//Loop through each attribute
		for (var j = 0; j < divAttributes.length; j++) {
			//Look for one with the name 'maincontent'
			if (divAttributes[j].value == "maincontent") {
				//Put reference to the DIV in the variable
				divMainContent = allDivs[i];
				//Break out of the 'checkAllDivs' loop by 
				//referencing the label.
				break checkAllDivs;
			}
		}
		
	}
	//Get a collection of the course DIV elements by getting all 
	//DIVs that are contained within the 'divMainContent' object.
	cseDivElements = divMainContent.getElementsByTagName("div");
	//Return the collection of course DIV element references.
return cseDivElements;
}

function getCseDivElement(childElement) {
/*PURPOSE:  Finds the course DIV element from reference to a child element.
ARGUMENTS:  childElement.  A child of the DIV element to find reference to.
RETURNS:  The parent DIV of a child node.
COMMENTS:  Works up through the DOM from the given element to find a parent 
that is a DIV.  In the event of a failure to find a parent DIV the script 
will return the same element that was sent in the argument.
*/
	//Set the local variable with the passed argument.
	var cseDivElement = childElement;
	//RegExp to find 'DIV'.
	var re = /^div$/i;
	//RegExp to find 'BODY'
	var re4Error = /body/i;
	//Loop until the target node is a DIV.
	while (!re.test(cseDivElement.nodeName)) {
		//Test for Error conditions.  Maincontent className check on a DIV element is included 
		//incase a browser calls it's DIV elements something that is not recognised by the RegExp.
		if (cseDivElement.className == "maincontent" || re4Error.test(cseDivElement.nodeName)) {
			//stop the process and return the original child element for errors conditions.
			return childElement;
		}
		//otherwise move up the DOM to the next parent node.
		cseDivElement = cseDivElement.parentNode;
	} //Run the loop with the next parent node as the target object
// Return the course DIV element object reference.
return cseDivElement;
}

function removeDisableLinkButton() {
/*PURPOSE:  To remove the button allowing users to disable the dynamic display
ARGUMENTS:  None
RETURNS:  None
COMMENTS:  Uses DOM manipulation to remove the page elements providing the 
static page button.
*/
	var mainBodyDiv;
	//Get all the DIV elements on the page.
	var allDivs = document.getElementsByTagName("div");
	//Loop the Div elements to find the one with the class attribute value of 'mainbody'
	for (var i = 0; i < allDivs.length; i++) {
		if (allDivs[i].className == "mainbody") {
			mainBodyDiv = allDivs[i];
			break;
		}
	}
	//Looking for the 'p' element containing the static page button.
	//In IE it is the lastChild.  In Modzilla based browsers we need to
	//skip the #text node.
	if (mainBodyDiv.lastChild.nodeType == 3) {
		//Remove the 'p' element in Modzilla based browsers
		mainBodyDiv.removeChild(mainBodyDiv.lastChild.previousSibling);
	}
	else {
		//Remove the 'p' element in IE browsers.
		mainBodyDiv.removeChild(mainBodyDiv.lastChild);
	}
return;
}

/*-----------------END SUB FUNCTIONS----------------------*/
