function testanswers (strAnswers) {
/* +===============================================================================================================+
   | This function accepts a string of text representing the type of question used (included only to allow future  |
   | upgrades that will handle more question types than just single- and multiple-selection questions) and the     |
   | correct answers for that question.  The string is structured as such:                                         |
   |    <question type indicator>|<correct state for option 1>|<correct state for option 2>|...                    |
   | Question type indicator has any defined possible values.  Correct state is represented by using a '1' for     |
   | true (as in, the item should be selected) and '0' for false (as in, the item should not be selected). This    |
   | function also accepts multiple arguments, separated by commas.  An example call from the page would be:       |
   |    javascript:testanswers('singlesel|1|0','multisel|0|0|1|1','multisel|1|0|1','multisel|0|1|1|0');            |
   | This example is for 4 questions,  with 2, 4, 3, and 4 options within each, respectively.                      |
   | Currently supported learning activities include:                                                              |
   |    singlesel       single selection multiple choice (radio buttons)                                           |
   |    ssrsfb          single selection with response-specific feedback (radio buttons)                           |
   |    multisel        multiple selection multiple choice (check boxes)                                           |
   |    mspfb           multiple selection with partial feedback (check boxes)                                     |
   |    text            text responses (text boxes)                                                                |
   |    dd              drop-down menus (select boxes)                                                             |
   |    ddma            drop-down menus with more than one possible answer (select boxes)                          |
   |    ssbothadv       single selection multiple choice with both pos and neg fb on another page (radio buttons)  |
   |    sstout          single selection multiple choice when timer has expired (radio buttons)                    |
   +===============================================================================================================+ */


	
	// Assorted variable declarations
	var totalQ = testanswers.arguments.length;  // one argument passed for each question, thus this is total num of questions
	var answerMatrix = new Array(totalQ);  // will hold an array of answers for each question
	var correctMatrix = new Array(totalQ);  // will hold an array of T/F values indiciating the correctness of each q item
	var questionMatrix = new Array(totalQ);  // will hold the forms[] array and its elements
	var totals = new Array(2);  // will hold 2 values: total number correct, total number possible
	var i;  // counter
	var j;  // counter
	var k;  // counter
	
	//Build Q & A matricies
	for (i = 0; i < totalQ; i++) {  // Loops through each of the arguments passed to testanswers()
		answerMatrix[i] = testanswers.arguments[i].split("|"); // For the current argument, split the string
															   // of text into separate array elements
	};  // end for i loop

	questionMatrix = document.forms;  // Grab all the forms[] array from the document and keep it in questionMatrix
									  // Does assume the only forms on the page are questions

	// Go and make sure that all of the feedback that could be displayed on the page
	// as a result of any previous form submissions is reset to the default state or class
	if 	(answerMatrix[0][0] == 'mspfb') {
		resetFeedbackPFB();
	} else if (answerMatrix[0][0] == 'ssrsfb') {
		resetFeedbackRSFB();
	} else {
		resetFeedback();
	}; // end if

	//Validate the form to ensure that every question on the page has at least one selection made on it
	if (allAreAnswered(questionMatrix, answerMatrix) == false) {
		unvalidatedForm ();
		return;  // This ejects us from the remainder of the testanswers() function
	}; // end if

	//Call function to build correctMatrix from questionMatrix and answerMatrix
	correctMatrix = noteCorrects(questionMatrix, answerMatrix);
	//Get the total correct and total possible from the totals function
	totals = tally(correctMatrix, answerMatrix);
	
	//alert("pause");
	//pausecomp(2);
	//alert("unpause");
	
	// Go do whatever feedback is desired, based on whether each item was correct //, after a short delay
	//setTimeout("feedback(" + correctMatrix + ", " + totals + ")", 1000);
	//alert (answerMatrix[0][0]);
	switch (answerMatrix[0][0]) {
		case ('mspfb'):
			feedbackPFB(correctMatrix, totals);
			break;
		case ('ssrsfb'):
			feedbackRSFB(correctMatrix, totals);
			break;
		case ('sstout'):
			feedbackSSTOut(correctMatrix, totals);
			break;
		case ('ssbothadv'):
			feedbackSSBothAdv(correctMatrix, totals);
			break;
		default:
			feedback(correctMatrix, totals);
			break;
	}; // end switch
	
} // END TEST ANSWERS FUNCTION

function resetFeedback() {
/* +===============================================================================================================+
   | This function calls change() to reset any feedback DIVs to the 'fboff' class.  Customize to include a         |
   | separate call for each feedback DIV used on the page.                                                         |
   +===============================================================================================================+ */
	change ('negfb','fboff');
} // end function resetFeedback()

function resetFeedbackRSFB() {
/* +===============================================================================================================+
   | This function calls change() to reset any feedback DIVs to the 'fboff' class.  Customize to include a         |
   | separate call for each feedback DIV used on the page.                                                         |
   +===============================================================================================================+ */
	for (i = 0; i < document.forms.length; i++) { // Loop through each question
		for (j = 0; j < document.forms[i].elements.length; j++) {  // Loop through each item within the current question
			idToChange = "q" + i + "r" + j;  // Form the ID of the DIV to display using q number and resp number
			change (idToChange, 'fboff'); // Turn on the appropriate feedback.
		} // end for j loop
	} // end for i loop
} // end function resetFeedback()

function resetFeedbackPFB() {
/* +===============================================================================================================+
   | This function calls change() to reset any feedback DIVs to the 'fboff' class.  Customize to include a         |
   | separate call for each feedback DIV used on the page.                                                         |
   +===============================================================================================================+ */
	change ('negfb','fboff');
	change ('partfb','fboff');
} // end function resetFeedback()

function unvalidatedForm() {
/* +===============================================================================================================+
   | This function displays the appropriate alert informing the learner that the form did not validate.            |
   | Customize to desired message (or other procedures) locally on the page, if necessary.                         |
   +===============================================================================================================+ */
	alert ("Please answer this question.");
} // end function unvalidatedForm()

function allAreAnswered(q, a) {
/* +===============================================================================================================+
   | This function accepts an array of all of the questions on the page.  It then loops through each question      |
   | stored in that array and sends it to the isAnswered() function to analyze individually.                       |
   +===============================================================================================================+ */
	var i;
	for (i=0;i<q.length;i++) {  // Loop through each question stored in the array
		if (isAnswered(q[i], a[i][0])==false) {	// if any one is not answered...
			return false;											// ...they are not all answered
		};	// end if	
	}; // end for
	return true;													// if you get this far, they were all answered
} // end allAreAnswered

function isAnswered(q, qType) {
/* +===============================================================================================================+
   | Given an individual question and its type, this function loops through all of the options within the question |
   | to see if any one of them have been selected.  If so, then the question has been answered.                    |
   | qType is currently unused; included for future functionality when needing to branch based on qType.           |
   | Currently assumes single- or multiple-selection questions, only.                                              |
   +===============================================================================================================+ */
	
	
	var i;
	for (i=0;i<q.length;i++) {  // Loop through each option within the question
		if ((qType == 'text') || (qType == 'dd') || (qType == 'ddma')) {
			//alert (qType);
			if (q[i].value !== '') {
				//alert (q[i].value);
				return true;  // if any are selected or a text value provided, the question was answered
			 }; // end if
		} else {
			if (q[i].checked) {
				return true;  // if any are checked, the question was answered
			 }; // end if
		}; // end if qType
	}; // end for
	return false;		// if you get this far, the question was not answered
} // end isAnswered

function noteCorrects (q, a) {
/* +===============================================================================================================+
   | Given an array of question elements and an array of the appropriate responses, note which items were          |
   | correctly answered.                                                                                           |
   +===============================================================================================================+ */
	var i;
	var k;
	var corr = new Array(q.length);  // will hold an array of T/F values indiciating the correctness of each q item

	//Loop through all of the responses and check against the answers provided to testanswers()
	for (j = 0; j < q.length; j++) {  // Loop through all of the questions; j tracks current question
		var currQCorrects = new Array(q[j].length);  // Each time we come to a new question, rebuild the
																  // currQCorrects temporary array so that it is of
																  // same size as the total number of options on this item
		for (k = 0; k < q[j].length; k++) {  // Loop through all of the options of the current question
			// Go check to see if the current option of the current question was answered correctly.  currQCorrects then
			// holds the result for all the options of the current question.
			if ((a[j][0] == 'text') || (a[j][0] == 'dd')) {
			currQCorrects[k] = isCorrectTB (q[j].elements[k], a[j][k+1]);  // [k+1] used as a[j][0] is question type identifier
			} else if (a[j][0] == 'ddma') {
			possAns = a[j][k+1].split(","); // parse possible answers
			currQCorrects[k] = isCorrectDDMA (q[j].elements[k], possAns);
			} else {
			currQCorrects[k] = isCorrect (q[j].elements[k], a[j][k+1]);  // [k+1] used as a[j][0] is question type identifier
			}
		} // end for k loop
			corr[j] = currQCorrects;  // Now take all of the item results and store them in the correctMatrix
											   // that will house all of the results from all of the questions
	} // end for j loop
	return corr;
} // end noteCorrects()

function isCorrect(q,a) {
/* +===============================================================================================================+
   | Given the state of an option from a single question and the desired state of the corresponding option from    |
   | the same question, see if the selection was correct.                                                          |
   +===============================================================================================================+ */
		if (q.checked == a) {			// if the control matches the answer key...
			return true;				// the option is correct
		}; // end if
	return false;			// if you get this far, it was wrong
} // end isCorrect()

function isCorrectTB(q,a) {
/* +===============================================================================================================+
   | Given the state of an option from a single question and the desired state of the corresponding option from    |
   | the same question, see if the selection was correct.                                                          |
   +===============================================================================================================+ */
		if (q.value.toLowerCase() == a.toLowerCase()) {			// if the control matches the answer key...
			return true;				// the option is correct
		}; // end if
	return false;			// if you get this far, it was wrong
} // end isCorrect()

function isCorrectDDMA(q,a) {
/* +===============================================================================================================+
   | Given the state of an option from a single question and the desired state of the corresponding option from    |
   | the same question, see if the selection was correct.                                                          |
   +===============================================================================================================+ */
	var k;
	for (k = 0; k < a.length; k++) {  // Loop through all of the acceptable answers
		if (q.value == a[k]) {			// if the control matches the answer key...
			return true;				// the option is correct
		}; // end if
	}
	return false;			// if you get this far, it was wrong
} // end isCorrect()

function tally(correctMatrix, answerMatrix) {
/* +===============================================================================================================+
   | Given an array with indicators as to whether each option of each question was answered correctly, tally the   |
   | number of correct responses and the total number of responses on the page.  This function also applies        |
   | appropriate styling to each response as correct or incorrect.                                                 |
   +===============================================================================================================+ */
	var i;
	var j;
	var totalCorrect = 0;
	var totalPossible = 0;
	var idToChange;
	var totals = new Array(2);
	
	// wait (1000); // Insert a brief delay only to make it visually apparent that the feedback did turn off (if desired)

	for (i = 0; i < correctMatrix.length; i++) { // Loop through each question
		totalPossible = totalPossible + correctMatrix[i].length; // Note that the total possible for the question is its length
		for (j = 0; j < correctMatrix[i].length; j++) {  // Loop through each item within the current question
			if (correctMatrix[i][j] == true) { // If they got the current item right
					totalCorrect = totalCorrect + 1; // Add one to their tally
			}; // end if true # 1
			//alert (document.forms[i].elements[j].type);
			if ((document.forms[i].elements[j].checked) || ((document.forms[i].elements[j].value >= 0) && (document.forms[i].elements[j].type != 'checkbox')) || (document.forms[i].elements[j].type == 'text') || ((document.forms[i].elements[j].type == 'select-one') && (document.forms[i].elements[j].value != ''))) {  // only mark feedback on those items selected
				idToChange = document.forms[i].elements[j].id + "li";  // Append "li" to match the ID of the container LI
				//alert (idToChange);
				if (correctMatrix[i][j] == true) { // If they got the current item right
					change(idToChange, 'RespRight');  // Change the LI to the RespRight class
				}
				else {
					change(idToChange, 'RespWrong');  // Change the LI to the RespWrong class
				}; // end if true # 2
			};// end if checked
		}; // end for j loop
	}; // end for i loop

	totals[0] = totalCorrect; // store the totalCorrect value
	totals[1] = totalPossible; // store the totalPossible value
	
	return totals;
}  // end tally()

function feedback(correctMatrix, totals) {
/* +===============================================================================================================+
   | Given the individual indications of whether each response was correct or not, as well as a tally of the total |
   | possible and total correct, display appropriate feedback element, accordingly.  This function can be written  |
   | onto the learning activity page, itself, if there is a need to override the default method for displaying     |
   | feedback found in the external JavaScript file that would otherwise apply to the entire site.                 |
   | The following method is the 'all or nothing' approach most commonly used, currently.                          |
   +===============================================================================================================+ */
	var totalPossible = totals[0];
	var totalCorrect = totals[1];
	// This is the 'all or nothing' approach to displaying feedback
	if (totalCorrect == totalPossible) {
		//pausecomp(2);
		setTimeout("window.location = CorrectURL", 1500);  // This option is for page advances on correct
		//change('posfb','fbon');  // display posfb1 div if they got them all right
	} // end true condition
	else {
		setTimeout("change(\'negfb\',\'fbon\')",750);  // otherwise, display the negfb1 div
	}; // end false condition; end of if

} // end feedback()

function feedbackRSFB(correctMatrix, totals) {
/* +===============================================================================================================+
   | This function turns on the feedback DIV that corresponds to the selected form elements.  As the feedback is   |
   | to be custom to each response, no consideration of whether the response was correct or not is made here.      |
   | This function requires a DIV for each response on the page to be identified in the following format:          |
   | q0r0 (for question 0, response 0), q0r1 (for question 0, response 1), etc.  Be sure to use the customized     |
   | resetFeedback() function that corresponds to this response-specific feedback structure.                       |
   +===============================================================================================================+ */

	var totalPossible = totals[0];
	var totalCorrect = totals[1];
	// This is the 'all or nothing' approach to displaying feedback
	if (totalCorrect == totalPossible) {
		setTimeout("window.location = CorrectURL", 1500);  // This option is for page advances on correct
		//change('posfb','fbon');  // display posfb1 div if they got them all right
	} // end true condition
	else {
		for (i = 0; i < document.forms.length; i++) { // Loop through each question
			for (j = 0; j < document.forms[i].elements.length; j++) {  // Loop through each item within the current question
				if (document.forms[i].elements[j].checked) {  // only display feedback for selected responses
					idToChange = "q" + i + "r" + j;  // Form the ID of the DIV to display using q number and resp number
					setTimeout("change (idToChange, \'fbon\')",750); // Turn on the appropriate feedback.
				} // end true condition
			} // end for j loop
		} // end for i loop
	}; // end false condition; end of if
} // end feedback()

function feedbackPFB(correctMatrix, totals) {
/* +===============================================================================================================+
   | Given the individual indications of whether each response was correct or not, as well as a tally of the total |
   | possible and total correct, display appropriate feedback element, accordingly.  This function can be written  |
   | onto the learning activity page, itself, if there is a need to override the default method for displaying     |
   | feedback found in the external JavaScript file that would otherwise apply to the entire site.                 |
   | The following method is the 'all or nothing' approach most commonly used, currently.                          |
   +===============================================================================================================+ */
	var totalPossible = totals[0];
	var totalCorrect = totals[1];
	var eligibleForPartial;
	
	// Figure out if the answer qualifies as at least partially correct.
	for (i = 0; i < document.forms.length; i++) { // Loop through each question
		for (j = 0; j < correctMatrix[i].length; j++) {  // Loop through each item within the current question
			if ((correctMatrix[i][j] == true) && (document.forms[i].elements[j].checked)) { // If they got the current item right and it was checked
					eligibleForPartial = true; // they are eligible for partial correct credit.
			}; // end if true # 1
		}; // end for j loop
	}; // end for i loop

	// This is the partially correct allowed approach to displaying feedback
	if (totalCorrect == totalPossible) {
		setTimeout("window.location = CorrectURL", 1500);  // This option is for page advances on correct
		//change('posfb1','fbon');  // display posfb1 div if they got them all right
	} // end true condition
	else if (eligibleForPartial == true) {
		setTimeout("change(\'partfb\',\'fbon\')",750); // display the partfb1 div if they got it partially correct
	} // end else if condition
	else {
		setTimeout("change(\'negfb\',\'fbon\')",750);  // otherwise, display the negfb1 div
	}; // end false condition; end of if

} // end feedback()

function feedbackSSTOut(correctMatrix, totals) {
/* +===============================================================================================================+
   | No matter if the question was answered correctly or not, window advances to the IncorrectURL variable defined |
   | locally on the page.                                                                                          |
   +===============================================================================================================+ */
		setTimeout("window.location = IncorrectURL", 1500);  // This option is for page advances on correct
} // end feedback()

function feedbackSSBothAdv(correctMatrix, totals) {
/* +===============================================================================================================+
   | Given the individual indications of whether each response was correct or not, as well as a tally of the total |
   | possible and total correct, display appropriate feedback element, accordingly.  This function can be written  |
   | onto the learning activity page, itself, if there is a need to override the default method for displaying     |
   | feedback found in the external JavaScript file that would otherwise apply to the entire site.                 |
   | The following method is the 'all or nothing' approach most commonly used, currently.                          |
   +===============================================================================================================+ */
	var totalPossible = totals[0];
	var totalCorrect = totals[1];
	// This is the 'all or nothing' approach to displaying feedback
	if (totalCorrect == totalPossible) {
		setTimeout("window.location = CorrectURL", 1500);  // This option is for page advances on correct
	} // end true condition
	else {
		setTimeout("window.location = IncorrectURL", 1500);  // otherwise, advance to the incorrect page
	}; // end false condition; end of if

} // end feedback()

function change(id, newClass) {
/* +===============================================================================================================+
   | Given the ID attribute of the desired HTML element and the newClass to which the element should change,       |
   | do just that and assign newClass to the class property of the element ID.                                     |
   +===============================================================================================================+ */

identity=document.getElementById(id);  // This is required for Mozilla-based browsers (including NS)
identity.className=newClass;  // Change the element's class to newClass
} // end change()


function pausecomp(delayTime)
{
var today=new Date();
var now=today.getSeconds();
var today2; now2;

while (1)
{
today2=new Date();
var now2=today2.getSeconds();
if (now2<now) {now2+=60;}
if (now2-now>=delayTime) {break;}
}
}

function newWindow(url) {
	window.open(url);
}


function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

function MM_findObj(n, d) { //v4.0
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && document.getElementById) x=document.getElementById(n); return x;
}

function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}


function MM_openBrWindow(theURL,winName,features) { //v2.0
  sample=window.open(theURL,winName,features); sample.window.focus();
}



function MM_goToURL() { //v3.0
  var i, args=MM_goToURL.arguments; document.MM_returnValue = false;
  for (i=0; i<(args.length-1); i+=2) eval(args[i]+".location='"+args[i+1]+"'");
}

function construction () {
     alert("This feature is currently under construction.");
}


function windowSize () {

var targetheight=460;
var targetwidth=775;

function winWid(){ return (ns4||ns6) ? window.innerWidth : document.body.clientWidth; }
function winHei(){ return (ns4||ns6) ? window.innerHeight : document.body.clientHeight; }
function centerX(){ return (ns4||ns6) ? parseInt((screen.width/2)-(width/2)) : parseInt((screen.availWidth/2)-(width/2)); }
function centerY(){ return (ns4||ns6) ? parseInt((screen.height/2)-(height/2)) : parseInt((screen.availHeight/2)-(height/2)); }
var ns4 = (document.layers) ? 1 : 0;
var ie4 = (document.all) ? 1 : 0;
var ns6 = (document.getElementById && !document.all) ? 1 : 0;
top.resizeTo(targetwidth,targetheight);
var width=winWid();
var height=winHei();
var difx=targetwidth-winWid();
var dify=targetheight-winHei();
width+=(difx*2);
height+=(dify*2);
top.resizeTo(width,height);
top.moveTo(centerX(),centerY());

}




function glossaryplatformDetect()
{
  if(navigator.appVersion.indexOf("Win") != -1)
  {
    MM_openBrWindow('glossary/index.cfm','whatever1','toolbar=no,location=no,status=no,menubar=no,resizable=no,width=550,height=375');
  }
  else if(navigator.appVersion.indexOf("Mac") != -1)
  {
    MM_openBrWindow('glossary/index.cfm','whatever1','toolbar=no,location=no,status=no,menubar=no,resizable=no,width=535 ,height=375');
  }
  else alert("Other");
}


function libraryplatformDetect()
{
  if(navigator.appVersion.indexOf("Win") != -1)
  {
    MM_openBrWindow('library/index.cfm','whatever1','toolbar=no,location=no,status=no,menubar=no,resizable=no,width=550,height=375');
  }
  else if(navigator.appVersion.indexOf("Mac") != -1)
  {
    MM_openBrWindow('library/index.cfm','whatever1','toolbar=no,location=no,status=no,menubar=no,resizable=no,width=535 ,height=375');
  }
  else alert("Other");
}
