///////////////////////////
// htmlcore.js
// All Javascript functions used for Perception delivery
// Copyright Questionmark Computing 2002 - 2006
// Version:	4.3.0.3
//
// last modified 27.06.2006
//
// turn off applet and QxQ support to begin with

var QMJava = false;
var isQxQ = false;

// detect browser being used
bSB = false;	// is Preception Secure Browser
var isIE = false;	// is Internet Explorer or compatible
var isIE4 = false; 	// is Internet Explorer 4 
var isIE5 = false; 	// is Internet Explorer 5 
var isIE6 = false; 	// is Internet Explorer 6 
var isNN6 = false;	// is Netscape 6 or later 
var isDOM1 = false;	// supports DOM v1 or later
var isSaf = false;	// is Safari Browser

if ( (navigator.appName.indexOf("Internet Explorer") > -1) &&
	 (parseInt(navigator.appVersion) > 3) ) {
	isIE = true;
	if (navigator.userAgent.indexOf("MSIE 6")!=-1) {
		isIE6 = true;
	} else {
		if (navigator.userAgent.indexOf("MSIE 5")!=-1) {
			isIE5 = true;
		} else {
			isIE4 = true;
		}
	}
} 

if ( (navigator.appName.indexOf("Netscape") > -1) &&
	 (parseInt(navigator.appVersion) >= 5) ) {
	if (navigator.userAgent.indexOf("Firefox") > -1) {
		isDOM1 = true;
		isIE = true;
	} else {		
		if(navigator.userAgent.indexOf('Safari') > -1)
		{
			isSaf = true;
			isDOM1 = true;
		}
		else {
			isNN6 = true;
		}
	}
}

if (isIE6 || isIE5 || isNN6) {
	isDOM1 = true;
} 


//Register an empty unload method to clear cache for firefox
//Fast Back and Forward Button
if(window.addEventListener)
{
	window.addEventListener("unload",function() { }, false );
}

function DoSubmit() {

	if (bSubmitted) return false;

	if (iConfirmSubmit == 1) {
		if (!window.confirm(sConfirmSubmitText)) {
			return false;
		}
	}

	if (QMJava) {
		CheckApplets();
	} 
	for (i = 0; i < document.forms[0].length; i++) { 
		if (document.forms[0].elements[i].type == "submit") {
			document.forms[0].elements[i].disabled = true;
		}
	}
	bSubmitted = true;
	window.setTimeout('ResetSubmit()',iSubmitTimeout * 1000);
	return true;
}

function ResetSubmit() {
	bSubmitted = false;
	for (i = 0; i < document.forms[0].length; i++) { 
		if (document.forms[0].elements[i].type == "submit") {
			document.forms[0].elements[i].disabled = false;
		}
	}
}

function DoReset() {
	if (iConfirmReset == 1) {
		if (!window.confirm(sConfirmResetText)) {
			return false;
		}
	}
	document.forms[0].reset();
	return false;
}

function DoQuit() {
	if (iConfirmQuit == 1) {
		if (!window.confirm(sConfirmQuitText)) {
			return false;
		}
	}
	if (QMJava) {
		CheckApplets();
	} 

	if (isQxQ) 	{
		CheckTime();
	}

	document.forms[0].FINISH.value = "USER"; 
	document.forms[0].submit();		

	return true;
}

function DoHelp() {
	if (bSB) {
		var sParams = "href=" + sHelpWindowURL + " " + sHelpWindowFeatures;
		SB_PopUp(sParams);
	} else {
		window.open(sHelpWindowURL, sHelpWindowName, sHelpWindowFeatures); 
	}
}


// check the value of an input box to see if its a valid number
function checkNumber(obj) {

	if (obj.value == "") { return; }

	// use a copy of the number, force to string
	var sNumber = "" + obj.value;
	// remove blanks
	sNumber = sNumber.replace(/\s/g,"");

	var bCommaUsed = false; // was a comma used as decimal separator

	if (iDecimalFormat == 1) {
		if (sNumber.indexOf('.') > -1) {
			alert("\"" + obj.value + "\" " + sNotNumericText);
			return;
		}
	}

	// change any commas to periods, e.g. "1,01" to "1.01"
	if (iDecimalFormat > 0) {
		if (sNumber.indexOf(',') > -1) {
			bCommaUsed = true;
			sNumber = sNumber.replace(/,/g,".");
		}
	}

	// look for any non-numeric characters
	// 0..9 . - + e E
	var sGoodChars = "0123456789.-+eE";

	for (i = 0; i < sNumber.length; i++) {
		if(sGoodChars.indexOf(sNumber.charAt(i)) == -1) {
			alert("\"" + obj.value + "\" " + sNotNumericText);
			return;
		}
	}
	
	// is it a real number ?
	floatValue = parseFloat(sNumber);
	if (isNaN(floatValue)) {
		// is it a whole number ?
		intValue = parseInt(sNumber);
		if (isNaN(intValue)) {
			// its not a number at all
			alert("\"" + obj.value + "\" " + sNotNumericText);
		} else {
			sNumber = "" + intValue;
			if (bCommaUsed) { // if a comma was converted to a period, convert it back
				sNumber = sNumber.replace(/\./g,",");
			}
			obj.value = sNumber;
		}
	} else {
		sNumber = "" + floatValue;
		if (bCommaUsed) { // if a comma was converted to a period, convert it back
			sNumber = sNumber.replace(/\./g,",");
		}
		obj.value = sNumber;
	}
}


function MatchChange(sQuestionID, oListbox) {

	var aSelects = new Array();		// array of all SELECT elements for this question
	var iNumSelects = 0;			// number of SELECT elements for this question

	// get list of all select elements for this question from hidden fields
	for (i = 0; i < document.forms[0].length; i++) { 
		if ((document.forms[0].elements[i].type == "hidden") && 
			(document.forms[0].elements[i].name == sQuestionID)){
			aSelects[iNumSelects] = document.forms[0].elements[i].value;
			iNumSelects++;
		}
	}

	// look for ALL select boxes in this form (for this question)
	// an an existing SELECT already has this option selected, 
	// set the selected option for this SELECT to 0 (which is blank)

	var thisvalue = oListbox.options[oListbox.selectedIndex].value;
	var valueselected = false;	// has previous selection of this option been found ?
	var select;			// the select box already set with this option

	// look at all form elements
	for (i = 0; i < document.forms[0].length; i++) { 
		// if its a select element with a different name to this one
		if ((document.forms[0].elements[i].type == "select-one") && 
			(document.forms[0].elements[i].name != oListbox.name)){
			// check its part of this question
			for (j = 0; j < iNumSelects; j++) {
				if (aSelects[j] == document.forms[0].elements[i].name) {
					select = document.forms[0].elements[i];
					// see if option has already been selected
					if (select.options[select.selectedIndex].value == thisvalue) {
						valueselected = true;
						break;
					}
				}
			}
		}
		if (valueselected) {
			break;
		}
	}

	// if option has already been selected, unselect this one and set focus to the other
	if (valueselected) {
		oListbox.options[oListbox.selectedIndex].selected = false;
		oListbox.selectedIndex = 0;
		select.focus();
		alert(thisvalue + " " + sSelectWarnText);
	}

}

function MRChange(sQuestionID, iMaxResponse, oCheckbox) {
	// don't do anything if being unchecked
	if (!oCheckbox.checked) {
		return;
	}

	var iChecked = 0;

	// find all checkboxes for this question
	for (i = 0; i < document.forms[0].length; i++) { 
		// finc checkbox elements with same name as (and including) this one
		if ((document.forms[0].elements[i].type == "checkbox") && 
			(document.forms[0].elements[i].name == oCheckbox.name)){
			// count how many are checked
			if (document.forms[0].elements[i].checked) {
				iChecked++;
			}
		}
	}

	// if equal to max don't allow this one to be checked
	if (iChecked > iMaxResponse) {
		oCheckbox.checked = false;
	}
}

// check all applets for Question Applets
function CheckApplets() {  

   // don't do anything if we're not needed
   if (!QMJava) {
      return true;
   } 
   var sType = ""; var sApplet = ""; var sField = ""; var sValue = ""; var sEval = ""; var sName = "";     
   var sSubField = ""; var sTemp = ""; var sSubValue = "";
   var iPos = 0; var iLength = 0;

   // look at each form element
   for (i = 0; i < document.forms[0].length; i++) { 
      sValue = "";
      sTemp = "";
      sName = document.forms[0].elements[i].name;
      iPos = sName.indexOf(':');

      if (iPos > -1) {
         sType = sName.substring(0,iPos);
         sApplet = sName.substring(iPos+1,sName.length);
         sField = document.forms[0].elements[i].value;
         if (sType == "QMApplet") {
		// we've found an applet, get it's value
		var appObj;
		if (isDOM1) {
			appObj = document.getElementById(sApplet);	
		} else {
			appObj = document.applets[sApplet]; 
		}
		if (appObj) {
			sValue = "" + appObj.getValue(); 
		} 
		// see if reporting more than one choice
		iPos = sValue.indexOf(':');
		if (iPos > -1) {
			// get values for all choice IDs
			while ((iPos != -1) && (iPos < sValue.length)){					
				sSubField = sValue.substring(0,iPos);			
				sTemp = sValue.substring(iPos+1,sValue.length); 		
				iPos = sTemp.indexOf(':');
				if (iPos > -1) {
					sSubValue = sTemp.substring(0,iPos);
				}
				if (sSubValue.length > 0) {			
					// find corresponding form field
					for (j = 0; j < document.forms[0].length; j++) {
						sName = document.forms[0].elements[j].name;
						if (sName == sSubField) {
							// set field to applet value
							document.forms[0].elements[j].value = sSubValue;
							break;
						}
					}
				}
				sValue = sTemp.substring(iPos+1,sTemp.length); 	
				iPos = sValue.indexOf(':');
			}
		} else {
			// use single value for whole question
			// find corresponding form field
	            	for (j = 0; j < document.forms[0].length; j++) {
				sName = document.forms[0].elements[j].name;
				if (sName == sField) {
					// set field to applet value
					document.forms[0].elements[j].value = sValue;
					break;
				}
	            	}
		}
         }
      }

   }
   return true;
}

// swallow return key, except for text areas
// prevents unintentional submitting of block
function checkReturn(evt) {
    var evt = (evt) ? evt : ((window.event) ? window.event : null);
	var bReturn = false;
	var bCancel = false;

    if (evt) {
		if (evt.keyCode) {
			bReturn = (evt.keyCode == 13);
		} else {
			if (evt.charCode) {
				bReturn = (evt.charCode == 13);
			}
		} 

		var elem = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
        if (elem) {
			if ((bReturn) && (elem.type != "textarea")) bCancel = true;
		}

		if (bCancel) {
			evt.returnValue = false;
			evt.cancelBubble = true;
			if (evt.preventDefault)	evt.preventDefault();
			return false;
		}
    }
}

// general functions for Flash support
var iChoice = 0;
function QM_setInfo(choiceID, questionID, command, args) {
 //alert(choiceID + ", " + questionID + ", " + command + ", " + args);
	command = String(command);
  	switch (command){
     	case "MM_cmiSendInteractionInfo":
		args = String(args);
  		if (args != "")
		{
			var F_intData = args.split(";");
			var result = F_intData[7]; 
			var interaction = F_intData[2];
			SetChoice(choiceID,result);
			SetInteraction(interaction,result)
		}
		if (isQxQ){
			// find the question object
			var objThis = aElements[iActive];

			if (objThis) {
				// mark the question as answered
				objThis.setAnswered(true);
		
				// unflag it if it is flagged
				if (objThis.getFlag()) {
					objThis.setFlag(false);
				}
				// reset navigation panel
				SetNav();
			} 
		}
		break;
	case "CMISetFailed":
		SetChoice(choiceID,"W");
		break;
	case "CMISetPassed":
		SetChoice(choiceID,"C");
		break;
	case "CMIInitialize":
		if (iFlashSubmit == 1) {
			for (i = 0; i < document.forms[0].length; i++) { 
				if (document.forms[0].elements[i].type == "submit") {
					document.forms[0].elements[i].disabled = true;
				}
			}
			bSubmitted = true;
		}
		break;
	case "CMIExitAU":
		
		if (iFlashSubmit == 2) {
			document.forms[0].submit();
		} else {
			if (iFlashSubmit == 1) {
				ResetSubmit();
			}
		}
		break;
	}
	SetComment(questionID,command + " " + args);
}

function SetChoice(choiceID,result) {
	for (i = 0; i < document.forms[0].length; i++) { 
		// find the required hidden field for the question (choiceID)
		if ((document.forms[0].elements[i].type == "hidden") && (document.forms[0].elements[i].name == choiceID)) {
			// set the value
			document.forms[0].elements[i].value = result;
		}	
	}
}
function SetInteraction(intID,result) {
	for (i = 0; i < document.forms[0].length; i++) { 
		if ((document.forms[0].elements[i].type == "hidden") && (document.forms[0].elements[i].id == "intid" + intID)) {
			// set the value
			document.forms[0].elements[i].value = result;
		}
	}
}
function SetComment(questionID,comment) {
	for (i = 0; i < document.forms[0].length; i++) { 
		if ((document.forms[0].elements[i].type == "hidden") && (document.forms[0].elements[i].name == 'COM_' + questionID)) {
			// set the value
			document.forms[0].elements[i].value = document.forms[0].elements[i].value + "\r\n" + comment;
			break;
		}
	}
}

// keep track of the time left
function DoTimer() { 
  // initialise timer
  if (!bTimerInit) {
	StartTime = new Date();
	bTimerInit = true;
  }
  // update clock
  NowTime = new Date();
  clockStart = Math.round(clockInit - ((NowTime.getTime() - StartTime.getTime())/1000)); 

  var tSecs = clockStart; 
  var iSecs = tSecs % 60;
  var iMins = Math.round((tSecs-30)/60); 
  if (iMins < 0) iMins = 0;
  var iHours = 0; 
  var sHours = " ";
  if (iMins > 59) {
	iHours = Math.round((iMins-30)/60);//iMins / 60;
	iMins = iMins % 60;
	sHours = "" + iHours + ":";
  } 
  var sSecs =":" + ((iSecs > 9) ? iSecs : "0" + iSecs);
  var sMins ="" + ((iMins > 9) ? iMins : "0" + iMins);
  if (useStatus == 1) {
		document.forms[0].timespent.value = sHours + sMins + sSecs;
	} else {
		if (clockStart > 0) {
			status = remainText + " " + sHours + sMins + sSecs;
		} else {
			status = finishText;
		}
  }
  if (clockStart > 0) {
	// give warning of impending time limit
	if ((clockWarning > 0) && (clockWarning < clockInit) && (clockStart <= clockWarning)) {
		clockWarning = 0; // only happens once
		if ((bSB) || (!bMessagePopUp)) {
			// use Perception Secure Browser
			alert(sTimeLimitWarnText);
		} else {
			// use standard browser
			timerWindow = window.open("","timer","width=" + warnWidth + ",height=" + warnHeight + ",resizable=yes"); 
			message = warnMessage;
			window.setTimeout('DoMessage(timerWindow,message);',200);
			window.setTimeout('CloseWindow(timerWindow);',warnTime); 
		}
	}

	window.setTimeout('DoTimer()',1000); 
  } else {
	// give time limit reached message and submit the page
	if ((bSB)  || (!bMessagePopUp)) {
		// use Perception Secure Browser
		alert(finishText);
		window.setTimeout('Finish(null)',warnTime); 
	} else {
		timerWindow = window.open("","timer","width=" + warnWidth + ",height=" + warnHeight + ",resizable=yes"); 
		message = finishMessage;
		window.setTimeout('DoMessage(timerWindow,message)',200);
		window.setTimeout('Finish(timerWindow)',warnTime); 
	}
  }
}

// open a pop-up window for messages
function DoMessage(msgWindow,msg) {
	msgWindow.document.open();
	msgWindow.document.write(warnHead);
	msgWindow.document.write(warnBody);
	msgWindow.document.write(warnTitle);
	msgWindow.document.write(msg);
	msgWindow.document.write('</BODY></HTML>');
	msgWindow.document.close();

}

// function to finish when time limit reached
function Finish(msgWindow) {
	CloseWindow(msgWindow);
	if (QMJava) {
		CheckApplets();
	}
 
	if (isQxQ) 	{
		CheckTime();
	}

	document.forms[0].FINISH.value = "TIMER"; 
	document.forms[0].submit();
}

function CloseWindow(theWindow) {
	if ((theWindow != null) && (!theWindow.closed)){
		theWindow.close();
	}
}


// set saving to occur automatically after interval
// Bug 7462: changed this function to be tottaly independant from DoSAYG(), as was creating an infinate loop.
// first time it runs it dosn't save, it just starts the timer.
function SetSAYGTimer() {
	if (bSAYGTimer) 
	{
			if(bFirstSAYG == 0)	{ DoSAYG(); } else{bFirstSAYG = 0;}
			window.setTimeout('SetSAYGTimer()',iSAYGInterval);
	}
}

// disable button for limited time to stop java being overwhelmed ( not used anymore, as java called EnableSAYGButton when it's finished proccessing)
var bDisabledButton = false;
//Default Save button value
var sSaveButtonText = "Save";
function DisableSAYGButton() {
	//first try catch for normal templates
	try
	{
		if(document.QUESTION.Save.value.length > 0) 
		{
			sSaveButtonText = document.QUESTION.Save.value;
		}
		
		document.QUESTION.Save.disabled=true;
		document.QUESTION.Save.value="Saving";
	}
	catch(err)
	{
	}

	//second try catch to check for QxQ templates with save button ( cannot disable an image )
	try
	{
		//check if a value exists before setting the variable
		if(document.getElementById('qsave').Save.value.length > 0)
		{
			sSaveButtonText = document.getElementById('qsave').Save.value;
		}
		document.getElementById('qsave').disabled=true;
		document.getElementById('qsave').Save.value="Saving";
	}
	catch(err)
	{
	}

	bDisabledButton = true;



	
}

//enable the SAYG button again ( called by Java when it's finished processing )
function EnableSAYGButton() {


	try
	{
		
		document.QUESTION.Save.disabled=false;
		document.QUESTION.Save.value=sSaveButtonText;
	}
	catch(err)
	{
	}

	try
	{
		document.getElementById('qsave').disabled=false;
		document.getElementById('qsave').Save.value=sSaveButtonText;
	}
	catch(err)
	{
	}

	bDisabledButton = false;

	
}

//start auto save timer logic
var bFirstSAYG = 1;
//window.setTimeout('SetSAYGTimer()',1000);


//var to stop function running more then once at a time
var bIsDoSAYGrunning = false;
// collect all form data and pass to SAYG applet
function DoSAYG() {
	
	//check if already running
	if (bIsDoSAYGrunning == false && bDisabledButton == false)
	{	
		bIsDoSAYGrunning = true;
		DisableSAYGButton();
		
		if (iAskConfirmSAYG == 1) {
			if (!window.confirm(sConfirmSAYGText)) {
				//SetSAYGTimer(); 7462, timer logic dosn't require this
				return false;
			}
		}

		var appObj = null;
		var sValue = "";
		var sName = "";
		
		if (isDOM1) {
			appObj = document.getElementById('saveapplet');	
		} else {
			appObj = document.applets['saveapplet']; 
		}

		if (appObj && bSAYGApplet) {

			if (QMJava) {
				CheckApplets();
			}

			for (i = 0; i < document.forms[0].length; i++) { 

				if (document.forms[0].elements[i].type) {

					// We need to specifically handle radio buttons and check boxes.
					if (document.forms[0].elements[i].type.toLowerCase() == "checkbox" || document.forms[0].elements[i].type.toLowerCase() == "radio")
					{
						if (document.forms[0].elements[i].checked)
						{
							sName = document.forms[0].elements[i].name;
							sValue = document.forms[0].elements[i].value;
							appObj.setParameter(sName, sValue);
						}
					}
					else if (document.forms[0].elements[i].type.toLowerCase() == "select-one") {
						sName = document.forms[0].elements[i].name;
						sValue = document.forms[0].elements[i].options[document.forms[0].elements[i].selectedIndex].value;
						appObj.setParameter(sName, sValue);
					}
					else if (document.forms[0].elements[i].type.toLowerCase() != "submit" && document.forms[0].elements[i].type.toLowerCase() != "reset" && document.forms[0].elements[i].type.toLowerCase() != "button" && document.forms[0].elements[i].type.toLowerCase() != "fileupload")
					{
						sName = document.forms[0].elements[i].name;
						sValue = document.forms[0].elements[i].value;
						appObj.setParameter(sName, sValue);
					}
				}

			}
			appObj.refresh();;
		} else {
			alert("SaveApplet not found");
		}

		bIsDoSAYGrunning = false;
		return false;
	}
	
}



// get a named attribute from an html element
function GetAttribute(sAttName, obj) {
	
	var sAttValue = null;

	if (isIE) {
		eval ("sAttValue = obj." + sAttName);
	} else {
		var objAttColl = obj.attributes;
		var objAtt = objAttColl.getNamedItem(sAttName);
		if (objAtt) {
			sAttValue = objAtt.value;
		}
	}

	return sAttValue;
}

// construct a windows features string from the attribute of an html (hyperlink) element
function GetWindowFeatures(obj) {

	var sFeatures = "";

	var sAtt;

	sAtt = GetAttribute("SCROLLBARS", obj);
	if (sAtt) {
		sFeatures += "scrollbars=" + sAtt + ", ";
	}

	sAtt = GetAttribute("TOOLBAR", obj);
	if (sAtt) {
		sFeatures += "toolbar=" + sAtt + ", ";
	}

	sAtt = GetAttribute("STATUS", obj);
	if (sAtt) {
		sFeatures += "status=" + sAtt + ", ";
	}

	sAtt = GetAttribute("RESIZABLE", obj);
	if (sAtt) {
		sFeatures += "resizable=" + sAtt + ", ";
	}

	sAtt = GetAttribute("MENUBAR", obj);
	if (sAtt) {
		sFeatures += "menubar=" + sAtt + ", ";
	}

	sAtt = GetAttribute("LOCATION", obj);
	if (sAtt) {
		sFeatures += "location=" + sAtt + ", ";
	}

	sAtt = GetAttribute("HEIGHT", obj);
	if (sAtt) {
		sFeatures += "height=" + sAtt + ", ";
	}

	sAtt = GetAttribute("WIDTH", obj);
	if (sAtt) {
		sFeatures += "width=" + sAtt + ", ";
	}

	return sFeatures;

}

// launch content in a new window
function DoContent(obj) {
	
	var sGUID;
	if (obj != null)
	{
		//HTML DOM standard of referring to HTML elements attribute for browser's compatibility.
		sGUID=obj.getAttribute("GUID");
	}
	var sContentURL = sContentEngine + sGUID  + "&NAME=" + escape(sUserName) + "&GROUP=" + escape(sGroup) + "&ACCESS=" + sAccess;
	var sFeatures = GetWindowFeatures(obj);
	if (bSB) {
		var sParms = "href=" + sContentURL + " " + sFeatures;
		SB_PopUp(sParms);
	} else {
		contentWindow = window.open(sContentURL,"Content",sFeatures);
	}
	return false;
}

// launch content in a new window (for tryout in AM)
function DoContentTryout(obj) {
	var sContentURL = obj.href;
	var sFeatures = GetWindowFeatures(obj);
	if (bSB) {
		var sParms = "href=" + sContentURL + " " + sFeatures;
		SB_PopUp(sParms);
	} else {
		contentWindow = window.open(sContentURL,"Content",sFeatures);
	}
	return false;
}

// open hyperlink in a new window
function DoLink(obj) {
	var sURL = obj.href;
	var sFeatures = GetWindowFeatures(obj);

	if (bSB) {
		var sParms =  "href=" + sURL + " " + sFeatures;
		SB_PopUp(sParms);
	} else {
		linkWindow = window.open(sURL,"Link",sFeatures);
	}
	return false;
}

// display MathML
function WriteMathML(mathmlID) {
	var objMathML = null;

	if (isDOM1) {
		objMathML = document.getElementById(mathmlID);
	} else {
		document.writeln(sMathMLBrowserText);
	}

	if (objMathML != null) {
		var sMathML = objMathML.innerHTML;
		document.writeln('<applet class="mathml" codebase="' + sJavaPath + '" code="webeq3.ViewerControl" width="' + objMathML.width + '" height="' + objMathML.height + '" align="middle">');
		document.write('<param name=eq value="' + sMathML + '">');
		document.writeln('<param name=color value="' + sMathMLColor + '">');
		document.writeln('<param name=size value="' + sMathMLSize + '">');
		document.writeln('<param name=parser value="mathml">');
		document.writeln('</applet><br/>');
	} else {
		document.writeln(sMathMLScriptText);
	}
}

// handle PIP home button
function PipHome() {
	if (bPipCloseHome) {
		if (bSB) {
			SB_ExitQS();
		} else {
			window.close();
		}
		return false;
	} else {
		document.location = sPipLink;
	}
}


// do PIP notification in pop-up window
function PipNotifyWindow() {
   
	if (bPipNotifyWindow) {
		if(!bSB) { // if Secure Browser not present 
			var wSCO = window.open('','new_window','height=100,width=100,toolbar=0,location=0,directories=0,menubar=0,resizable=0,status=0,scrollbars=0');
			wSCO.opener = this.opener;
			this.focus();
			wSCO.document.location = sPipLink;
		}  else  {
			if (false==SB_SetSCORMResults(sPipLink))  {
				alert("Unable to locate the SCORM launch frame, the results have not been returned.")
			}  
		}
	}
}

/******************************************************
 Function: Insert Flash

This is a function that dynamically writes the object
and embed tags to insert a Flash object. 
*******************************************************/

function insertFlash(swf,width,height,bgcolor,params,pairs) {
	
	// set default bgcolor if not provided
	if(!bgcolor || bgcolor=="") bgcolor = "#FFFFFF";
	
	//parse pairs
	var flashvars="";
	var writeAmp=false;
	for(var i in pairs){
		if (writeAmp){flashvars=flashvars+"&";}else{writeAmp=true;}
		
		if(window.encodeURIComponent){
			flashvars=flashvars+i+"="+encodeURIComponent(pairs[i]);
		}else{ // use escape
	  		flashvars=flashvars+i+"="+escape(pairs[i]);
		}

	}
	//alert(flashvars);
	
	
	if(!params) params = new Object();
	if(!params.version) params.version = "6,0,0,0";
	if(!params.FlashVars) params.FlashVars=flashvars;
	
	// parse parameters
	var objectParams = "";
	var embedParams = "";
	for(var i in params) {
		objectParams += "<PARAM NAME="+i+" VALUE=\""+params[i]+"\">\n";
		embedParams += i+"=\""+params[i]+"\" ";
	}

	//alert(embedParams);

	// write the object
	var sContent="";

	sContent+="<OBJECT  classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" ";
	sContent+="codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version="+params.version+"\"";
	sContent+="WIDTH=\""+width+"\" HEIGHT=\""+height+"\" id=\"flash\" ALIGN=\""+params.align+"\">";
	sContent+="<PARAM NAME=movie VALUE=\""+swf+"\">";
	sContent+="<PARAM NAME=quality VALUE=high>";
	sContent+="<PARAM NAME=bgcolor VALUE=#ffffff>";
	sContent+="<PARAM NAME=wmode VALUE=transparent>";
	sContent+="<PARAM NAME=scale VALUE=noscale>";
	sContent+="<PARAM NAME=salign VALUE=\"lt\">";
	sContent+=objectParams;
	sContent+="<EMBED src=\""+swf+"\" quality=high  scale=\"noscale\" SALIGN=\"lt\" ";
        
	//This is a workaround for Mozilla / Netscape - it requires scale after salign rather than before
	//if(navigator.appName=="Netscape"){sContent+=" scale=\"noscale\" "; }
	// Paul - removed 27.01.06 - doesn't seem to do anything
	
	sContent+=" bgcolor=\"#FFFFFF\" wmode=\"transparent\" WIDTH=\""+width+"\" HEIGHT=\""+height+"\" name=\"flash\" ALIGN=\""+params.align+"\"";
	sContent+=embedParams;
	sContent+=" TYPE=\"application/x-shockwave-flash\" PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\"></EMBED>";
	sContent+="</OBJECT>";


	if (isDynamicJava)
	{
		document.write("<div id=\"qDiv" + iQDivCount + "\" ></div>");
		DoAddJavaApplet(iQDivCount,sContent);		
	}
	else
	{
		document.write(sContent);
	}

}

/******************************************************
 Function: New Size

This changes the size of an object in the HTML. Using it
with div objects primarily.
*******************************************************/

function newSize(objectname,datoX,datoY) {
	
	//alert(objectname + " : " + datoX+" "+datoY);
	if(document.all && !document.getElementById) {
 		document.all[objectname].style.pixelWidth = datoX + "px";
 		document.all[objectname].style.pixelHeight = datoY + "px";
	}else{
		if (isDynamicJava)
		{
			document.getElementById(objectname).style.width = datoX  + "px";
		} else {
			// needs to be a bit wider to get over Firefox/Mozilla 'bug'
			document.getElementById(objectname).style.width = (datoX + (datoX / 5)) + "px";
		}
		document.getElementById(objectname).style.height = datoY + "px";
	}
}

/******************************************************
 Function: Get Max Width

This returns the maximum available width in the browser
that does not cause horizontal scrollbars to appear.
*******************************************************/


function getMaxWidth() {
	
	var ns4 = (document.layers)? true:false;
	var ie4 = (document.all)? true:false;
	var winW = (ie4)?  document.body.offsetWidth : window.innerWidth ;
	return winW;
}

/******************************************************
 Function: Set Hidden Values

Sets a number of hidden values in a form to a new value.

*******************************************************/

function setHiddenValues(ids,values){

	var theIds=ids.split(",");
	var theValues=values.split(",");

	for (var i = 0; i < theIds.length; i++) {
		if(window.decodeURIComponent){
			setHiddenValue(decodeURIComponent(theIds[i]),decodeURIComponent(theValues[i]));
		}else{ // use unescape
			setHiddenValue(unescape(theIds[i]),unescape(theValues[i]));
		}
	}

}


/******************************************************
 Function: Set Hidden Value

This sets a hidden value in a form to a new value.

*******************************************************/

function setHiddenValue(id,value){

	for (var i = 0; i < document.forms[0].length; i++) {
		if (document.forms[0].elements[i].name == id){
				document.forms[0].elements[i].value=value;
			return true;
   		}
	}

}

/******************************************************
 Function: Report Error

This reports an error has occured

*******************************************************/

function reportError(errorText){
	alert(errorText);
}


/******************************************************
 Fix for Issue 21734P - Load Java Applets dynamically in IE
*******************************************************/

var sQDivContents=new Array();
var iQDivNumbers=new Array();
var iQDivCount=0;
var previousonLoad=null;
var bOnLoadReplaced=false;

var isDynamicJava=(navigator.userAgent.search("MSIE")!=-1);

function DoAddJavaApplet(iQNumber, sContent)
{
	if (isIE)
	{
		if (!bOnLoadReplaced)
		{
			previousonLoad=document.body.onLoad;
			document.body.onLoad=setTimeout(DoCreateJavaApplets,500);
			bOnLoadReplaced=true;
		}
	}

	sQDivContents[iQDivCount]=sContent;
	iQDivNumbers[iQDivCount]=iQNumber;
	iQDivCount++;
}

function DoCreateJavaApplets()
{
	if (previousonLoad!=null) 
	{
		eval(previousonLoad);
	}

	for (i=0;i<iQDivCount;++i)
	{
		document.getElementById("qDiv" + iQDivNumbers[i]).innerHTML=sQDivContents[i];
	}
}


// javascript functions for DHTML Drag and Drop

// prevent IE text selection while dragging
function windowLoaded(evt) {

	var aDivs = document.body.getElementsByTagName("div");

	for (iDiv = 0; iDiv < aDivs.length; iDiv++) {
		if (aDivs.item(iDiv).className == "hotTarget") {
			Reset(aDivs.item(iDiv).id,((document.forms[0].name == "FEEDBACK") || (document.forms[0].name == "END")),sAlignMarkers);
		}
	}

	document.body.ondrag = function () { return false; };
	
	//Disable mouse RIGHT CLICK
	if (bDisableRightClick){
	   document.body.onselectstart = function () { return false; };
	}


	//changed
	
	if(document.forms[0] != null)
	{
		bIsFeedback = ((document.forms[0].name == "FEEDBACK") || (document.forms[0].name == "END"));	
	}
}


// utility functions to set and get position and size
function getX(node) {
	return parseInt(node.style.left);
}

function getY(node) {
	return parseInt(node.style.top);
}

function getWidth(node) {
	return parseInt(node.style.width);
}

function getHeight(node) {
	return parseInt(node.style.height);
}

function setX(node,x) {
	node.style.left = x + "px";
}

function setY(node,y) {
	node.style.top = y + "px";
}

// event handling hooks

// define our own event object
function Evt(evt) {
	this.evt = evt ? evt : window.event; 
	this.source = evt.target ? evt.target : evt.srcElement;
	this.x = evt.pageX ? evt.pageX : evt.clientX;
	this.y = evt.pageY ? evt.pageY : evt.clientY;
	this.button = evt.button;
}


// swallow the event
Evt.prototype.consume = function () {
	if (this.evt.stopPropagation) {
		this.evt.stopPropagation();
		this.evt.preventDefault();
	} else if (this.evt.cancelBubble) {
		this.evt.cancelBubble = true;
		this.evt.returnValue  = false;
	}
};

// capture specific events
Evt.addEventListener = function (target,type,func,bubbles) {
	if (document.addEventListener) {
		target.addEventListener(type,func,bubbles);
	} else if (document.attachEvent) {
		target.attachEvent("on"+type,func,bubbles);
	} else {
		target["on"+type] = func;
	}
};

// release specific event
Evt.removeEventListener = function (target,type,func,bubbles) {
	if (document.removeEventListener) {
		target.removeEventListener(type,func,bubbles);
	} else if (document.detachEvent) {
		target.detachEvent("on"+type,func,bubbles);
	} else {
		target["on"+type] = null;
	}
};

// dragged object is starting to move
// object is constrained within area defined by 0,0 and mX,mY
function dragStart(evt, mX, mY) {

	if (bIsFeedback) return;

	evt = new Evt(evt);

	bIsDrag = true;
	maxX = mX;
	maxY = mY;
	objMarker = evt.source;

	deltaX = evt.x - getX(objMarker);
	deltaY = evt.y - getY(objMarker);

	// capture mouse moves
	Evt.addEventListener(document,"mousemove",dragMove,false);

	// capture mouse button up
	Evt.addEventListener(document,"mouseup",dragStop,false);

	evt.consume();
}

// dragged object is moving
function dragMove(evt) {
	evt = new Evt(evt);
	
	xPos = evt.x - deltaX;
	yPos = evt.y - deltaY;

	if (xPos < 1) xPos = 0;
	if (yPos < 1) yPos = 0;
	if (xPos > maxX) xPos = maxX;
	if (yPos > maxY) yPos = maxY;

	setX(objMarker,xPos);
	setY(objMarker,yPos);
	evt.consume();
}

// dragged object has been dropped
function dragStop(evt) {
	evt = new Evt(evt);
	bIsDrag = false;

	// release mouse moves
	Evt.removeEventListener(document,"mousemove",dragMove,false);

	// release mouse button up
	Evt.removeEventListener(document,"mouseup",dragStop,false);

	// take the centre of the object as the answer coordinate
/*
	xPos = Math.round(parseInt(objMarker.style.left) + (parseInt(objMarker.style.width) / 2));
	yPos = Math.round(parseInt(objMarker.style.top) + (parseInt(objMarker.style.height) / 2));
*/
	xPos = Math.round(parseInt(objMarker.style.left) + (parseInt(objMarker.width) / 2));
	yPos = Math.round(parseInt(objMarker.style.top) + (parseInt(objMarker.height) / 2));

	if (xPos < 1) xPos = 0;
	if (yPos < 1) yPos = 0;
	if (xPos > maxX) xPos = maxX;
	if (yPos > maxY) yPos = maxY;

	objMarker.setAttribute("position", xPos + "," + yPos);
	
	// update form fields here

	// find hidden field matching choice ID
	aFields = document.getElementsByName(objMarker.id)
	for (i = 0; i < aFields.length; i++) {
		if (aFields.item(i).type = "hidden") {
			aFields.item(i).value = xPos + "," + yPos;
		}
	}

	if (!bIsFeedback) {
		SetQxQAnswered(objMarker.parentNode.id,true);
	}

	// debug
	//alert(objMarker.id + " : x " + xPos + ", y " + yPos);

	evt.consume();
}
	
function clickTarget(evt,objTarget,mX, mY) {

	if (bIsFeedback) return;
	if (bIsDrag) return;
	// check we're not clicking on the marker itself
	var source = evt.target ? evt.target : evt.srcElement;
	if (source.className == "hotMarker") return;

	var aChildren = objTarget.childNodes;
	var objMarker = null;
	var iNumMarkers = 0;

	for (var i = 0; i < aChildren.length; i++) {
		if (aChildren.item(i).className == "hotMarker") {
			objMarker = aChildren.item(i);
			iNumMarkers++;
		}
	}

	if (iNumMarkers > 1) {
		return;
	}

	maxX = mX;
	maxY = mY;

	if (evt.layerX) {
		xPos = evt.layerX;
		yPos = evt.layerY;
	} else {
		xPos = evt.offsetX;
		yPos = evt.offsetY;
	}

	// take the centre of the object as the answer coordinate
/*
	var objWidth = Math.round( (parseInt(objMarker.style.width) / 2));
	var objHeight = Math.round( (parseInt(objMarker.style.height) / 2));
*/
	var objWidth = Math.round( (parseInt(objMarker.width) / 2));
	var objHeight = Math.round( (parseInt(objMarker.height) / 2));


	if (xPos < objWidth) xPos = objWidth;
	if (yPos < objHeight) yPos = objHeight;
	if (xPos > (maxX - objWidth)) xPos = maxX - objWidth;
	if (yPos > (maxY - objHeight)) yPos = maxY - objHeight;

	// center the marker on the click
	setX(objMarker,xPos - objWidth);
	setY(objMarker,yPos - objHeight);
// debug	
// alert(objMarker.id + " : width " + objWidth + ", x " + objMarker.style.left + ", height " + objHeight + ", y " + objMarker.style.top);

	// find hidden field matching choice ID
	aFields = document.getElementsByName(objMarker.id)
	for (i = 0; i < aFields.length; i++) {
		if (aFields.item(i).type = "hidden") {
			aFields.item(i).value = xPos + "," + yPos;
		}
	}

	if (!bIsFeedback) {
		SetQxQAnswered(objTarget.id,true);
	}
 
}



// move all markers back to their correct position	
// only alignment of bottom supported at the moment
// use saved value of position if set (for feedback or SYAG restart)
function Reset(sDiv,bFeedback,sAlignment) {

	bIsFeedback = bFeedback;
	var objTarget = document.getElementById(sDiv);
	var aChildren = objTarget.childNodes;
	var iLeft = 0;
	var iHeight = parseInt(objTarget.style.height);


	for (i = 0; i < aChildren.length; i++) {
		if (aChildren.item(i).className == "hotMarker") {
			aChildren.item(i).style.width = aChildren.item(i).width;
			aChildren.item(i).style.height = aChildren.item(i).height;
			// get x,y position from position attribute
			var sPos = aChildren.item(i).getAttribute("position");
			// if this is non-blank, it's either feedback or a saved value from SAYG
			if (sPos) {
				aCoords = sPos.split(",");
				// centre the marker on the coordinate
				if ( (!isNaN(parseInt(aCoords[0]))) && (!isNaN(parseInt(aCoords[1]))) ) {
					aChildren.item(i).style.left = Math.round(parseInt(aCoords[0]) - (parseInt(aChildren.item(i).width) / 2)) + "px";
					aChildren.item(i).style.top = Math.round(parseInt(aCoords[1]) - (parseInt(aChildren.item(i).height) / 2)) + "px";
				}
			} else {
				aChildren.item(i).style.left = iLeft + "px";
				aChildren.item(i).style.top = iHeight - aChildren.item(i).height + "px";
			}
			//This sorts vertically
			//iHeight = iHeight - aChildren.item(i).height;
			//This Horizontally
			iLeft = iLeft + aChildren.item(i).width;
		}
	}

}

// move all markers back to start position
// clear position data from form fields
function Clear(sDiv,sAlignment) {

	var objTarget = document.getElementById(sDiv);
	var aChildren = objTarget.childNodes;
	var iLeft = 0;
	var iHeight = parseInt(objTarget.style.height);

	for (var i = 0; i < aChildren.length; i++) {
		if (aChildren.item(i).className == "hotMarker") {
			// align the marker
			aChildren.item(i).style.width = aChildren.item(i).width;
			aChildren.item(i).style.height = aChildren.item(i).height;
			aChildren.item(i).style.left = iLeft;
			aChildren.item(i).style.top = iHeight - aChildren.item(i).height;
			iLeft = iLeft + aChildren.item(i).width;

			// clear the form field
			// find hidden field matching choice ID
			aFields = document.getElementsByName(aChildren.item(i).id)
			for (var j = 0; j < aFields.length; j++) {
				if (aFields.item(j).type = "hidden") {
					aFields.item(j).value = "";
				}
			}

			// set question unanswered
			SetQxQAnswered(objTarget.id,false);
		}
	}
}

// for QxQ delivery set this question as answered
function SetQxQAnswered(sQID,bAnswered) {

	if (isQxQ) {
		// add "Q_" prefix to question ID
		var sQuestionId = "Q_" + sQID;
		// check each question to find the one this marker comes from
		for (var k = 1; k < (aQuestions.length); k++) {
			if (aQuestions[k].getId() == (sQuestionId)) {
				// set the question as answered
				aQuestions[k].setAnswered(bAnswered);
				break;
			}
		}
	} 
}

// functions for survey matrix questions

// highlight the left most cell in a row (the choice text)
function Highlight(idRow,idCol,on) {

	if (document.forms[0].name != "QUESTION") return;

	objRow = document.getElementById(idRow);
	objCol = document.getElementById(idCol);
	if (on) {
		objRow.className = 'smatRowHighlight';
		objCol.className = 'smatHeadHighlight';
	} else {
		objRow.className = 'smatRow';
		objCol.className = 'smatHead';
	}
}

// highlight an indiviual cell
function HighlightCell(idTable, idQuestion, active) {
	
	if (document.forms[0].name != "QUESTION") {
		if (!active) return;
	}

	// find the table
	objTable = document.getElementById(idTable);

	// get all radio buttons in the table
	setRadio = objTable.getElementsByTagName('input');

	var objRadio;
	var objCell;

	for (i = 0; i < setRadio.length; i++) {
		objRadio = setRadio[i];
		// look at radio buttons of class 'smatRadio'
		if (objRadio.className == 'smatRadio') {
			// find the cell it's in
			objCell = objRadio.parentNode;
			if (objCell)  {
				// highlight the cell if the radio button is checked
				if (objRadio.checked) {
					objCell.className = 'smatOptionHighlight';
					if (idQuestion != '0') {
						SetQxQAnswered(idQuestion,true);
						break;
					}
				} else {
					objCell.className = 'smatOption';
				}
			}
		}
	}
}

// pass click from a cell onto the radio button inside it
function ClickCell(objCell,idTable) {

	if (document.forms[0].name != "QUESTION") return;

	var objRadio = null;

	for (i = 0; i < objCell.childNodes.length; i++) {
		if (objCell.childNodes.item(i).className == 'smatRadio') {
			objRadio = objCell.childNodes.item(i);
			break;
		}
	}

	if (objRadio != null) {
		objRadio.click();
	}
}

// file upload functions
/*
Launch the upload program with these parameters :

Name - participant name, for logging purposes
Group - member group, for logging purposes, may be blank
Access - access token, for logging purposes
QuestionID - the ID of the question the file is being uploaded for
Whitelist - list of permitted file extensions, may be blank
Config - name of config file to use, may be blank
Checksum - MD5 hashcode of the above 
*/	
function DoFileUpload(sQuestionID, sWhitelist, sChecksum) {

	if (bIsFeedback) return;

	if (sUploadURL.length == 0) return;

	var objCancel = null;
	if (bShowCancel)  {
		objCancel = document.getElementById('cancel' + sQuestionID);
	}

	var sURL = sUploadURL + '?Name=' + sUploadName + '&Group=' + sUploadGroup + '&Access=' + sUploadAccess + '&QuestionID=' + sQuestionID + '&Whitelist=' + sWhitelist + '&Config=' + sUploadConfig + '&Checksum=' + sChecksum;

	if (bSB) {
		// Questionmark Secure
		SB_PopUp( 'href=' +  document.location.protocol + '//' + document.location.host + sURL + ' height=' + sUploadHeight + ' width=' + sUploadWidth);
	} else {
		// normal browser
		if (objWindowList[sQuestionID]  == null) {
			objWindowList[sQuestionID] = window.open(sURL,sQuestionID,'height=' + sUploadHeight + ', width=' + sUploadWidth + ', ' + sUploadFeatures);

			var objSubmit = document.getElementById('qm_SUBMIT');
			objSubmit.disabled = true;
			var objQuestionField = document.getElementById('upload' + sQuestionID);
			var objDisplayField = document.getElementById('display' + sQuestionID);
			objDisplayField.value = sUploadProgressText;
			var objUploadButton = document.getElementById('button' + sQuestionID);
			objUploadButton.title = sUploadProgressToolTip;
		} else {
			objWindowList[sQuestionID].focus();
		}
	}

	if (bShowCancel)  { 
		objCancel.style.visibility = 'visible';
	}

}

/*
Function called by Upload program with these parameters :
QuestionID - the ID of the question the file is being uploaded for
Status - 0 = abandoned or cancelled, 1 = file sucessfully uploaded
Filename - full local pathname of file uploaded
Savename - name uploaded file was saved as
*/
function UploadNotify(sQuestionID,  iStatus, sFilename, sSavename) {

	//alert(sQuestionID + ", " +  iStatus + ", " + sFilename + ", " + sSavename);

	var objDisplayField = document.getElementById('display' + sQuestionID);
	var objChoiceField = document.getElementById('filename' + sQuestionID);
	var objSaveField = document.getElementById('savename' + sQuestionID);
	var objUploadButton = document.getElementById('button' + sQuestionID);
	var objSubmit = document.getElementById('qm_SUBMIT');
	var objCancel = null;
	if (bShowCancel)  {
		objCancel = document.getElementById('cancel' + sQuestionID);
	}

	if (iStatus == 1) {
		
		objChoiceField.value = sFilename;
		objDisplayField.value = sFilename;
		objSaveField.value = sSavename;
		objUploadButton.disabled = true;
		objUploadButton.title = sUploadFinishedToolTip;
	} else {
		objDisplayField.value = "";
		objUploadButton.title = sUploadToolTip;
	}

	if (!bSB) {
		if (objWindowList[sQuestionID]  != null && objWindowList[sQuestionID].open && !objWindowList[sQuestionID].window.closed) {
			objWindowList[sQuestionID].close();
		}
		objWindowList[sQuestionID]  = null;
	}

	if (bShowCancel)  {
		objCancel.style.visibility = 'hidden';
	}
	objSubmit.disabled = false;

}

// cancel the upload for this question
// close the window
function UploadCancel(objCancel,sQuestionID) {

	if (!bShowCancel)  { return; }
	
	var objDisplayField = document.getElementById('display' + sQuestionID);
	var objUploadButton = document.getElementById('button' + sQuestionID);
	var objSubmit = document.getElementById('qm_SUBMIT');

	if (!bSB) {
		if (objWindowList[sQuestionID]  != null  && objWindowList[sQuestionID].open && !objWindowList[sQuestionID].closed) 	{
			var objWindow = objWindowList[sQuestionID];
			objWindowList[sQuestionID]  = null;
			objWindow.close();
		}
	}
	objWindowList[sQuestionID]  = null;
	objDisplayField.value = "";
	objUploadButton.title = sUploadToolTip;
	objSubmit.disabled = false;
	objCancel.style.visibility = 'hidden';
}
function addReloadObjectHandler()
{
   if (window.attachEvent && window.detachEvent){
	window.detachEvent("onload",reloadActiveXObject);
   	window.attachEvent("onload",reloadActiveXObject);
  }
}

function reloadActiveXObject()
{
	if (document.getElementsByTagName && document.body.outerHTML) 
	{
      		var tags = ['object','embed','applet'];

  		for (var i in tags) {
        	
        	// get all elements with tag
        	var objs = document.getElementsByTagName(tags[i]);
		
		if(objs !=  null && objs.length > 0)
		{
        		for (var j=0;j < objs.length;j++) 
			{
            			var obj = objs.item(j);

            			// find param tags within object
            			var params = obj.getElementsByTagName('param');
            			var inner = '';

            			// if there are params, but param tags can't be found within innerHTML
            			if (params != null && params.length >0)
            			{    // add all param tags to 'inner' string
                			for (var x=0;x < params.length;x++)
                    				inner += params.item(x).outerHTML;
				}
            
				// put 'inner' string with param tags in the middle of the outerHTML
				obj.outerHTML = obj.outerHTML.replace('>', '>' + inner);
        		}
  		}
	   }
	}

}



