
function addOnLoadFunc(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    };
  }
}

/**
 * Returns the answer selected by the user for the given question number on a
 * page. Note: question_num == the page-specific question number (e.g., 0, 1,
 * etc.). question_num != the question ID.
 */
function getSelectedAnswer(question_num) {
	if (!document.getElementById) {
		return null;
	}
	
	var ans = ["A","B","C","D","E"];
	for (var i=0; i<ans.length; i++) {
		if (document.getElementById("q"+question_num+"_ans"+ans[i]).checked) {
			return ans[i];
		}
	}
	return null;
}

var SafeGPTrack = {
	_trackShareThis: function()
	{
		try
		{
			pageTracker._trackEvent('Sharing', 'ShareThis');
		}
		catch (e)
		{
		}
	}
};

var AJAX = {
	createHttpRequest: function()
	{
		try {
			return new XMLHttpRequest();
		} catch (trymicrosoft) {
			try {
				return new ActiveXObject("Msxml2.XMLHTTP");
			} catch (othermicrosoft) {
				try {
					return new ActiveXObject("Microsoft.XMLHTTP");
				} catch (failed) {
					return null;
				}
			}
		}
	},
	
	getAbsoluteRootPath: function()
	{
		var currentUrl = window.location.href;
		
		if (currentUrl.indexOf("http://192.168.1.149") != -1)
		{
			return "http://192.168.1.149/platinum/";
		}
		else if (currentUrl.indexOf("http://localhost") != -1)
		{
			return "http://localhost/platinum/";
		}
		else if (currentUrl.indexOf("http://platinumgmat.com") != -1)
		{
			ErrorLogger.logWarning("User accessing non-www URL.");
			return "http://www.platinumgmat.com/";
		}
		else if (currentUrl.indexOf("http://www.platinumgmat.com") != -1)
		{
			return "http://www.platinumgmat.com/";
		}
		else if (currentUrl.indexOf("https://www.platinumgmat.com") != -1)
		{
			return "https://www.platinumgmat.com/";
		}
		else if (currentUrl.indexOf("http://192.168.1.101") != -1)
		{
			return "http://192.168.1.101/platinum/website/www/";
		}
		else if (currentUrl.indexOf("http://192.168.0.2") != -1)
		{
			return "http://192.168.0.2/platinum/website/www/";
		}
		else if (currentUrl.indexOf("http://127.0.0.11/") != -1)
		{
			return "http://127.0.0.11/platinum/website/www/";
		}
		else if (currentUrl.indexOf("http://192.168.0.8/") != -1)
		{
			return "http://192.168.0.8/platinum/website/www/";
		}
		else if (currentUrl.indexOf("http://eab/") != -1)
		{
			return "http://eab/platinum/website/www/";
		}
		else
		{
			return "http://www.platinumgmat.com/";
		}
	},
	
	getAbsoluteHttpsRootPath: function()
	{
		var url = AJAX.getAbsoluteRootPath();
		return url.replace(/http:\/\/www.platinumgmat/, "https://www.platinumgmat");
	}
};

var CheckoutHandler = {
	updateTotalCostProductInformation: function(productId, unitPrice, newQuantity)
	{	
		var payPalDomElement = document.getElementById("paypal-form-container");
		
		if (document.getElementById("paypal-checkout-loading-active") == undefined
			|| document.getElementById("paypal-checkout-loading-active") == null)
		{
			var spinnerImage = document.getElementById("paypal-checkout-loading").cloneNode(true);
			spinnerImage.setAttribute("id", "paypal-checkout-loading-active");
			payPalDomElement.appendChild(spinnerImage);
		}
		if (document.getElementById("frm-paypal-submit") != undefined
			&& document.getElementById("frm-paypal-submit") != null)
		{
			document.getElementById("frm-paypal-submit").className = 'checkout-account-form-element-disabled';
		}
		
		document.getElementById("paypal-checkout-loading-active").className = 'checkout-account-form-element-enabled';
		
		var newTotalCost = (new Number(unitPrice)) * (new Number(newQuantity));
			
		if (document.getElementById("product_" + new String(productId) + "_total_price") != undefined
			&& document.getElementById("product_" + new String(productId) + "_total_price") != null)
		{
			document.getElementById("product_" + (new String(productId)) + "_total_price").innerHTML = newTotalCost;
		}
		
		CheckoutHandler.updateTotalOrderPride();
		CheckoutHandler.updatePayPalButton();
	},
	
	updateTotalOrderPride: function()
	{
		if (document.getElementById("checkout-total-order-price") == undefined
			|| document.getElementById("checkout-total-order-price") == null
			|| document.getElementById("checkout-product-ids") == undefined
			|| document.getElementById("checkout-product-ids") == null)
		{
			return false;
		}
		var totalOrderPrice = 0;
		
		var productIds = document.getElementById("checkout-product-ids").value;
		
		var productIdsArray = productIds.split(',');
		for (var i = 0; i < productIdsArray.length; i++)
		{
			if (document.getElementById("product_" + (new String(productIdsArray[i])) + "_total_price"))
			{
				totalOrderPrice += new Number(document.getElementById("product_" + (new String(productIdsArray[i])) + "_total_price").innerHTML);
			}
		}
		document.getElementById("checkout-total-order-price").innerHTML = totalOrderPrice;
	},
	
	updatePayPalButton: function()
	{
		handleServerErrorResponse = function(myAjaxSocket)
		{
			if (document.getElementById("frm-paypal-encrypted") != undefined
				&& document.getElementById("frm-paypal-encrypted") != null)
			{
				document.getElementById("frm-paypal-encrypted").value = '';
			}
		}
		
		handleServerSuccessResponse = function(myAjaxSocket)
		{
			if (myAjaxSocket.responseText == '100')
			{
				handleServerErrorResponse(myAjaxSocket);
				return false;
			}
			var ajaxResponseText = myAjaxSocket.responseText;
			if (ajaxResponseText.indexOf("-BEGIN") == -1
				|| ajaxResponseText.indexOf("PKCS7-") == -1)
			{
				handleServerErrorResponse(myAjaxSocket);
			}
			
			if (document.getElementById("paypal-checkout-loading-active") != undefined
				&& document.getElementById("paypal-checkout-loading-active") != null)
			{
				document.getElementById("paypal-checkout-loading-active").className = 'checkout-account-form-element-disabled';
			}
			
			if (document.getElementById("frm-paypal-encrypted") != undefined
					&& document.getElementById("frm-paypal-encrypted") != null)
			{
				document.getElementById("frm-paypal-encrypted").value = ajaxResponseText;
			}
			
			if (document.getElementById("frm-paypal-submit") != undefined
					&& document.getElementById("frm-paypal-submit") != null)
			{
				document.getElementById("frm-paypal-submit").className = 'checkout-account-form-element-enabled';
			}
		}
		
		var myAjaxSocket = AJAX.createHttpRequest();
		if (myAjaxSocket == null)
		{
			/*
			* XML Http Request Object not supported. Enable standard submission to proceed.
			*/
			return true;
		}
		
		myAjaxSocket.onreadystatechange = function()
		{
			if(myAjaxSocket.readyState == 4)
			{
				if (myAjaxSocket.status == 200)
				{
					handleServerSuccessResponse(myAjaxSocket);
				}
				else
				{
					handleServerErrorResponse(myAjaxSocket);
				}
			}
		}
		
		var pStringValue = '';
		var qStringValue = '';
		
		var checkoutForm = document.getElementById("plat-checkout-form");
		var regularExpressionFormNameCheck = new RegExp("product_([1-9]){1,3}_quantity");
		for (var i = 0; i < checkoutForm.elements.length; i++)
		{
			var formElementName = new String(checkoutForm.elements[i].name);
			if (regularExpressionFormNameCheck.test(formElementName))
			{
				var arrFormMatch = formElementName.match(regularExpressionFormNameCheck);
				pStringValue += arrFormMatch[1] + ',';
				qStringValue += checkoutForm.elements[i].value + ',';
			}
		}
		
		pStringValue = pStringValue.substr(0, (pStringValue.length - 1));
		qStringValue = qStringValue.substr(0, (qStringValue.length - 1));
		
		var parameters = "p=" + pStringValue + "&q=" + qStringValue;
		myAjaxSocket.open("GET", AJAX.getAbsoluteHttpsRootPath() + "ajax/paypal_button?mode=ajax&" + parameters);
		myAjaxSocket.send(null);
	},
	
	preselectCardType: function(ccNumberInput)
	{
		ccNumber = new Number(ccNumberInput);
		if (ccNumber < 2
			|| document.getElementById("field-cctype").options[0].selected == false)
		{
			return false;
		}
		
		ccNumber = new String(ccNumber);
		if (ccNumber.substr(0,1) == "4")
		{
			document.getElementById("field-cctype").options[1].selected = true;
		}
		else if (ccNumber.substr(0,1) == "5")
		{
			document.getElementById("field-cctype").options[2].selected = true;
		}
		else if (ccNumber.substr(0,1) == "6")
		{
			document.getElementById("field-cctype").options[3].selected = true;
		}
	},
	
	receiveNoExtantAccountChecked: function()
	{
		if (document.getElementById("extant-account-login") != undefined
				&& document.getElementById("extant-account-login") != null)
		{
			document.getElementById("extant-account-login").className = "checkout-account-form-element-disabled"
		}
	
		if (document.getElementById("extant-account-creation") != undefined
				&& document.getElementById("extant-account-creation") != null)
		{
			document.getElementById("extant-account-creation").className = "checkout-account-form-element-enabled";;
		}	
	},
	
	receiveExtantAccountChecked: function()
	{
		if (document.getElementById("extant-account-login") != undefined
			&& document.getElementById("extant-account-login") != null)
		{
			document.getElementById("extant-account-login").className = "checkout-account-form-element-enabled";
		}
	
		if (document.getElementById("extant-account-creation") != undefined
			&& document.getElementById("extant-account-creation") != null)
		{
			document.getElementById("extant-account-creation").className = "checkout-account-form-element-disabled";
		}
		
		if (document.getElementById("extant-member-login-pw") != undefined
			&& document.getElementById("extant-member-login-pw") != null)
		{
			document.getElementById("extant-member-login-pw").focus();
		}
	},
	
	
	receivePlatinumCheckoutChecked: function()
	{
		if (document.getElementById("table-platinum-checkout-billing-info") != undefined
				&& document.getElementById("table-platinum-checkout-billing-info") != null)
		{
			document.getElementById("table-platinum-checkout-billing-info").className = "checkout-account-form-element-enabled";
		}
	
		if (document.getElementById("platinumgmat-checkout-button") != undefined
			&& document.getElementById("platinumgmat-checkout-button") != null)
		{
			document.getElementById("platinumgmat-checkout-button").className = "checkout-account-form-element-enabled";
		}
		
		if (document.getElementById("paypal-form-container") != undefined
				&& document.getElementById("paypal-form-container") != null)
		{
			document.getElementById("paypal-form-container").className = "checkout-account-form-element-disabled";
		}
	},
	
	receivePaypalCheckoutChecked: function()
	{
		if (document.getElementById("table-platinum-checkout-billing-info") != undefined
				&& document.getElementById("table-platinum-checkout-billing-info") != null)
		{
			document.getElementById("table-platinum-checkout-billing-info").className = "checkout-account-form-element-disabled";
		}
	
		if (document.getElementById("platinumgmat-checkout-button") != undefined
			&& document.getElementById("platinumgmat-checkout-button") != null)
		{
			document.getElementById("platinumgmat-checkout-button").className = "checkout-account-form-element-disabled";
		}
		
		if (document.getElementById("paypal-form-container") != undefined
				&& document.getElementById("paypal-form-container") != null)
		{
			document.getElementById("paypal-form-container").className = "checkout-account-form-element-enabled";
		}
	},
	
	validateCreditCardNumber: function(ccNumber, domNotificationId)
	{
		var ccNumberPattern = new RegExp("^[0-9]{12,25}$");
		var isValid = ccNumberPattern.test(ccNumber);
		if (document.getElementById(domNotificationId) != undefined
				&& document.getElementById(domNotificationId) != null)
		{
			if (!isValid
				&& ccNumber.length > 0)
			{
				document.getElementById(domNotificationId).innerHTML = "The credit card number you entered appears to be invalud.";
				document.getElementById(domNotificationId).className = "checkout-account-form-element-enabled";
			}
			else
			{
				document.getElementById(domNotificationId).innerHTML = "";
				document.getElementById(domNotificationId).className = "checkout-account-form-element-disabled";				
			}
		}
	},
	
	validateCreditCardVerification: function(ccNumber, domNotificationId)
	{
		var ccVerificationPattern = new RegExp("^[0-9]{1,5}$");
		var isValid = ccVerificationPattern.test(ccNumber);
		if (document.getElementById(domNotificationId) != undefined
				&& document.getElementById(domNotificationId) != null)
		{
			if (!isValid
				&& ccNumber.length > 0)
			{
				document.getElementById(domNotificationId).innerHTML = "The credit card verification number appears to be invalud.";
				document.getElementById(domNotificationId).className = "checkout-account-form-element-enabled";
			}
			else
			{
				document.getElementById(domNotificationId).innerHTML = "";
				document.getElementById(domNotificationId).className = "checkout-account-form-element-disabled";				
			}
		}
	}
};

var ToggleGlobalGetUrlGui = {
	toggleGlobalGetUrlDisplay: function(domId, parentDomId, openLeft)
	{
		var domIdName = domId;
		var domId = document.getElementById(domId);
		var parentDomId = document.getElementById(parentDomId); 
		if (domId == null
			|| domId == undefined
			|| parentDomId == null
			|| parentDomId == undefined)
		{
			return false;
		}
		
		if (openLeft == null
			|| openLeft == undefined
			|| openLeft == true)
		{
			openLeft = true;
		}
		else
		{
			openLeft = false;
		}
		
		/*
		 * Internet Explorer displays the website such that the GetUrlGui should always open up on the right. 
		 */
		var is_ie6 = (
				window.external &&
				typeof window.XMLHttpRequest == "undefined"
		);
		if (is_ie6)
		{
			openLeft = false;
		}
		
		if (domId.className == "get-link-disabled")
		{
			element = parentDomId;
			var y = 0;
			for (var e = element; e; e = e.offsetParent)
			{
				y += e.offsetTop;
			}

			var x = 0;
			element = parentDomId;
			while (element)
			{
				x += element.offsetLeft;
				element = element.offsetParent;
			}

			domId.className = "get-link-enabled";
			
			if (openLeft)
			{
				domId.style.left = (x-400) + "px";
			}
			else
			{
				domId.style.left = (x+20) + "px";
			}
			
			domId.style.top = (y+25) + "px";
			
			document.getElementById(domIdName + "-textbox").select();
			document.getElementById("div-overlay").className = "div-overlay-enabled";
		}
		else if (domId.className = "get-link-enabled")
		{
			domId.className = "get-link-disabled";
			document.getElementById("div-overlay").className = "display-none";
		}
		
		return false;
	}
};

var MemberLoginGui = {
	handleSignOutClick: function()
	{
		if (typeof myAjaxSessionGuiDriver != 'undefined'
			&& myAjaxSessionGuiDriver != undefined 
			&& myAjaxSessionGuiDriver != null
			&& myAjaxSessionGuiDriver instanceof AjaxSessionGuiDriver
			&& typeof myAjaxSessionGuiDriver.receiveRequestForStateChangeToSignOut == 'function')
		{
			myAjaxSessionGuiDriver.receiveRequestForStateChangeToSignOut();
			MemberLoginGui.cleanOutCacheUponLoginStatusChange();
			return false;
		}
		return true;
	},
	
	handleLoginSubmit: function()
	{
		if (document.getElementById("member-login-pw") != undefined
			&& document.getElementById("member-login-pw") != null
			&& document.getElementById("member-login-mn") != undefined
			&& document.getElementById("member-login-pw") != null
			&& document.getElementById("member-login-mn").value.length != 0
			&& document.getElementById("member-login-pw").value.length != 0)
		{
			var myAjaxSocket = AJAX.createHttpRequest();
			if (myAjaxSocket == null)
			{
				/*
				* XML Http Request Object not supported. Enable standard submission to proceed.
				*/
				return true;
			}
			
			myAjaxSocket.onreadystatechange = function()
			{
				printServerErrorResponse = function()
				{
					document.getElementById("member-login-box-notification-contents").innerHTML = "Unfortunately, it appears that either the connection between your web browser and the server was lost or an error occurred on the server. Please try refreshing the webpage. If the problem persists, please contact us.";
					document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
				}
				
				if(myAjaxSocket.readyState == 4)
				{
					if (myAjaxSocket.status == 200)
					{
						var response = myAjaxSocket.responseText;
						if (response == "0")
						{
							MemberLoginGui.cleanOutCacheUponLoginStatusChange();
							
							document.getElementById("member-login-box-notification-contents").innerHTML = "";
							
							document.title = "Login Successful";
					        if (document.getElementById("title") != undefined &&
					                document.getElementById("title") != null)
					        {
					            document.getElementById("title").innerHTML = "Login Successful"; 
					        }
					        
							var displayHtml = '<p>Any quizzes or practice tests you attempt will now be saved.</p>';
							displayHtml += '<ul><li><a href="' + AJAX.getAbsoluteRootPath() +  'gmat-practice-test/?state=mh-qcl">View My History of Quizzes and Practice Tests</a></li><li><a href="' + AJAX.getAbsoluteRootPath() + 'gmat-practice-test/?state=qc-cn">Take a New Quiz</a></li><li><a href="' + AJAX.getAbsoluteRootPath() + 'gmat-practice-test/">Take a New Practice Test</a></li></ul>';
							document.getElementById("div-member-login-container").innerHTML = displayHtml;
							document.getElementById("div-member-login-container").className = "member-login-notification-contents-update";
							
							MemberLoginGui.changeUpperRightUponLoginSuccess();
						}
						else if (response == "100")
						{
							document.getElementById("member-login-box-notification-contents").innerHTML = "This account is not yet active. In order to activate this account, please follow the instructions sent in the registration email. If you did not receive an email or you would like another email, please visit the sign in page and click \"I cannot access my accont\"";
							document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
						}
						else if (response == "1003")
						{
							printServerErrorResponse();
						}
						else
						{
							document.getElementById("member-login-box-notification-contents").innerHTML = "The login credentials you supplied were incorrect. Please try again.";
							document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
						}
					}
					else
					{
						printServerErrorResponse();
					}
				}	
			}
			
			var parameters = "membername=" + document.getElementById("member-login-mn").value + "&password=" + document.getElementById("member-login-pw").value;
			
			myAjaxSocket.open("POST", AJAX.getAbsoluteHttpsRootPath() + "memberSignin?state=doLoginAuthentication&mode=ajax");
			
			myAjaxSocket.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			myAjaxSocket.setRequestHeader("Connection", "close");
			
			myAjaxSocket.send(parameters);
			
			document.getElementById("member-login-box-notification-contents").innerHTML = "Processing Login. Please wait.";
			document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-update";
			return false;
			
		}
		else if (document.getElementById("member-login-pw").value.length == 0)
		{
			document.getElementById("member-login-box-notification-contents").innerHTML = "Please specify a password.";
			document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
			return false;
		}
		else if (document.getElementById("member-login-mn").value.length == 0)
		{
			document.getElementById("member-login-box-notification-contents").innerHTML = "Please specify a username.";
			document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
			return false;
		}
		
		/*
		* Return true as a fail-safe. If JS could not handle submission, ensure it is dealt with in the traditional means.
		*/
		return true;
	},
	
	handleSendPasswordResetSubmit: function()
	{
		if (document.getElementById("member-login-mn") != undefined
				&& document.getElementById("member-login-mn") != null
				&& document.getElementById("member-login-mn").value.length != 0)
		{
			if (MemberLoginGui.testEmail(document.getElementById("member-login-mn").value) == false)
			{
				document.getElementById("member-login-box-notification-contents").innerHTML = "The email address you specified does not appear to be valid.";
				document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
				return false;				
			}
		}
		else
		{
			document.getElementById("member-login-box-notification-contents").innerHTML = "Please specify an email address.";
			document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
			return false;
		}
		
		/*
		* Return true as a fail-safe. If JS could not handle submission, ensure it is dealt with in the traditional means.
		*/
		return true;
	},
	
	changeUpperRightUponLoginSuccess: function()
	{
		if (document.getElementById("member-signup-anchor") != null
			&& document.getElementById("member-signup-anchor") != undefined)
		{
			document.getElementById("member-signup-anchor").className = "member-link-login-component-disabled";
		}
		
		if (document.getElementById("member-link-divider") != null
			&& document.getElementById("member-link-divider") != undefined)
		{
			document.getElementById("member-link-divider").className = "member-link-login-component-disabled";
		}
		
		if (document.getElementById("member-signin-anchor") != null
			&& document.getElementById("member-signin-anchor") != undefined)
		{
			document.getElementById("member-signin-anchor").className = "member-link-login-component-disabled";
		}
		
		if (document.getElementById("member-signout-anchor") != null
			&& document.getElementById("member-signout-anchor") != undefined)
		{	
			document.getElementById("member-signout-anchor").className = "member-link-login-component-enabled";
		}
	},
	
	cleanOutCacheUponLoginStatusChange: function()
	{
		if (typeof myBackgroundContentLoader != 'undefined' 
			&& myBackgroundContentLoader != undefined
			&& myBackgroundContentLoader != null
			&& myBackgroundContentLoader instanceof BackgroundContentLoader 
			&& myBackgroundContentLoader.publicDownloadAllQuestionIdsMarkedForReview != null
			&& myBackgroundContentLoader.publicDownloadAllQuestionIdsMarkedForReview != undefined
			&& typeof myBackgroundContentLoader.publicDownloadAllQuestionIdsMarkedForReview == 'function')
		{
			MarkedQuestionRepositoryManager.clearMarkedQuestions();
			myBackgroundContentLoader.publicDownloadAllQuestionIdsMarkedForReview();
		}
		
		if (typeof myBackgroundContentLoader != 'undefined'
			&& myBackgroundContentLoader != undefined
			&& myBackgroundContentLoader != null
			&& myBackgroundContentLoader instanceof BackgroundContentLoader
			&& myBackgroundContentLoader.publicDownloadAllQuestionIdsMarkedForReview != null
			&& myBackgroundContentLoader.publicDownloadAllQuestionIdsMarkedForReview != undefined
			&& typeof myBackgroundContentLoader.publicDownloadAllQuestionIdsMarkedForReview == 'function')
		{
			/*
			 * There is no need to re-download the Question Context list since every time My History is loaded
			 * the list is downloaded.
			 */
			QuestionContextRepositoryManager.clearQuestionContexts();
		}		
	},
	
	NO_PASSWORD: 0,
	TOO_FEW_CHARACTERS: 1,
	STRONG_PASSWORD: 2,
	MEDIUM_PASSWORD: 3,
	WEAK_PASSWORD: 4,
	
	testPasswordStrength: function(password)
	{
		var strongRegex = new RegExp("^(?=.{8,})(?=.*[A-z])(?=.*[0-9])(?=.*\[^a-zA-Z0-9]).*$", "g");
		var mediumRegex = new RegExp("^(?=.{8,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$", "g");
		var enoughRegex = new RegExp("(?=.{8,}).*", "g");
		
		if (password.length == 0)
		{
			return MemberLoginGui.NO_PASSWORD;
		}
		else if (password.length < 8)
		{
			return MemberLoginGui.TOO_FEW_CHARACTERS;
		}
		else if (strongRegex.test(password))
		{
			return MemberLoginGui.STRONG_PASSWORD;
		}
		else if (mediumRegex.test(password))
		{
			return MemberLoginGui.MEDIUM_PASSWORD;
		}
		else
		{
			return MemberLoginGui.WEAK_PASSWORD;
		}
	},
	
	testEmail: function(email)
	{
	    var emailRegex = new RegExp("^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+\.([a-zA-Z])+([a-zA-Z])+");
	    return emailRegex.test(email);
	},
	
	testUsername: function(username)
	{
		if (username.indexOf("_") !== -1
		    || username.indexOf("-") !== -1)
	    {
	    	return false;
	    }
		var usernameRegex = new RegExp("^([a-zA-Z0-9]){6,}");
	    return usernameRegex.test(username);
	},
	
	inlineUsernameValidation: function(username, domId)
	{
		if (MemberLoginGui.testUsername(username) == false)
		{
			document.getElementById(domId).innerHTML = "The username you entered is invalid. It must be at least six characters in length and contain only alpha-numeric characters.";
			document.getElementById(domId).className = "member-login-notification-contents-error";
		}
		else
		{
			document.getElementById(domId).innerHTML = "";	
		}
	},
	
	inlineEmailValidation: function(email, domId)
	{
		if (MemberLoginGui.testEmail(email) == false)
		{
			document.getElementById(domId).innerHTML = "The email address you entered is invalid.";
			document.getElementById(domId).className = "member-login-notification-contents-error";
		}
		else
		{
			document.getElementById(domId).innerHTML = "";	
		}
	},
	
	passwordStrengthSuggestion: function(password, notificationDomId)
	{
		if (document.getElementById(notificationDomId) == null
			|| document.getElementById(notificationDomId) == undefined)
		{
			return false;
		}
		var result = MemberLoginGui.testPasswordStrength(password);
		switch(result)
		{
			case MemberLoginGui.NO_PASSWORD:
				document.getElementById(notificationDomId).innerHTML = "A password must be 8 characters.";
				document.getElementById(notificationDomId).className = "member-login-notification-contents-error";
				break;
			case MemberLoginGui.TOO_FEW_CHARACTERS:
				document.getElementById(notificationDomId).innerHTML = "A password must be 8 characters.";
				document.getElementById(notificationDomId).className = "member-login-notification-contents-error";
				break;
			case MemberLoginGui.WEAK_PASSWORD:
				document.getElementById(notificationDomId).innerHTML = "Consider strengthening your password by including both letters and numbers.";
				document.getElementById(notificationDomId).className = "member-login-password-strength-notification-suggestion";
				break;
			case MemberLoginGui.MEDIUM_PASSWORD:
				document.getElementById(notificationDomId).innerHTML = "Consider strengthening your password by including a non alpha-numeric chatacter.";
				document.getElementById(notificationDomId).className = "member-login-password-strength-notification-suggestion";
				break;
			case MemberLoginGui.STRONG_PASSWORD:
				document.getElementById(notificationDomId).innerHTML = "Your password is strong!";
				document.getElementById(notificationDomId).className = "member-login-password-strength-notification-strong";
				break;
		}
	},
	
	handleSignupSubmit: function()
	{		
		if (document.getElementById("member-login-pw") != undefined
			&& document.getElementById("member-login-pw") != null
			&& document.getElementById("member-login-mn") != undefined
			&& document.getElementById("member-login-pw") != null
			&& document.getElementById("member-login-em") != undefined
			&& document.getElementById("member-login-em") != null
			&& document.getElementById("member-login-pw-confirm") != undefined
			&& document.getElementById("member-login-pw-confirm") != null)
		{
			if (document.getElementById("member-login-pw-confirm").value.length <= 7
				|| document.getElementById("member-login-pw").value.length <= 7)
			{
				document.getElementById("member-login-box-notification-contents").innerHTML = "Your password must be at least 8 chatacters in length.";
				document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";				
				return false;
			}
			
			if (document.getElementById("member-login-pw-confirm").value
				!= document.getElementById("member-login-pw").value)
			{
				document.getElementById("member-login-box-notification-contents").innerHTML = "The passwords you entered do not match.";
				document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
				return false;
			}
			
			if (MemberLoginGui.testEmail(document.getElementById("member-login-em").value) == false)
			{
				document.getElementById("member-login-box-notification-contents").innerHTML = "The email address you entered is invalid.";
				document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
				return false;
			}
			
			if (MemberLoginGui.testUsername(document.getElementById("member-login-mn").value) == false)
			{
				document.getElementById("member-login-box-notification-contents").innerHTML = "The username you entered is invalid. It must be at least six characters in length and contain only alpha-numeric characters.";
				document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
				return false;
			}
			
			
			var myAjaxSocket = AJAX.createHttpRequest();
			if (myAjaxSocket == null)
			{
				/*
				* XML Http Request Object not supported. Enable standard submission to proceed.
				*/
				return true;
			}
			
			myAjaxSocket.onreadystatechange = function()
			{
				printServerErrorResponse = function()
				{
					document.getElementById("member-login-box-notification-contents").innerHTML = "Unfortunately, it appears that either the connection between your web browser and the server was lost or an error occurred on the server. Please try refreshing the webpage. If the problem persists, please contact us.";
					document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
				}
				
				if(myAjaxSocket.readyState == 4)
				{
					if (myAjaxSocket.status == 200)
					{
						var response = myAjaxSocket.responseText;
						if (response == "0")
						{
							/*
							 * Creating an Account Succeeded.
							 */
							document.getElementById("member-login-box-notification-contents").innerHTML = "";
							
							MemberLoginGui.changeUpperRightUponLoginSuccess();
							
							document.title = "Account Created - Sign Up Complete";
					        if (document.getElementById("title") != undefined &&
					                document.getElementById("title") != null)
					        {
					            document.getElementById("title").innerHTML = "Account Created - Sign Up Complete"; 
					        }
					        
					        var accountCreatedHtml = '<p>The sign up process is complete! Any quizzes or practice tests you work while signed in will be saved and available to you upon future login.</p>';
					        accountCreatedHtml += '<ul><li><a href="http://www.platinumgmat.com/gmat-practice-test/?state=qc-cn">Take a New Quiz Now</a></li><li><a href="http://www.platinumgmat.com/gmat-practice-test/">Take a New Practice Test Now</a></li></ul>';
					    
							document.getElementById("div-member-login-container").innerHTML = accountCreatedHtml;
							document.getElementById("div-member-login-container").className = "member-login-notification-contents-sign-up-complete";

						}
						else if (response == "1001")
						{
							document.getElementById("member-login-box-notification-contents").innerHTML = "A required input value is missing. Please ensure that: (1) your username is at least six characters and contains only alpha-numeric characters [no spaces or underscores] (2) your password is at least 8 characters and contains only alpha-numeric characters (3) you supplied a valid email address.";
							document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
						}
						else if (response == "1002")
						{
							document.getElementById("member-login-box-notification-contents").innerHTML = "The username is taken. Please select a different username.";
							document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
						}
						else if (response == "1003")
						{
							document.getElementById("member-login-box-notification-contents").innerHTML = "An account is already signed up with this email address.";
							document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
						}
						else if (response == "1004")
						{
							printServerErrorResponse();
						}
						else if (response == "1005")
						{
							document.getElementById("member-login-box-notification-contents").innerHTML = "An account is already signed up with this email address.";
							document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
						}
						else
						{
							document.getElementById("member-login-box-notification-contents").innerHTML = "Sign Up Data Incorrect. Please specify a valid username (at least six chatacters), password (at least eight chatacters), and email.";
							document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-error";
						}
					}
					else
					{
						printServerErrorResponse();
					}
				}	
			}
			
			var parameters = "membername=" + document.getElementById("member-login-mn").value + "&password=" + document.getElementById("member-login-pw").value + "&password-confirm=" + document.getElementById("member-login-pw-confirm").value + "&email=" + document.getElementById("member-login-em").value;
			
			myAjaxSocket.open("POST",  AJAX.getAbsoluteHttpsRootPath() + "memberSignup?state=doSignup&mode=ajax");
			
			myAjaxSocket.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			myAjaxSocket.setRequestHeader("Connection", "close");
			
			myAjaxSocket.send(parameters);
			
			document.getElementById("member-login-box-notification-contents").innerHTML = "Processing Sign Up. Please wait.";
			document.getElementById("member-login-box-notification-contents").className = "member-login-notification-contents-update";
			return false;
			
		}
		
		/*
		* Return true as a fail-safe. If JS could not handle submission, ensure it is dealt with in the traditional means.
		*/
		return true;
	}
};

var Path = {
	_pathToWebRoot: null,
	
	/*
	 * Note: This function assumes that this external JavaScript file resides
	 *       in a directory such as WEBROOT/views/something or
	 *       WEBROOT/global/something.
	 */
	toWebRoot: function()
	{
		if (Path._pathToWebRoot !== null)
		{
			return Path._pathToWebRoot;
		}
		
		var scriptElms = document.getElementsByTagName('script');
		if (scriptElms.length < 1)
		{
			// Somehow there isn't a <script> tag on the page yet this external
			// JavaScript is executing. Hmmmm... this would be bizzare.
			return '/';
		}
		
		var pagePath = window.location.href;
		var scriptPath = scriptElms[0].src;
		
		// In Internet Explorer, scriptPath may contain a relative URL along the
		// lines of "../global/script.js". The algorithm below assumes an
		// absolute URL. Thus, we must force the scriptPath to be absolute.
		// The following three lines are a convenient way to convert from a
		// relative to an absolute URL in Internet Explorer.
		var divElm = document.createElement("div");
		divElm.innerHTML = '<a href="' + scriptPath + '"></a>';
		scriptPath = divElm.firstChild.href;
		
		var sameBeforePos = 0;
		while (sameBeforePos < Math.min(pagePath.length, scriptPath.length))
		{
			if (pagePath.charAt(sameBeforePos) == scriptPath.charAt(sameBeforePos))
			{
				sameBeforePos++;
			}
			else
			{
				break;
			}
		}
		
		var pagePathUnique = pagePath.substr(sameBeforePos);
		if (pagePathUnique.indexOf('?') > -1)
		{
			pagePathUnique = pagePathUnique.substr(0, pagePathUnique.indexOf('?'));
		}
		if (pagePathUnique.indexOf('#') > -1)
		{
			pagePathUnique = pagePathUnique.substr(0, pagePathUnique.indexOf('#'));
		}
		
		var pageDepth = pagePathUnique.split('/').length - 1;
		
		var pathToWebRoot = "";
		for (var i = 0; i < pageDepth; i++)
		{
			pathToWebRoot += "../";
		}
		
		Path._pathToWebRoot = pathToWebRoot;
		
		return Path._pathToWebRoot;
		
		//alert("pathToWebRoot = " + pathToWebRoot + "\npagePath = " + pagePath + "\nscriptPath = " + scriptPath + "\nsameBeforePos = " + sameBeforePos + "\nSame String = " + pagePath.substr(0, sameBeforePos) + "\ncharAt = " + pagePath.charAt(sameBeforePos) + "\npagePathUnique = " + pagePathUnique + "\npageDepth = " + pageDepth);
		
	}
};

var Preload = {
	_images: {},
	
	preloadImages: function()
	{
		for (var i=0; i < arguments.length; i++){
			var imgEl = document.createElement('img');
			imgEl.src = arguments[i];
		}
	}
};

var Feedback = {

	_httpRequest: null,
	_showContentFoundPrompt: [],
	_showReportTypo: [],
	_showReportContentError: [],
	_showReportSpam: [],
	_previousContentFoundFeedback: [],
	_previousComment: [],
	_ratings: [],
	_texts: [],
	_comments: [],
	_contentFound: [],
	
	init: function(family, item, promptText, adjective)
	{
		if (Feedback._texts.length === 0)
		{
			// Do first time initializations
			Preload.preloadImages(
				Path.toWebRoot() + "global/images/rating/norating_on.gif?20081226",
				Path.toWebRoot() + "global/images/rating/star_on.gif?20081226" );
		}
		
		var elId = family+'-'+item;
		
		Feedback._texts[elId] = [];
		Feedback._texts[elId].prompt = promptText;
		Feedback._texts[elId].adjective = adjective;
		
		if (Feedback._showContentFoundPrompt[elId] !== true)
		{
			Feedback._showContentFoundPrompt[elId] = false;	
		}
		
		if (Feedback._previousComment[elId] === undefined)
		{
			Feedback._previousComment[elId] = null;	
		}
		
		if (Feedback._showReportTypo[elId] === undefined || Feedback._showReportTypo[elId] !== true)
		{
			Feedback._showReportTypo[elId] = false;	
		}		

		if (Feedback._showReportContentError[elId] === undefined || Feedback._showReportContentError[elId] !== true)
		{
			Feedback._showReportContentError[elId] = false;	
		}
		
		if (Feedback._showReportSpam[elId] === undefined || Feedback._showReportSpam[elId] !== true)
		{
			Feedback._showReportSpam[elId] = false;	
		}
	},
	
	getPrintHtml: function(family, item)
	{
		if (!document.getElementById) {
			// We don't stand a chance.
			return;
		}
		
		if (Feedback._httpRequest === null)
		{
			try {
				Feedback._httpRequest = new XMLHttpRequest();
			} catch (trymicrosoft) {
				try {
					Feedback._httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
				} catch (othermicrosoft) {
					try {
						Feedback._httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
					} catch (failed) {
						Feedback._httpRequest = null;
						// The user's browser doesn't support AJAX. So, don't even
						// bother printing anything to the user.
						return;
					}
				}
			}
		}
		
		var elId = family+'-'+item;
		
		Feedback._ratings[elId] = 0;
		
		var html = '<div class="inline-feedback">'
			+ '<span class="inline-feedback-prompt">' + Feedback._texts[elId].prompt + '</span>';
		
		html += '<span class="inline-feedback-stars-text-container">';
		for (var rating = 0; rating <= 5; rating++)
		{
			html += '<img class="inline-feedback-stars" id="inline-feedback-star-' + elId + '-' + rating + '" '
			      + (rating === 0 ? 'style="visibility:hidden" ' : '')
			      + 'src="' + Path.toWebRoot() + 'global/images/rating/'+(rating === 0 ? 'norating_off' : 'star_off')+'.gif?20081226" width="14" height="14" alt="X" '
			      + 'onmouseover="Feedback.mouseover(\''+family+'\',\''+item+'\','+rating+')" '
			      + 'onmouseout="Feedback.mouseout(\''+family+'\',\''+item+'\')" '
			      + 'onclick="Feedback.log(\''+family+'\',\''+item+'\','+rating+',null);Feedback.promptForComment(\''+family+'\',\''+item+'\','+rating+')" />';
		}
		
		html += '<span class="inline-feedback-action" id="inline-feedback-action-'+elId+'"></span>';
		html += '<span class="inline-feedback-status" id="inline-feedback-status-'+elId+'"></span>';
		html += '</span>';
		
		if (Feedback._showContentFoundPrompt[elId] === true)
		{
			var radioBoxYesText = "";
			var radioBoxNoText = "";
			if (Feedback._previousContentFoundFeedback[elId] === 0)
			{
				radioBoxNoText = 'checked="checked"';
			}
			else if (Feedback._previousContentFoundFeedback[elId] === 1)
			{
				radioBoxYesText = 'checked="checked"';
			}
			
			html += '<form method="get" action="" style="border:0px; margin:0px; padding:0px;"><span class="inline-feedback-desired-content-prompt">Did you find the content you wanted?</span> <input type="radio" name="found-' + elId + '" id="found-' + elId + 'yes" value="Yes" ' + radioBoxYesText + ' onclick="Feedback.log(\''+family+'\',\''+item+'\',null,null,true); Feedback.promptForComment(\''+family+'\',\''+item+'\',null, true)" /> Yes <input type="radio" name="found-' + elId + '" id="found-' + elId + 'no" value="No" ' + radioBoxNoText + ' onclick="Feedback.log(\''+family+'\',\''+item+'\',null,null,false); Feedback.promptForComment(\''+family+'\',\''+item+'\',null, true)" /> No&nbsp;<span class="inline-feedback-content-found-status" id="inline-feedback-content-found-status-'+elId+'"></span></form>';
		}
		
		if (Feedback._showReportTypo[elId] === true && Feedback._showReportContentError[elId] === true)
		{
			html += '<div><span class="inline-feedback-report-typo-display" onClick="Feedback.promptForComment(\''+family+'\',\''+item+'\',null, true);Feedback.log(\''+family+'\',\''+item+'\',null,null,null,true);this.className=\'inline-feedback-report-typo-display-clicked\'">Report Typo</span>&nbsp;&middot;&nbsp;<span class="inline-feedback-report-error-display" onClick="Feedback.promptForComment(\''+family+'\',\''+item+'\',null, true);Feedback.log(\''+family+'\',\''+item+'\',null,null,null,null,true);this.className=\'inline-feedback-report-error-display-clicked\'">Report Content Error</span></div>';
		}
		else if (Feedback._showReportTypo[elId] === true)
		{
			html += '<div><span class="inline-feedback-report-typo-display" onClick="Feedback.promptForComment(\''+family+'\',\''+item+'\',null, true);Feedback.log(\''+family+'\',\''+item+'\',null,null,null,true);this.className=\'inline-feedback-report-typo-display-clicked\'">Report Typo</span></div>';
		}
		else if (Feedback._showReportContentError[elId] === true)
		{
			html += '<div><span class="inline-feedback-report-error-display" onClick="Feedback.promptForComment(\''+family+'\',\''+item+'\',null, true);Feedback.log(\''+family+'\',\''+item+'\',null,null,null,null,true);this.className=\'inline-feedback-report-error-display-clicked\'">Report Content Error</span></div>';
		}
			
		html += '<div class="inline-feedback-comment-wrapper" id="inline-feedback-comment-wrapper-'+elId+'">';
		html += '<form method="get" action="">Please explain: <input type="button" onclick="Feedback.log(\''+family+'\',\''+item+'\',null,document.getElementById(\'inline-feedback-comment-textarea-'+elId+'\').value)" class="submit-button" value="Submit">';
		html += '<span class="inline-feedback-comment-status" id="inline-feedback-comment-status-'+elId+'"></span><br />';
		
		var textForTextArea;
		if (Feedback._previousComment[elId] !== undefined && Feedback._previousComment[elId] !== null)
		{
			if (Feedback._previousComment[elId].length > 0)
			{
				textForTextArea = Feedback._previousComment[elId];	
			}
		}
		else
		{
			textForTextArea = "";
		}
		
		html += '<div><textarea id="inline-feedback-comment-textarea-'+elId+'" rows="10" cols="40">' + textForTextArea + '</textarea></div></form>';
		html += '</div>';
		html += '</div>';
		return html;
	},
	
	print: function(family, item)
	{
		var html = Feedback.getPrintHtml(family, item);
		document.write(html);
	},
		
	mouseover: function(family, item, rating)
	{
		var elId = family+'-'+item;
		
		var actionText = '';
		switch(rating)
		{
			case 0: actionText = 'Remove all feedback.';       break;
			case 1: actionText = 'Not at all '+Feedback._texts[elId].adjective+'.'; break;
			case 2: actionText = 'A little '+Feedback._texts[elId].adjective+'.';   break;
			case 3: actionText = 'Somewhat '+Feedback._texts[elId].adjective+'.';   break;
			case 4: actionText = 'Quite '+Feedback._texts[elId].adjective+'.';      break;
			case 5: actionText = 'Extremely '+Feedback._texts[elId].adjective+'.';  break;
			default: return; // Invalid value
		}
		if (Feedback._ratings[elId] > 0) {
			var norating = document.getElementById('inline-feedback-star-'+elId+'-0');
			norating.src = Path.toWebRoot() + 'global/images/rating/norating_' + (rating === 0 ? 'on' : 'off') + '.gif?20081226';
			norating.style.visibility = 'visible';
		}
		for (var i = 1; i <= 5; i++)
		{
			var img = document.getElementById('inline-feedback-star-'+elId+'-'+i);
			if (img) {
				img.src = Path.toWebRoot() + 'global/images/rating/star_' + (i > rating ? 'off' : 'on') + '.gif?20081226';
			}
		}
		var actionEl = document.getElementById('inline-feedback-action-'+elId);
		if (actionEl) {
			// TODO Use document.createTextNode() and actionEl.setText()  or something like that
			actionEl.innerHTML = actionText;
		}
		var statusEl = document.getElementById('inline-feedback-status-'+elId);
		if (statusEl) {
			// TODO Use document.createTextNode() and statusEl.setText()  or something like that
			statusEl.innerHTML = '';
		}
		
		Feedback.hideCommentStatus(family, item);
	},
	
	initRating: function(family, item, rating)
	{
		var elId = family+'-'+item;
		Feedback._ratings[elId] = rating;
		Feedback.mouseout(family, item);
	},
	
	mouseout: function(family, item)
	{
		var elId = family+'-'+item;
		
		var norating = document.getElementById('inline-feedback-star-'+elId+'-0');
		norating.style.visibility = 'hidden';
		
		var rating = Feedback._ratings[elId];
	
		for (var i = 1; i <= 5; i++)
		{
			var img = document.getElementById('inline-feedback-star-'+elId+'-'+i);
			if (img) {
				img.src = Path.toWebRoot() + 'global/images/rating/star_' + (i > rating ? 'off' : 'on') + '.gif?20081226';
			}
		}
		var actionEl = document.getElementById('inline-feedback-action-'+elId);
		if (actionEl) {
			// TODO Use document.createTextNode() and actionEl.setText()  or something like that
			actionEl.innerHTML = '';
		}
	},
	
	promptForComment: function(family, item, rating, forceShow)
	{
		if (forceShow === undefined) {
			forceShow = false;
		}

		if (rating > 0 || forceShow === true)
		{
			var elId = family+'-'+item;
			document.getElementById('inline-feedback-comment-wrapper-'+elId).style.display = 'block';
		}
	},
	
	log: function(family, item, rating, comment, contentFound, report_typo, report_content_error, report_spam)
	{
		if (contentFound === undefined) {
			contentFound = null;
		}
		if (report_typo === undefined) {
			report_typo = null;
		}
		if (report_content_error === undefined) {
			report_content_error = null;
		}		
		if (report_spam === undefined) {
			report_spam = null;
		}	
		
		var elId = family+'-'+item;
		
		if ( (rating === null && comment === null) || Feedback._httpRequest === null ) {
			if (contentFound === null && report_typo === null && report_content_error === null && report_spam === null) {
				return;
			}
		}
		
		var explanationEl = document.getElementById('inline-feedback-action-'+elId);
		var statusEl = document.getElementById('inline-feedback-status-'+elId);
		if (!explanationEl || !statusEl) {
			return;
		}
		
		var url = Feedback._buildUrl(family, item, rating, comment, contentFound, report_typo, report_content_error, report_spam);
		
		//alert(url);
		
		if (rating !== null)
		{
			Feedback._ratings[elId] = rating;
			Feedback._httpRequest.onreadystatechange = function() {Feedback._receiptOfRating(family, item);};
		}
		else if (comment !== null)
		{
			Feedback._comments[elId] = comment;
			Feedback._httpRequest.onreadystatechange = function() {Feedback._receiptOfComment(family, item);};			
		}
		else if (contentFound !== null)
		{
			Feedback._contentFound[elId] = contentFound;
			Feedback._httpRequest.onreadystatechange = function() {Feedback._receiptOfContentFound(family, item);};
		}
		Feedback._httpRequest.open("GET", url);
		Feedback._httpRequest.send(null);
	},
	
	hideCommentStatus: function(family, item)
	{
		var statusEl = document.getElementById('inline-feedback-comment-status-'+family+'-'+item);
		if (statusEl)
		{
			statusEl.innerHTML = '';
		}
	},
	
	_setShowContentFoundPrompt: function (family, item, showStatus)
	{
		var elId = family+'-'+item;
		if (showStatus === true)
		{
			Feedback._showContentFoundPrompt[elId] = true;
		}
		else
		{
			Feedback._showContentFoundPrompt[elId] = false;
		}
	},
	
	_setShowReportTypo: function (family, item, showStatus)
	{
		var elId = family+'-'+item;
		if (showStatus === true)
		{
			Feedback._showReportTypo[elId] = true;
		}
		else
		{
			Feedback._showReportTypo[elId] = false;
		}
	},

	_setShowReportContentError: function (family, item, showStatus)
	{
		var elId = family+'-'+item;
		if (showStatus === true)
		{
			Feedback._showReportContentError[elId] = true;
		}
		else
		{
			Feedback._showReportContentError[elId] = false;
		}
	},
	
	_setShowReportSpam: function (family, item, showStatus)
	{
		var elId = family+'-'+item;
		if (showStatus === true)
		{
			Feedback._showReportSpam[elId] = true;
		}
		else
		{
			Feedback._showReportSpam[elId] = false;
		}
	},
	
	
	_setPreviousContentFoundFeedback: function (family, item, userFeedback)
	{
		var elId = family+'-'+item;
		if (userFeedback === 0)
		{
			Feedback._previousContentFoundFeedback[elId] = 0;
		}
		else if (userFeedback === 1)
		{
			Feedback._previousContentFoundFeedback[elId] = 1;
		}
		else
		{
			Feedback._previousContentFoundFeedback[elId] = null;
		}
	},
	
	_setPreviousCommentText: function (family, item, userComment)
	{
		var elId = family+'-'+item;
		if (userComment === undefined || userComment === null || userComment.length < 1)
		{
			Feedback._previousComment[elId] = false;
		}
		else
		{
			Feedback._previousComment[elId] = userComment;
		}
	},
	
	_buildUrl: function(family, item, rating, comment, contentFound, report_typo, report_content_error, report_spam)
	{
		if (contentFound === undefined) {
			contentFound = null;
		}
		if (report_typo === undefined) {
			report_typo = null;
		}
		if (report_content_error === undefined) {
			report_content_error = null;
		}		
		if (report_spam === undefined) {
			report_spam = null;
		}
		
		var url = Path.toWebRoot() + 'ajax/feedback?action=save&family='+escape(family)+'&item='+escape(item);
		if (rating !== null)
		{
			url += '&rating='+escape(rating);
		}
		if (comment !== null)
		{
			url += '&comment='+escape(comment);
		}
		if (contentFound !== null)
		{
			url += '&contentFound='+escape(contentFound);
		}
		if (report_typo !== null)
		{
			url += '&report_typo='+escape(report_typo);
		}
		if (report_content_error !== null)
		{
			url += '&report_content_error='+escape(report_content_error);
		}
		if (report_spam !== null)
		{
			url += '&report_spam='+escape(report_spam);
		}
		
		return url;
	},
	
	_receiptOfRating: function(family, item)
	{
		var elId = family+'-'+item;
		
		if (Feedback._httpRequest.readyState != 4) {
			return;
		}
		
		var success = false;
		var text = "";
		
		if (Feedback._httpRequest.status == 200)
		{
			// A response of 0 indicates success. All other responses indicate
			// failure.
			if (Feedback._httpRequest.responseText == '0')
			{
				success = true;
				if (Feedback._ratings[elId] === 0)
				{
					text = "Rating Removed";
					Feedback._displayClearedAllFeedback(family, item, success);
				}
				else
				{
					text = "Rating Saved";
				}
			}
			else
			{
				text = "Error saving feedback (" + Feedback._httpRequest.responseText + ")";
			}
		}
		else
		{
			text = "Error saving feedback (" + Feedback._httpRequest.status + ") " + Feedback._httpRequest.responseText + "";
		}
		
		var statusEl = document.getElementById('inline-feedback-status-'+elId);
		if (statusEl) {
			while (statusEl.hasChildNodes())
			{
				statusEl.removeChild(statusEl.firstChild);
			}
			statusEl.appendChild(document.createTextNode(text));
			statusEl.className = "inline-feedback-status inline-feedback-status-" + (success ? "success" : "error");
		}
	},
	
	
	_receiptOfComment: function(family, item)
	{
		var elId = family+'-'+item;
		
		if (Feedback._httpRequest.readyState != 4) {
			return;
		}
		
		var success = false;
		var text = "";
		
		if (Feedback._httpRequest.status == 200)
		{
			// A response of 0 indicates success. All other responses indicate
			// failure.
			if (Feedback._httpRequest.responseText == '0')
			{
				success = true;
				text = "Feedback Saved";
			}
			else
			{
				text = "Error saving feedback (" + Feedback._httpRequest.responseText + ")";
			}
		}
		else
		{
			text = "Error saving feedback (" + Feedback._httpRequest.status + ") " + Feedback._httpRequest.responseText + "";
		}
		
		var statusEl = document.getElementById('inline-feedback-comment-status-'+elId);
		if (statusEl) {
			while (statusEl.hasChildNodes())
			{
				statusEl.removeChild(statusEl.firstChild);
			}
			statusEl.appendChild(document.createTextNode(text));
			statusEl.className = "inline-feedback-comment-status inline-feedback-comment-status-" + (success ? "success" : "error");
			statusEl.style.display = 'inline';
		}
	},
	
	_receiptOfContentFound: function(family, item)
	{
		var elId = family+'-'+item;
		if (Feedback._showContentFoundPrompt[elId] === true)
		{
			//double check to ensure that Radio Boxes and DIVs asking this question exist
			if (Feedback._httpRequest.readyState != 4) {
				return;
			}
			
			var success = false;
			var text = "";
			
			if (Feedback._httpRequest.status == 200)
			{
				// A response of 0 indicates success. All other responses indicate
				// failure.
				if (Feedback._httpRequest.responseText == '0')
				{
					success = true;
					text = "Feedback Saved";
				}
				else
				{
					text = "Error saving feedback (" + Feedback._httpRequest.responseText + ")";
				}
			}
			else
			{
				text = "Error saving feedback (" + Feedback._httpRequest.status + ") " + Feedback._httpRequest.responseText + "";
			}
			
			var statusEl = document.getElementById('inline-feedback-content-found-status-'+elId);
			if (statusEl)
			{
				while (statusEl.hasChildNodes())
				{
					statusEl.removeChild(statusEl.firstChild);
				}
				statusEl.appendChild(document.createTextNode(text));
				statusEl.className = "inline-feedback-content-found-status inline-feedback-content-found-status-" + (success ? "success" : "error");
				statusEl.style.display = 'inline';
			}
		}	
	},
	
	_displayClearedAllFeedback: function(family, item, success)
	{
		var elId = family+'-'+item;
		
		
		// Deal With Content Found Prompt & Input & Response (e.g., "Did you find the content you wanted?")
		if (Feedback._showContentFoundPrompt[elId] === true)
		{
		
			var statusEl = document.getElementById('inline-feedback-content-found-status-'+elId);
			var text = "Feedback Removed";
		
			if (statusEl)
			{
				if (statusEl.hasChildNodes())
				{
					while (statusEl.hasChildNodes())
					{
						statusEl.removeChild(statusEl.firstChild);
					}
					statusEl.appendChild(document.createTextNode(text));
					statusEl.className = "inline-feedback-comment-status inline-feedback-comment-status-" + (success ? "success" : "error");
					statusEl.style.display = 'inline';
				}
			}
			
			//clear check boxs after checking to make sure they exist
			if (document.getElementById('found-' + elId + 'no') !== null)
			{
				document.getElementById('found-' + elId + 'no').checked = false;
			}
			
			if (document.getElementById('found-' + elId + 'yes') !== null)
			{
				document.getElementById('found-' + elId + 'yes').checked = false;
			}
		}
			
		// Deal With Comment (i.e., TextArea) Box
		var statusE2 = document.getElementById('inline-feedback-comment-status-'+elId);
		text = "Comments Removed";
		if (statusE2)
		{
			if (statusE2.hasChildNodes())
			{
				while (statusE2.hasChildNodes())
				{
					statusEl.removeChild(statusE2.firstChild);
				}
				statusE2.appendChild(document.createTextNode(text));
				statusE2.className = "inline-feedback-comment-status inline-feedback-comment-status-" + (success ? "success" : "error");
				statusE2.style.display = 'inline';				
			}
		}
		document.getElementById('inline-feedback-comment-textarea-'+elId).value = "";
		
		
		// Deal With 5-Star Rating Option and Accompanying Text 
		var statusE3 = document.getElementById('inline-feedback-status-'+elId);
		text = "Rating Removed";
		if (statusE3)
		{
			if (statusE3.hasChildNodes())
			{	
				while (statusE3.hasChildNodes())
				{
					statusE3.removeChild(statusE3.firstChild);
				}
				statusE3.appendChild(document.createTextNode(text));
				statusE3.className = "inline-feedback-status inline-feedback-status-" + (success ? "success" : "error");
			}
		}
	}
};

var QuestionInteraction = {
	_pageLoadedTimestamp: null,
	_alreadySaved: [],
	
	pageLoaded: function()
	{
		if (QuestionInteraction._pageLoadedTimestamp === null)
		{
			QuestionInteraction._pageLoadedTimestamp = (new Date()).getTime();
		}
	},
	
	answerShown: function(question_type, question_id, page_generated_timestamp, selected_answer)
	{
		var time_offset = QuestionInteraction._computeTimeOffset();
		var params = {
			'question_type': question_type,
			'question_id': question_id,
			'timestamp': page_generated_timestamp,
			'time_to_answer': time_offset
			};
		if (typeof selected_answer !== "undefined" && selected_answer !== null)
		{
			params['selected_answer'] = selected_answer;
		}
		QuestionInteraction._saveInteraction(params);
	},
	
	explanationShown: function(question_type, question_id, page_generated_timestamp)
	{
		var time_offset = QuestionInteraction._computeTimeOffset();
		var params = {
			'question_type': question_type,
			'question_id': question_id,
			'timestamp': page_generated_timestamp,
			'time_to_explanation': time_offset
			};
		QuestionInteraction._saveInteraction(params);
	},
	
	hintShown: function(question_type, question_id, page_generated_timestamp)
	{
		var time_offset = QuestionInteraction._computeTimeOffset();
		var params = {
			'question_type': question_type,
			'question_id': question_id,
			'timestamp': page_generated_timestamp,
			'time_to_hint': time_offset
			};
		QuestionInteraction._saveInteraction(params);
	},
	
	_computeTimeOffset: function()
	{
		var currentTime = (new Date()).getTime();
		
		if (QuestionInteraction._pageLoadedTimestamp == null
				|| QuestionInteraction._pageLoadedTimestamp == 0
				|| QuestionInteraction._pageLoadedTimestamp > currentTime)
		{
			return 0;
		}
		else
		{
			return currentTime - QuestionInteraction._pageLoadedTimestamp;
		}
	},
	
	_saveInteraction: function(querystringParams)
	{
		if (QuestionInteraction._alreadySaved[QuestionInteraction._concatKeys(querystringParams)])
		{
			return;
		}
		
		var url = QuestionInteraction._buildUrl(querystringParams);
		
		var httpRequest = AJAX.createHttpRequest();
		if (httpRequest !== null)
		{
			httpRequest.onreadystatechange = function() {
					QuestionInteraction._markAsSaved(querystringParams, httpRequest);
				};
			httpRequest.open("GET", url);
			httpRequest.send(null);
		}
	},
	
	_markAsSaved: function(querystringParams, httpRequest)
	{
		if (httpRequest.readyState == 4 && httpRequest.status == 200)
		{
			QuestionInteraction._alreadySaved[QuestionInteraction._concatKeys(querystringParams)] = true;
		}
	},
	
	_concatKeys: function(map, delimiter)
	{
		var concat = '';
		
		for (var key in map)
		{
			concat += (concat.length == 0 ? '' : delimiter) + key;
		}
		
		return concat;
	},
	
	_buildUrl: function(querystringParams)
	{
		var url = '';
		
		for (var key in querystringParams)
		{
			url += (url.length == 0 ? '?' : '&') + key + '=' + escape(querystringParams[key]);
		}
		
		return Path.toWebRoot() + 'ajax/question_interaction' + url;
	}
};


var InlineQuestion = {

	_buttonText: new Array(),
	
	toggle: function(questionNum, section) {
		if (document.getElementById("inline-question-" + section + "-" + questionNum).style.display == "block") {
			InlineQuestion.setVisibility(questionNum, section, false);
		} else {
			InlineQuestion.setVisibility(questionNum, section, true);
		}
		InlineQuestion.updateButtonText(questionNum, section);
	},
	
	setVisibility: function(questionNum, section, visible) {
		document.getElementById("inline-question-" + section + "-" + questionNum).style.display = (visible ? "block" : "none");
		document.getElementById("inline-question-" + section + "-button-link-" + questionNum).className = (visible ? "collapsable" : "expandable");
		if (section == 'answer') {
			// Special case when toggling answer visibility
			InlineQuestion.setAnswerVisibility(questionNum, visible);
		}
	},
	
	updateButtonText: function(questionNum, section) {
		if (typeof InlineQuestion._buttonText[questionNum][section] != 'undefined') {
			var displayValue = document.getElementById("inline-question-" + section + "-" + questionNum).style.display;
			document.getElementById("inline-question-" + section + "-button-link-" + questionNum).innerHTML = InlineQuestion._buttonText[questionNum][section][displayValue];
		}
	},
	
	registerButtonText: function(questionNum, section, makeVisibleText, makeHiddenText) {
		if (typeof InlineQuestion._buttonText[questionNum] == 'undefined') {
			InlineQuestion._buttonText[questionNum] = new Array();
			if (typeof Preload != 'undefined' && typeof Preload.preloadImages != 'undefined') {
				// TODO Left off here... preload expand.png and other images
				Preload.preloadImages(
					Path.toWebRoot() + 'global/images/icons/collapse.png?20081226',
					Path.toWebRoot() + 'global/images/icons/expand.png?20081226'
				);
			}
		}
		if (typeof InlineQuestion._buttonText[questionNum][section] == 'undefined')
			InlineQuestion._buttonText[questionNum][section] = new Array();
		InlineQuestion._buttonText[questionNum][section]["none"] = makeVisibleText;
		InlineQuestion._buttonText[questionNum][section]["block"] = makeHiddenText;
	},
	
	setAnswerVisibility: function(questionNum, visible) {
		var correctEl = document.getElementById("inline-question-correct-answer-" + questionNum);
		if (correctEl) {
			if (visible) {
				correctEl.className = 'inline-question-answer inline-question-correct-answer';
			} else {
				correctEl.className = 'inline-question-answer';
			}
		}
	}
}
