/*********************************************************************************
 * CONSTANTS USED THROUGHOUT THE SITE
 *********************************************************************************/

// Standard width of a secondary window
var stdWindowWidth = 600;

// Standard height of a secondary window
var stdWindowHeight = 400;

// string - the current page number from the file path
var coursePage;

// integer - The current index position of the arrPages array
var int_arrPagesCurrPos = 0;

// Index in page array that indicates where to return to from remediation
var remediationReturnPage;

// displays page number when true, hides it when false
var debug = false;

// Flags that indicate state of course controls
var btnReturnActive = false;
var btnPreviousActive = true;
var btnNextActive = true;
var pageSelectorsActive = true;

// Contains handles of open windows referenced by window name
var oWinHandles = new Object();



/*********************************************************************************
 * FUNCTION LIST
 *********************************************************************************/

/********************************************************************
 * Author:	M. Lawn
 * Date:	Unknown
 * Inputs:	Nothing
 * Outputs:	Nothing
 * Purpose:	Load first page of SCO
 ********************************************************************/
function launchFirstPage() {
//Call the LMS initialize and get the bookmark

	var bkmPge;

	//Initialize with first page URL and page number.
	var pageNumber = 1;
	var firstPge = "./sco" + courseSection + "/" + coursePagePrefix + courseNumber + "_" + courseSection + arrPages[0] + ".html";

	bkmPge = loadPage(firstPge);

	if (bkmPge == firstPge) {
		//Check for bookmark passed in URL search string.
		if ( getQueryVariable("bookmark") ) bkmPge = getQueryVariable("bookmark");
	}

	//Get bookmark URL and page number.
	if (bkmPge != firstPge) {
		bkmPge = "./sco" + courseSection + "/" + bkmPge;
		pageNumber = parseInt(bkmPge.substr(bkmPge.lastIndexOf(".") - 2, 2), 10);
	}

	setupPage(bkmPge, pageNumber);

}


/********************************************************************
 * Author: 	R. Fitzgerald
 * Date: 		20-March-2006
 * Inputs:	variable (string) - query string variable who's value
 *				is being queried
 * Outputs:	value of the query string variable being referenced
 * Purpose:
 ********************************************************************/
function getQueryVariable(variable) {

	query = window.location.search.substring(1);

	vars = query.split("&");

	for (var i=0;i<vars.length;i++) {
		var pair = vars[i].split("=");

		if (pair[0] == variable) {
			return pair[1];
		}
	}

	return null;

}


/********************************************************************
 * Author: 	M. Lawn
 * Date: 		unknown
 * Inputs:	nothing
 * Outputs:	nothing
 * Purpose:
 * Status: tbd
 ********************************************************************/
function extractPageInfo()
{
	var tmpStr = courseFrame.document.getElementById("iContent").src;

	tmpStr = tmpStr.substring( tmpStr.lastIndexOf('/')+1, tmpStr.lastIndexOf('.') );
	courseNumber = tmpStr.substring(coursePagePrefix.length, (coursePagePrefix.length + 2));
	coursePage = tmpStr.substring((tmpStr.length - 2), tmpStr.length);
	tmpLngth = arrPages.length;

	if((arrPages[int_arrPagesCurrPos] * 1) != (coursePage * 1)){
		int_arrPagesCurrPos = null;
		for (x=0;x<=tmpLngth;x++){
			if((arrPages[x] * 1) == (coursePage * 1)){
				int_arrPagesCurrPos = x;
				x = tmpLngth + 1;
			}
		}
	}

}


/********************************************************************
 * Authors: M. Lawn, J. Eckenrode
 * Date: 4/2008
 * Inputs: None
 * Outputs: None
 * Purpose:	Display course controls and page counter
 ********************************************************************/
function displayCourseControls() {

	var tBar = "";
	var s;


	//Set up spans for toolbar controls.

	if (SCOmenuAvailable) tBar += "<span class=\"SCOmenuControls\" id=\"SCOmenuControls\"></span>";
	tBar += "<span class=\"glossaryControls\" id=\"glossaryControls\"></span>";
	tBar += "<span class=\"printLessonControls\" id=\"printLessonControls\"></span>";
	tBar += "<span class=\"helpControls\" id=\"helpControls\"></span>";
	tBar += "<span class=\"returnControl\" id=\"returnControl\"></span>";
	tBar += "<span class=\"previousControl\" id=\"previousPageControl\"></span>";
	tBar += "<span class=\"nextControl\" id=\"nextPageControl\"></span>";
	tBar += "<span class=\"pageCounter\" id=\"pageCounter\"></span>";

	courseFrame.document.getElementById("toolBar").innerHTML = tBar;


	//Display toolbar controls. Wrap buttons in anchors to enable tabbing.


	//SCO menu control.
	if (SCOmenuAvailable) {
		s = "<a href=\"javascript:parent.openSCOmenu();\" alt=\"" + SCOmenuTitle + "\" title=\"" + SCOmenuTitle + "\" class=\"buttonLink\" tabindex=\"1\">" +
			 	"<img src=\"./interface/btnSCOMenuUp.gif\" border=\"0\" id=\"SCOmenuButton\" class=\"toolbarButton\" />" +
			"</a>";		
		s += "<a href=\"javascript:parent.openSCOmenu();\" class=\"toolbarLink\" id=\"SCOmenuLink\" tabindex=\"1\">Lesson&nbsp;Topics</a>";
		courseFrame.document.getElementById("SCOmenuControls").innerHTML = s;
		courseFrame.document.getElementById("SCOmenuControls").style.visibility = "inherit";
	}


	//Glossary control.
	s = "<a href=\"javascript:parent.openGlossary();\" alt=\"Glossary\" title=\"Glossary\" class=\"buttonLink\" tabindex=\"2\">" +
			"<img src=\"./interface/btnGlossaryUp.gif\" border=\"0\" id=\"glossaryButton\" class=\"toolbarButton\" />";
		"</a>";		
	s += "<a href=\"javascript:parent.openGlossary();\" class=\"toolbarLink\" id=\"glossaryLink\" tabindex=\"2\">Glossary</a>";
	courseFrame.document.getElementById("glossaryControls").innerHTML = s;


	//Print lesson control.
	s = "<a href=\"javascript:parent.openPrintLesson();\" alt=\"Print Lesson\" title=\"Print Lesson\" class=\"buttonLink\" tabindex=\"3\">" +
			"<img src=\"./interface/btnPrintLessonUp.gif\" border=\"0\" id=\"printLessonButton\" class=\"toolbarButton\" />";
		"</a>";		
	s += "<a href=\"javascript:parent.openPrintLesson();\" class=\"toolbarLink\" id=\"printLink\" tabindex=\"3\">Print&nbsp;Lesson</a>";
	courseFrame.document.getElementById("printLessonControls").innerHTML = s;


	//Help control.
	s = "<a href=\"javascript:parent.openHelp();\" alt=\"Help\" title=\"Help\" class=\"buttonLink\" tabindex=\"4\">" +
			"<img src=\"./interface/btnHelpUp.gif\" border=\"0\" id=\"helpButton\" class=\"toolbarButton\" />";
		"</a>";		
	s += "<a href=\"javascript:parent.openHelp();\" class=\"toolbarLink\" id=\"helpLink\" tabindex=\"4\">Help</a>";
	courseFrame.document.getElementById("helpControls").innerHTML = s;


	//Return control.
	courseFrame.document.getElementById("returnControl").innerHTML = "" +
		"<a href=\"#\" id=\"returnLink\" alt=\"Return\" title=\"Return\" class=\"buttonLink\" tabindex\"5\">" +
			"<img src=\"./interface/btnReturnUp.gif\" border=\"0\" id=\"returnButton\" />" +
		"</a>";
	courseFrame.document.getElementById("returnControl").style.visibility = "hidden";


	//Display paging controls.
	if (arrPages.length > 1) {

		//Previous page control.
		if (int_arrPagesCurrPos != 0) {
			courseFrame.document.getElementById("previousPageControl").innerHTML = "" +
				"<a href=\"#\" id=\"previousPageLink\" alt=\"Previous Page of Lesson\" title=\"Previous Page of Lesson\" class=\"buttonLink\" tabindex=\"6\">" +
					"<img src=\"./interface/btnPreviousUp.gif\" border=\"0\" id=\"previousPageButton\" />" +
				"</a>";
		}
		else {
			courseFrame.document.getElementById("previousPageControl").innerHTML = "" +
				"<a href=\"#\" id=\"previousPageLink\" alt=\"Previous Page of Lesson\" title=\"Previous Page of Lesson\" class=\"buttonLink\" tabindex=\"6\">" +
					"<img src=\"./interface/btnPreviousInactive.gif\" border=\"0\" id=\"previousPageButton\" />" +
				"</a>";
		}


		//Next page control.
		if (int_arrPagesCurrPos != (arrPages.length - 1)) {
			courseFrame.document.getElementById("nextPageControl").innerHTML = "" +
				"<a href=\"#\" id=\"nextPageLink\" alt=\"Next Page of Lesson\" title=\"Next Page of Lesson\" class=\"buttonLink\" tabindex=\"7\">" +
					"<img src=\"./interface/btnNextUp.gif\" border=\"0\" id=\"nextPageButton\" />" +
				"</a>";
		}
		else {
			courseFrame.document.getElementById("nextPageControl").innerHTML = "" +
				"<a href=\"#\" id=\"nextPageLink\" alt=\"Next Page of Lesson\" title=\"Next Page of Lesson\" class=\"buttonLink\" tabindex=\"7\">" +
					"<img src=\"./interface/btnNextInactive.gif\" border=\"0\" id=\"nextPageButton\" />" +
				"</a>";
		}

	}

}


/********************************************************************
 * Author: J. Eckenrode
 * Date: July 26, 2007
 * Inputs: mediaURL - String -- relative path to media file
 *         mediaType - String -- file type
 *         mediaID - String
 *         mediaWidth - Integer
 *         mediaHeight - Integer
 *         mediaCaption - String
 *         mediaAltText - String
 *         mediaDlink - String
 *         bgColor - String
 * Purpose: Display media on course main page. Use document.write
 *          to fix object tag rollover problem in IE6 where border
 *          appears and click is required to activate content.
 ********************************************************************/
function displayPageMedia(mediaURL, mediaType, mediaID, mediaWidth, mediaHeight, mediaCaption, mediaAltText, mediaDlink, bgColor) {

	var s = createMediaHTML(mediaURL, mediaType, mediaID, mediaWidth, mediaHeight, mediaCaption, mediaAltText, mediaDlink, bgColor, 'parent.parent');
	courseFrame.document.getElementById("iContent").contentWindow.document.write(s);

}


/********************************************************************
 * Author: J. Eckenrode
 * Date: July 26, 2007
 * Inputs: mediaURL - String -- relative path to media file
 *         mediaType - String -- file type
 *         mediaID - String
 *         mediaWidth - Integer
 *         mediaHeight - Integer
 *         mediaCaption - String
 *         mediaAltText - String
 *         mediaDlink - String
 *		   bgColor - String
 * Purpose: Display media in pop-up window. Use document.write to
 *          fix object tag rollover problem in IE6 where border
 *          appears and click is required to activate content.
 ********************************************************************/
function displayWindowMedia(mediaURL, mediaType, mediaID, mediaWidth, mediaHeight, mediaCaption, mediaAltText, mediaDlink, bgColor) {

	var s = createMediaHTML(mediaURL, mediaType, mediaID, mediaWidth, mediaHeight, mediaCaption, mediaAltText, mediaDlink, bgColor, 'opener');
	document.write(s);

}


/*******************************************************************************
* Authors: M. Lawn, J. Eckenrode
* Purpose: This function is called to create HTML used to display a media file
*          and media information. All of the imputs are required.
* Inputs:  mediaURL - String -- relative path to media file
*          mediaType - String -- file type
*          mediaID - String
*          mediaWidth - Integer
*          mediaHeight - Integer
*          mediaCaption - String
*          mediaAltText - String
*          mediaDlink - String
*		   bgColor - String
*          documentReference - document where media is displayed; main page or
*		   secondary winow
* Returns: HTML string
*******************************************************************************/
function createMediaHTML(mediaURL, mediaType, mediaID, mediaWidth, mediaHeight, mediaCaption, mediaAltText, mediaDlink, bgColor, documentReference) {

	if (typeof bgColor == "undefined" || bgColor == "") bgColor = "#FFFFFF";

	mediaHTML = '<table border="0" width="' + mediaWidth + '" cellpadding="0" cellspacing="0"><tr><td>';


	switch(mediaType) {

		case "swf":
		case "flv":

			mediaHTML += '' +
				'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" ' +
					'id="' + mediaID + '" width="' + mediaWidth + '" height="' + mediaHeight + '" accesskey="?" alt="' + mediaAltText + '" title=""';

					if ( (typeof mediaDlink != "undefined") && (mediaDlink != "") ) {
						mediaHTML += ' ' + 'longdesc="' + documentReference + '.launchIt(\'LONGDESCRIPTION\',\''+ mediaDlink + '\');"';
					}

					mediaHTML += ">\n" + 
					'<param name="movie" value="' + mediaURL + '" />\n' +
					'<param name="quality" value="high" />\n' +
					'<param name="bgcolor" value="' + bgColor + '" />\n' +
					'<param name="name" value="' + mediaAltText + '" />\n' +
					'<param name="description" value="' + mediaDlink + '" />\n' +
					'<param name="wmode" value="transparent" />\n' +
					'<param name="allowScriptAccess" value="always" />\n' +
					'<param name="SeamlessTabbing" value="true" />\n' +
					'<embed src="' + mediaURL + '"\n' +
						'quality="high"\n' +
						'wmode="transparent"\n' +
						'allowScriptAccess="always"\n' +
						'SeamlessTabbing="true"\n' +
						'bgcolor="' + bgColor + '"\n' +
						'pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" ' +
						'width="' + mediaWidth + '" height="' + mediaHeight + '" alt="' + mediaAltText + '" title="">' +
					'</embed>\n' +
				'</object>';

			break;


		case "gif":
		case "jpg":
		case "png":

			mediaHTML += '' +
				'<img src="' + mediaURL + '" ' +
					'id="' + mediaID + '" width="' + mediaWidth + '" height="' + mediaHeight + '" alt="' + mediaAltText + '" title="' + mediaAltText + '" ';

					if ( (typeof mediaDlink != "undefined") && (mediaDlink != "") ) {
						mediaHTML += 'longdesc="' + documentReference + '.launchIt(\'LONGDESCRIPTION\',\''+ mediaDlink + '\');" ';
					}

				mediaHTML += '/>';

			break;


		default:
			break;

	}


	if ( (typeof mediaCaption != "undefined") && (mediaCaption != "") ) {
		mediaHTML += '<div class="mediaCaption">' + mediaCaption + '</div>';
	}
	if ( (typeof mediaDlink != "undefined") && (mediaDlink != "") ) {
		mediaHTML += '<div class="mediaDlink"><a class="dLink" href="javascript:' + documentReference + '.launchIt(\'LONGDESCRIPTION\',\''+ mediaDlink + '\');">d-link</a></div>';
	}

	mediaHTML += '</td></tr></table>';

	return mediaHTML;

}


/*******************************************************************************
 * Author: 	M. Lawn
 * Date:  Unknown
 * Inputs:	direction (string) - which navigation button the user is clicking
 * Outputs:	toReturn (string) - the new page number
 * Purpose:	will determine what the next or previous page number is.
 * -----------------------------------------------------------------------------

 * Editor: 	R. Fitzgerald
 * Date:		14-February-2006
 * Change:	Rewrote function to use a switch statement in place of an
 *			if...else if...else statement
 ******************************************************************************/
function determinePageNumber(direction){

	switch (direction){
		case "previous":
			toReturn = arrPages[int_arrPagesCurrPos - 1];
			break;
		case "next":
			toReturn = arrPages[int_arrPagesCurrPos + 1];
			break;
		case "first":
			toReturn = arrPages[0];
			break;
		case "last":
			toReturn = arrPages[arrPages.length - 1];
			break;
		default:
			toReturn = arrPages[0];
			break;
	}
	return toReturn;
}


/*******************************************************************************
 * Author:	M. Lawn
 * Date: 	Unknown
 * Inputs:	nothing
 * Purpose:	Called to display the current page of total pages to the screen
 * -----------------------------------------------------------------------------
 * Author:	R. Fitzgerald
 * Date: 	10-February-2006
 * Change:	Rewrote to return the coure number as well as the page number
 			seperated by a "."  Therefore, if you're in the second course,
			on page three, "2.3" with any padding specified would be returned.

			Added "location" variable as an input, so the function would
			return the correct page number for which side of the book the
			page number is being displayed on.
*******************************************************************************/
function displayPageNumbers() {

	courseFrame.document.getElementById("pageCounter").innerHTML = ((int_arrPagesCurrPos * 1) + 1) + " of " + arrPages.length;
}


/********************************************************************
 * Author: 	M. Lawn
 * Date: 	Unknown
 * Inputs:
 * Outputs:
 * Purpose:	Wrapper function for launching a window for the resource
 * 			specified by "what".
 ********************************************************************/
function launchIt( what, file, width, height )	{

	// Set width and height
	if (typeof width == "undefined" || width == 0) width = screen.width;
	if (typeof height == "undefined" || height == 0) height = screen.height;

	// Center window onscreen
	var left = (screen.width - width) / 2;
	var top = (screen.height - height) / 2;

	//	Remove case-sensitivity issues
	what = what.toUpperCase();

	//	What resource do we want to launch?
	if( what == "LONGDESCRIPTION" ) {
		build_dLink(file, "Description");
	}
	if( what == "GLOSSARYENTRY" ) {
		openSecondaryWindow("wTerms", "../glossary/glossary_terms.html#" + file, width, height, left, top, 'no', 'no', 'no', 'no', 'no', 'no', 'yes', 'yes')
	}
	if( what == "WINDOW" ) {
		openSecondaryWindow("wSecondary", file, width, height, left, top, 'no', 'no', 'no', 'no', 'no', 'no', 'yes', 'yes')
	}
	return;
}


/********************************************************************
 * Author: 	M. Lawn
 * Date: 	Unknown
 * Inputs:	text (string) - main text content of the window
 *			windowName (string) - title of the window
 * Outputs:	nothing
 * Purpose:	This function will build a window page and write
 *			out the specified text for d-link descriptions.
 ********************************************************************/
function build_dLink(text, windowName)	{

	// Set default values for width and height
	var width = stdWindowWidth;
	var height = stdWindowHeight;

	var left = (screen.width - width) / 2;
	var top = (screen.height - height) / 2;

	sHTML = "" +
		"<html>\n" +
		"	<head>\n" +
		"		<title>" + windowName + "</title>\n" +
		"		<link href=\"../stylesheets/window.css\" rel=\"stylesheet\" type=\"text/css\">\n" +
		"		<script language=\"javascript\">\n" +
		"			opener.activateCourseControls(); //Enables non-sighted users to reactivate controls" +
		"		</script>\n" +
		"	</head>\n" +
		"	<body>\n" +
		"		<div class=\"windowHeader\">\n" +
		"			<a name=\"top\"></a>\n" +
		"			<div class=\"close\"><img src=\"../interface/btnCloseWindow.gif\" alt=\"Close\" title=\"Close\" onclick=\"window.close();\"></div>\n" +
		"		</div>\n" +
		"		<div class=\"windowBody\">\n" +
		"			<div class=\"contentTitle\">Content Description</div>\n" +
		"			<div class=\"clear\"></div>\n" +
		"			<div class=\"contentText\" id=\"definition\">\n" + text + "<br /><br /></div>\n" +
		"		</div>\n" +
		"		<div class=\"windowFooter\"></div>\n" +
		"	</body>\n" +
		"</html>"

	var hWin = openSecondaryWindow(windowName, "", width, height, left, top, 'no', 'no', 'no', 'no', 'no', 'no', 'yes', 'yes')

	var i = 0;
	while (!hWin.document.body) {
		//loop
		if (++i > 1000000) break;
	}

	if (hWin) {
		hWin.document.write(sHTML);
		hWin.document.close();
		hWin.focus();
	}

}


/********************************************************************
 * Author: 	R. Fitzgerald
 * Date: 	10-February-2006
 * Inputs:	character (string) - the prefix character
 *			count (integer) - the length to make the string when
 *				finished prefixing characters to it
 * 			stng (string) - the string of which to prefix
 * Outputs:	the prefixed string of the specified length
 * Purpose:	Append a numerical value with a speified character to
 *			a specfified length.
 ********************************************************************/
 function pad(character, count, stng){
	var temp = stng + "";

	for (s=temp.length; s<count; s++){
		temp = character + temp;
	}

	return temp;
 }


/********************************************************************
 * Author:	R. Fitzgerald
 * Date:	13-March-2006
 * Inputs:	nothing
 * Outputs:	nothing
 * Purpose:	displays page links
 ********************************************************************/
 function displayPageSelectors() {

	var sHTML = "";
	var p;

	//Preload link images
	sHTML += '<img src="./interface/pageSelectorViewed.gif" style="display: none;" />';
	sHTML += '<img src="./interface/pageSelectorViewing.gif" style="display: none;" />';
	sHTML += '<img src="./interface/pageSelectorNotViewed.gif" style="display: none;" />';

	for (n=0; n<arrPages.length; n++) {

		p = "'./sco" + courseSection + "/" + coursePagePrefix + courseNumber + "_" + courseSection + arrPages[n] + ".html'";

		if ((n * 1) < (int_arrPagesCurrPos * 1)) {
			sHTML += '<a href="#" class="pageSelector" onclick="if (parent.pageSelectorsActive) parent.setupPage(' + p + ', ' + (n + 1) + ')"><img class="pageSelectorImage" src = "./interface/pageSelectorViewed.gif" border = "0" alt = "Jump to page ' + (n + 1) +  '" title = "Jump to page ' + (n + 1) + '"></a>';
		}
		else if ((n * 1) == (int_arrPagesCurrPos * 1)) {
			sHTML += '<a href="#" class="pageSelector" onclick="if (parent.pageSelectorsActive) parent.setupPage(' + p + ', ' + (n + 1) + ')"><img class="pageSelectorImage" src = "./interface/pageSelectorViewing.gif" border = "0" alt = "Jump to page ' + (n + 1) +  '" title = "Jump to page ' + (n + 1) + '"></a>';
		}
		else if ((n * 1) > (int_arrPagesCurrPos * 1)) {
			sHTML += '<a href="#" class="pageSelector" onclick="if (parent.pageSelectorsActive) parent.setupPage(' + p + ', ' + (n + 1) + ')"><img class="pageSelectorImage" src = "./interface/pageSelectorNotViewed.gif" border = "0" alt = "Jump to page ' + (n + 1) + '" title = "Jump to page ' + (n + 1) + '"></a>';
		}
	}

	courseFrame.document.getElementById("pageSelectors").innerHTML = sHTML;

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: June 27, 2007
 * Inputs: None
 * Purpose: Set up the course frame.
 ********************************************************************/
function setupCourseFrame() {

	setEventHandlersForExitControl();

	if (SCOtype.toUpperCase() != "EXAM SCO:") {
		displayCourseControls();
		setEventHandlersForCourseControls();
		if (arrPages.length > 1) {
			displayPageNumbers();
			displayPageSelectors();
		};

	};

	launchFirstPage();

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: June 27, 2007
 * Inputs: Relative URL to page, page number
 * Purpose: Load URL, set page counter, update LMS.
 ********************************************************************/
function setupPage(pageURL, pageNumber) {

	var bookmark;

	courseFrame.document.getElementById("iContent").src = pageURL;


	if (arrPages.length > 1) {

		//Set navigation controls and status of multi-page SCO.
		int_arrPagesCurrPos = pageNumber - 1;

		//First page.
		if (int_arrPagesCurrPos == 0) deactivatePreviousButton()
		else activatePreviousButton();

		//Last page.
		if (int_arrPagesCurrPos == arrPages.length - 1) {
			deactivateNextButton();
			if (lessonStatus != "completed") {
				lessonStatus = "completed";
				//Set bookmark to first page.
				bookmark = coursePagePrefix + courseNumber + "_" + courseSection + arrPages[0] + ".html";
				if (lmsConnected) {
					completeSCO(lessonStatus);
					setBookmark(bookmark);
				}
			}
		}
		else activateNextButton();

		//Set page counter and progress indicators.
		courseFrame.document.all.pageCounter.innerHTML = pageNumber + " of " + arrPages.length;
		displayPageSelectors();
		pageSelectorsActive = true;

		//Set remediation return control.
		if (pageNumber == remediationReturnPage) {
			deactivateReturnButton();
			remediationReturnPage = null;
		}

		//Bookmark page.
		if (lmsConnected) {
			if (lessonStatus != "completed") {
				//Set bookmark to current page.
				bookmark = pageURL.substring(pageURL.lastIndexOf('/') + 1, pageURL.length);
				setBookmark(bookmark);
			}
		}
	}

	else if (SCOtype.toUpperCase() != "EXAM SCO:") {
		//Handle single-page SCO.
		if (lessonStatus != "completed") {
			lessonStatus = "completed";
			if (lmsConnected) completeSCO(lessonStatus);
		}
	}

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: January, 2008
 * Inputs: Index into page array
 * Purpose: Set global variable that indicates remediation return
 			page; turn on return control.
 ********************************************************************/
function setupRemediationReturn(n) {

	remediationReturnPage = n;
	activateReturnButton(n);

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: July 12, 2007
 * Inputs: None
 * Purpose: Set active state of course controls.
 ********************************************************************/
function activateCourseControls() {

	if (int_arrPagesCurrPos > 0) activatePreviousButton();
	if ( int_arrPagesCurrPos != (arrPages.length - 1) ) activateNextButton();
	pageSelectorsActive = true;

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: July 12, 2007
 * Inputs: None
 * Purpose: Set inactive state of course controls.
 ********************************************************************/
function deactivateCourseControls() {

	deactivatePreviousButton();
	deactivateNextButton();
	pageSelectorsActive = false;

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: June 27, 2007
 * Inputs: None
 * Purpose: Set button state.
 ********************************************************************/
function activatePreviousButton() {

	btnPreviousActive = true;
	courseFrame.document.getElementById("previousPageButton").src = "./interface/btnPreviousUp.gif";

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: June 27, 2007
 * Inputs: None
 * Purpose: Set button state.
 ********************************************************************/
function deactivatePreviousButton() {

	btnPreviousActive = false;
	courseFrame.document.getElementById("previousPageButton").src = "./interface/btnPreviousInactive.gif";

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: June 27, 2007
 * Inputs: None
 * Purpose: Set button state.
 ********************************************************************/
function activateNextButton() {

	btnNextActive = true;
	courseFrame.document.getElementById("nextPageButton").src = "./interface/btnNextUp.gif";

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: June 27, 2007
 * Inputs: None
 * Purpose: Set button state.
 ********************************************************************/
function deactivateNextButton() {

	btnNextActive = false;
	courseFrame.document.getElementById("nextPageButton").src = "./interface/btnNextInactive.gif";

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: January, 2008
 * Inputs: Number of page that button returns to.
 * Purpose: Set button state.
 ********************************************************************/
function activateReturnButton(n) {

	btnReturnActive = true;
	courseFrame.document.getElementById("returnButton").alt = "Return to Page " + n;
	courseFrame.document.getElementById("returnButton").title = "Return to Page " + n;
	courseFrame.document.getElementById("returnButton").src = "./interface/btnReturnUp.gif";
	courseFrame.document.getElementById("returnButton").style.visibility = "visible";

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: January, 2008
 * Inputs: None
 * Purpose: Set button state.
 ********************************************************************/
function deactivateReturnButton() {

	btnReturnActive = false;
	courseFrame.document.getElementById("returnButton").style.visibility = "hidden";

}



/******************************************************************************
 * Author: J. Eckenrode
 * Date: June 8, 2007
 * Inputs: Position and dimensions.
 * Purpose: Open a secondary window and display the SCO menu.
 ******************************************************************************/
function openSCOmenu(width, height, left, top) {

	if (typeof width == "undefined") width = 300;
	if (typeof height == "undefined") height = 400;
	if (typeof left == "undefined") left = 10;
	if (typeof top == "undefined") top = 100;

	openSecondaryWindow('wSCOmenu', './sco' + courseSection + '/' + 'SCOmenu.xml', width, height, left, top, 'no', 'no', 'no', 'no', 'no', 'yes', 'yes', 'yes');

}



/******************************************************************************
 * Author: J. Eckenrode
 * Date: February, 2008
 * Inputs: Position and dimensions.
 * Purpose: Open a secondary window and display the glossary.
 ******************************************************************************/
function openGlossary(width, height, left, top) {

	if (typeof width == "undefined") width = 600;
	if (typeof height == "undefined") height = 400;
	if (typeof left == "undefined") left = (screen.width - width) / 2;
	if (typeof top == "undefined") top = (screen.height - height) / 2;

	openSecondaryWindow('wGlossary', './glossary/glossary.html', width, height, left, top, 'no', 'no', 'no', 'no', 'no', 'yes', 'yes', 'yes');

}



/******************************************************************************
 * Author: J. Eckenrode
 * Date: June 8, 2007
 * Inputs: Position and dimensions.
 * Purpose: Open a secondary window and display the SCO content.
 ******************************************************************************/
function openPrintLesson(width, height, left, top) {

	if (typeof width == "undefined") width = 800;
	if (typeof height == "undefined") height = 600;
	if (typeof left == "undefined") left = (screen.width - width) / 2;
	if (typeof top == "undefined") top = (screen.height - height) / 2 - 50;

	openSecondaryWindow('wPrintLesson', './sco' + courseSection + '/' + 'printLesson.xml', width, height, left, top, 'no', 'no', 'no', 'no', 'yes', 'yes', 'yes', 'yes');

}



/******************************************************************************
 * Author: J. Eckenrode
 * Date: June 8, 2007
 * Inputs: Position and dimensions.
 * Purpose: Open a secondary window and display the help file.
 ******************************************************************************/
function openHelp(width, height, left, top) {

	if (typeof width == "undefined") width = 300;
	if (typeof height == "undefined") height = 400;
	if (typeof left == "undefined") left = (screen.width - width) / 2;
	if (typeof top == "undefined") top = (screen.height - height) / 2;

	openSecondaryWindow('wHelp', './help.html', width, height, left, top, 'no', 'no', 'no', 'no', 'no', 'yes', 'yes', 'yes');

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: May 1, 2007
 * Inputs: Window handle, name of page to display, window parameters
 * Purpose: Open a secondary window and display a page.
 ********************************************************************/
function openSecondaryWindow(sName, sURL, nWidth, nHeight, nLeft, nTop, bFullscreen, bLocation, bMenubar, bTitlebar, bToolbar, bStatus, bScrollbars, bResizable) {

	var hWindow;
	var sFeatures = "";

	if (nWidth == 0) {
		nWidth = screen.width;
		nLeft = 0;
	}

	if (nHeight == 0) {
		nHeight = screen.height;
		nTop = 0;
	}

	if (typeof nLeft == "undefined") nLeft = (screen.width - nWidth) / 2;
	if (typeof nTop == "undefined") nTop = (screen.height - nHeight) / 2;

	sFeatures += 'fullscreen=' + bFullscreen + ', ';
	sFeatures += 'width=' + nWidth + ', ';
	sFeatures += 'height=' + nHeight + ', ';
	sFeatures += 'left=' + nLeft + ', ';
	sFeatures += 'top=' + nTop + ', ';
	sFeatures += 'location=' + bLocation + ', ';
	sFeatures += 'menubar=' + bMenubar + ', ';
	sFeatures += 'titlebar=' + bTitlebar + ', ';
	sFeatures += 'toolbar=' + bToolbar + ', ';
	sFeatures += 'status=' + bStatus + ', ';
	sFeatures += 'scrollbars=' + bScrollbars + ', ';
	sFeatures += 'resizable=' + bResizable;

	//hWindow = getWindowHandle(sName);

	hWindow = window.open(sURL, sName, sFeatures, false);
	hWindow.focus();

	registerWindow(hWindow, sName);

	return hWindow;

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: May 1, 2007
 * Inputs: None
 * Purpose: Close all open secondary windows
 * Notes: Windows must be reopened here by name to recreate window
 *        references without a URL. Otherwise, IE6 generates a
 *        Permission Denied error when .close() is called.
 *        See Microsoft support article 926046,
 *        http://support.microsoft.com/kb/926046
 ********************************************************************/
function closeSecondaryWindows() {

	return; //Deactivated until patch level determined.

	for (var p in oWinHandles) {
		oWinHandles[p] = window.open('', p);
		oWinHandles[p].close();
		oWinHandles[p] = null;
	}

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: August 2, 2007
 * Inputs: Window handle and name
 * Purpose: Add window handle to object.
 ********************************************************************/
function registerWindow(oWindowHandle, sWindowName) {

	if (!oWinHandles[sWindowName]) {
		oWinHandles[sWindowName] = new Object();
		oWinHandles[sWindowName] = oWindowHandle;
	}

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: August 29, 2007
 * Inputs: Window name
 * Purpose: Clear window handle.
 ********************************************************************/
function unregisterWindow(sWindowName) {

	if (!oWinHandles[sWindowName]) oWinHandles[sWindowName] = null;

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: August 2, 2007
 * Inputs: Window name
 * Purpose: Return open window handle or null if no handle exists.
 ********************************************************************/
function getWindowHandle(sWindowName) {

	if (oWinHandles[sWindowName]) return oWinHandles[sWindowName];
	else return null;

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: May 2, 2007
 * Inputs: HTML page to display, dialog parameters, dialog arguments
 * Purpose: Open a modal dialog window and display an HTML page.
 ********************************************************************/
function openModalDialog(sURL, nWidth, nHeight, nLeft, nTop, oArguments) {

	var sCenter;
	var sFeatures = "";

	if ( (isNaN(parseInt(nLeft, 10))) || (isNaN(parseInt(nTop, 10))) ) sCenter = 'yes'
	else sCenter = 'no';

	sFeatures += 'dialogWidth:' + nWidth + 'px; ';
	sFeatures += 'dialogHeight:' + nHeight + 'px; ';
	sFeatures += 'dialogLeft:' + nLeft + '; ';
	sFeatures += 'dialogTop:' + nTop + '; ';
	sFeatures += 'center:' + sCenter + '; ';
	sFeatures += 'dialogHide:' + 'no' + '; ';
	sFeatures += 'edge:' + 'raised' + '; ';
	sFeatures += 'resizable:' + 'no' + '; ';
	sFeatures += 'scroll:' + 'no' + '; ';
	sFeatures += 'status:' + 'yes' + '; ';
	sFeatures += 'unadorned:' + 'no';

	return window.showModalDialog(sURL, oArguments, sFeatures);

}



/********************************************************************
 * Author: J. Eckenrode
 * Date: February, 2008
 * Inputs: None
 * Purpose: Set up event handlers for control in course frame.
 ********************************************************************/
function setEventHandlersForExitControl() {

	if ( courseFrame.document.getElementById("exitButton") ) {

		courseFrame.document.getElementById("exitButton").onmouseover = function() {
			courseFrame.document.getElementById("exitButton").src = "./interface/btnExitOver.gif";
		}
		courseFrame.document.getElementById("exitButton").onmouseout = function() {
			courseFrame.document.getElementById("exitButton").src = "./interface/btnExitUp.gif";
		}
		courseFrame.document.getElementById("exitButton").onmousedown = function() {
			courseFrame.document.getElementById("exitButton").src = "./interface/btnExitDown.gif";
		}
		courseFrame.document.getElementById("exitButton").onmouseup = function() {
			courseFrame.document.getElementById("exitButton").src = "./interface/btnExitUp.gif";
		}

	}

	if ( courseFrame.document.getElementById("exitLink") ) {

		courseFrame.document.getElementById("exitLink").onclick = function() {
			closeSecondaryWindows();
			top.close();
		}

	}

}


/********************************************************************
 * Author: J. Eckenrode
 * Date: June 27, 2007
 * Inputs: None
 * Purpose: Set up event handlers for controls in course frame.
 ********************************************************************/
function setEventHandlersForCourseControls() {


	//SCO menu control.
	if (courseFrame.document.getElementById("SCOmenuButton") && SCOmenuAvailable) {

		courseFrame.document.getElementById("SCOmenuButton").onmouseover = function() {
				courseFrame.document.getElementById("SCOmenuButton").src = "./interface/btnSCOMenuOver.gif";
			}
		courseFrame.document.getElementById("SCOmenuButton").onmouseout = function() {
				courseFrame.document.getElementById("SCOmenuButton").src = "./interface/btnSCOMenuUp.gif";
			}
		courseFrame.document.getElementById("SCOmenuButton").onmousedown = function() {
				courseFrame.document.getElementById("SCOmenuButton").src = "./interface/btnSCOMenuDown.gif";
			}
		courseFrame.document.getElementById("SCOmenuButton").onmouseup = function() {
				courseFrame.document.getElementById("SCOmenuButton").src = "./interface/btnSCOMenuUp.gif";
			}

	}


	//Glossary menu control.
	if ( courseFrame.document.getElementById("glossaryButton") ) {
		courseFrame.document.getElementById("glossaryButton").onmouseover = function() {
				courseFrame.document.getElementById("glossaryButton").src = "./interface/btnGlossaryOver.gif";
			}
		courseFrame.document.getElementById("glossaryButton").onmouseout = function() {
				courseFrame.document.getElementById("glossaryButton").src = "./interface/btnGlossaryUp.gif";
			}
		courseFrame.document.getElementById("glossaryButton").onmousedown = function() {
				courseFrame.document.getElementById("glossaryButton").src = "./interface/btnGlossaryDown.gif";
			}
		courseFrame.document.getElementById("glossaryButton").onmouseup = function() {
				courseFrame.document.getElementById("glossaryButton").src = "./interface/btnGlossaryUp.gif";
			}

	}


	//Print lesson control.
	if ( courseFrame.document.getElementById("printLessonButton") ) {
		courseFrame.document.getElementById("printLessonButton").onmouseover = function() {
				courseFrame.document.getElementById("printLessonButton").src = "./interface/btnPrintLessonOver.gif";
			}
		courseFrame.document.getElementById("printLessonButton").onmouseout = function() {
				courseFrame.document.getElementById("printLessonButton").src = "./interface/btnPrintLessonUp.gif";
			}
		courseFrame.document.getElementById("printLessonButton").onmousedown = function() {
				courseFrame.document.getElementById("printLessonButton").src = "./interface/btnPrintLessonDown.gif";
			}
		courseFrame.document.getElementById("printLessonButton").onmouseup = function() {
				courseFrame.document.getElementById("printLessonButton").src = "./interface/btnPrintLessonUp.gif";
			}

	}


	//Help control.
	if ( courseFrame.document.getElementById("helpButton") ) {
		courseFrame.document.getElementById("helpButton").onmouseover = function() {
				courseFrame.document.getElementById("helpButton").src = "./interface/btnHelpOver.gif";
			}
		courseFrame.document.getElementById("helpButton").onmouseout = function() {
				courseFrame.document.getElementById("helpButton").src = "./interface/btnHelpUp.gif";
			}
		courseFrame.document.getElementById("helpButton").onmousedown = function() {
				courseFrame.document.getElementById("helpButton").src = "./interface/btnHelpDown.gif";
			}
		courseFrame.document.getElementById("helpButton").onmouseup = function() {
				courseFrame.document.getElementById("helpButton").src = "./interface/btnHelpUp.gif";
			}

	}


	//Return control.
	if ( courseFrame.document.getElementById("returnButton") ) {
		courseFrame.document.getElementById("returnButton").onmouseover = function() {
				courseFrame.document.getElementById("returnButton").src = "./interface/btnReturnOver.gif";
			}
		courseFrame.document.getElementById("returnButton").onmouseout = function() {
				courseFrame.document.getElementById("returnButton").src = "./interface/btnReturnUp.gif";
			}
		courseFrame.document.getElementById("returnButton").onmousedown = function() {
				courseFrame.document.getElementById("returnButton").src = "./interface/btnReturnDown.gif";
			}
		courseFrame.document.getElementById("returnButton").onmouseup = function() {
				courseFrame.document.getElementById("returnButton").src = "./interface/btnReturnUp.gif";
				setupPage("./sco" + courseSection + "/" + coursePagePrefix + courseNumber + "_" + courseSection + arrPages[remediationReturnPage - 1] + ".html",
						parseInt(arrPages[remediationReturnPage - 1], 10)
				);
			}

	}


	//Previous page control.
	if ( courseFrame.document.getElementById("previousPageButton") ) {
		courseFrame.document.getElementById("previousPageButton").onmouseover = function() {
			if (int_arrPagesCurrPos != 0 && btnPreviousActive) {
				courseFrame.document.getElementById("previousPageButton").src = "./interface/btnPreviousOver.gif";
			}
		}
		courseFrame.document.getElementById("previousPageButton").onmouseout = function() {
			if (int_arrPagesCurrPos != 0 && btnPreviousActive) {
				courseFrame.document.getElementById("previousPageButton").src = "./interface/btnPreviousUp.gif";
			}
		}
		courseFrame.document.getElementById("previousPageButton").onmousedown = function() {
			if (int_arrPagesCurrPos != 0 && btnPreviousActive) {
				courseFrame.document.getElementById("previousPageButton").src = "./interface/btnPreviousDown.gif";
			}
		}
		courseFrame.document.getElementById("previousPageButton").onmouseup = function() {
			if (int_arrPagesCurrPos != 0 && btnPreviousActive) {
				courseFrame.document.getElementById("previousPageButton").src = "./interface/btnPreviousUp.gif";
			}
		}

	}

	if ( courseFrame.document.getElementById("previousPageLink") ) {
		courseFrame.document.getElementById("previousPageLink").onclick = function() {
			if (int_arrPagesCurrPos != 0 && btnPreviousActive) {
				setupPage("./sco" + courseSection + "/" + coursePagePrefix + courseNumber + "_" + courseSection + determinePageNumber("previous") + ".html",
					parseInt(determinePageNumber("previous"), 10)
				);
			}
		}

	}


	//Next page control.
	if ( courseFrame.document.getElementById("nextPageButton") ) {
		courseFrame.document.getElementById("nextPageButton").onmouseover = function() {
			if (int_arrPagesCurrPos != (arrPages.length - 1) && btnNextActive) {
				courseFrame.document.getElementById("nextPageButton").src = "./interface/btnNextOver.gif";
			}
		}
		courseFrame.document.getElementById("nextPageButton").onmouseout = function() {
			if (int_arrPagesCurrPos != (arrPages.length - 1) && btnNextActive) {
				courseFrame.document.getElementById("nextPageButton").src = "./interface/btnNextUp.gif";
			}
		}
		courseFrame.document.getElementById("nextPageButton").onmousedown = function() {
			if (int_arrPagesCurrPos != (arrPages.length - 1) && btnNextActive) {
				courseFrame.document.getElementById("nextPageButton").src = "./interface/btnNextDown.gif";
			}
		}
		courseFrame.document.getElementById("nextPageButton").onmouseup = function() {
			if (int_arrPagesCurrPos != (arrPages.length - 1) && btnNextActive) {
				courseFrame.document.getElementById("nextPageButton").src = "./interface/btnNextUp.gif";
			}
		}

	}

	if ( courseFrame.document.getElementById("nextPageLink") ) {
		courseFrame.document.getElementById("nextPageLink").onclick = function() {
			if (int_arrPagesCurrPos != (arrPages.length - 1) && btnNextActive) {
				setupPage("./sco" + courseSection + "/" + coursePagePrefix + courseNumber + "_" + courseSection + determinePageNumber("next") + ".html",
					parseInt(determinePageNumber("next"), 10)
				);
			}
		}

	}

}



/********************************************************************************************************
 * Author: J. Eckenrode
 * Date: June, 2008
 * Inputs: Module name, sco identifier, page identifier, window width, window height
 * Purpose: Launch remediation external to a course.
 ********************************************************************************************************/
function launchRemediation(sModule, sSCO, sPage, nWidth, nHeight) {

	openSecondaryWindow("Remediation", "../remediation/" + sModule + "/" + sSCO + "/index.html?bookmark=" + sPage, nWidth, nHeight);

}



/********************************************************************************************************
 * Author: J. Eckenrode
 * Date: August, 2007
 * Inputs: File URL, flag indicating asynchronous (true) or synchronous (false) loading
 * Purpose: Load xml file using XML DOM parser and return xml document.
 ********************************************************************************************************/
function loadXML(xmlFile, loadAsync) {

	var xmlDoc;

	if (typeof loadAsync == "undefined") loadAsync = false;

	//IE
	if (window.ActiveXObject) {
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async = loadAsync;
		xmlDoc.load(xmlFile);
	}

	//Mozilla
	else if (document.implementation && document.implementation.createDocument) {
		xmlDoc = document.implementation.createDocument("", "", null);
		xmlDoc.async = loadAsync;
		xmlDoc.load(xmlFile);
	}

	return xmlDoc;

}

