//
// Copyright (C) 2010 Tod Fitch
// All rights reserved.
//

/**
 *	For popup help boxes, specify the offset from the cursor for the window
 *	to appear.
 */
var xOffset = -200;
var yOffset = +10;
var displayDivTop = 150;
var displayDivLeft = 200;


// initialize hacks whenever the page loads
window.onload = initializeHacks;
// setup an event handler to hide popups for generic clicks on the document
document.onclick = hideCurrentPopup;

/**
 *	@brief Get element by ID
 *
 *	@par Description
 *	Based on several published and open source examples, return
 *	object for several versions of browsers.
 *
 *	@param[in] objectId ID of element to find
 *	@return object if successful, false otherwise
 */
function getObject(objectId)
{
	// W3C compliant
	if (document.getElementById &&
		document.getElementById(objectId))
	{
		return document.getElementById(objectId);
	}
	// Old MS IE
	else if (document.all && document.all(objectId))
	{
		return document.all(objectId);
	}
	// Old Netscape
	else if (document.layers && document.layers[objectId])
	{
		return document.layers[objectId];
	}
	else
	{
	   return false;
	}
}

/**
 *	@brief Get element style by object ID
 *
 *	@par Description
 *	Based on several published and open source examples, return
 *	style object for element for several versions of browsers.
 *
 *	@param[in] objectId ID of element to get style for
 *	@return object if successful, false otherwise
 */
function getStyleObject(objectId)
{
	// W3C compliant
	if (document.getElementById &&
		document.getElementById(objectId))
	{
		return document.getElementById(objectId).style;
	}
	// Old MS IE
	else if (document.all && document.all(objectId))
	{
		return document.all(objectId).style;
	}
	// Old Netscape
	else if (document.layers && document.layers[objectId])
	{
		return document.layers[objectId];
	}
	else
	{
	   return false;
	}
}

function listPropertyNames(obj)
{
	var names = "";
	for (var i in obj) names += i + ", ";
	alert(names);
}
/**
 *	Set a value into an object (typically an input field).
 *
 *	If this is the first time a set is performed then save
 *	the original value so that a resetValue() call can
 *	return it to the original value.
 */
function setValue(objectId, newValue)
{
	var obj = getObject(objectId);
	if (obj) {
		obj.value = newValue;
	}
}

/**
 *	Reset the value attribute on an object to that
 *	originally detected during the first setValue()
 *	call.
 */
function resetValue(objectId)
{
	var obj = getObject(objectId);
	if (obj) {
			obj.value = obj.defaultValue;
	}
}

/**
 *	@brief Change visibility attribute of an object
 *
 *	@param[in]	objectId		Object to work magic on
 *	@param[in]	newVisibility	New setting for visibility
 *	@return true if successful.
 */
function changeVisibility(objectId, newVisibility)
{
	var styleObject = getStyleObject(objectId);
	if(styleObject)
	{
		styleObject.visibility = newVisibility;
		return true;
	}
	else
	{
		return false;
	}
}

/**
 *	@brief Change enable attribute of an object
 *
 *	@param[in]	objectId		Object to work magic on
 *	@param[in]	newDisable		New setting for disable control
 *	@return true if successful.
 */
function changeDisable(objectId, newDisable)
{
	var ctlObject = getObject(objectId);
	if(ctlObject) {
		ctlObject.disabled = newDisable;
		return true;
	} else {
		return false;
	}
}

/**
 *	Move an object to a new location in the browser window
 *
 *	@param[in]	objectId	Unique identifier for object
 *	@param[in]	newX		New horizontal location
 *	@param[in]	newY		New vertical location
 *	@return true if successful otherwise false
 */
function moveObject(objectId, newX, newY) {
	var styleObject = getStyleObject(objectId);
	if(styleObject)
	{
		styleObject.left = newX + 'px';
		styleObject.top = newY + 'px';
		return true;
	}
	else
	{
		return false;
	}
} // moveObject

function showPopup(targetObjectId, eventObj)
{
	if(eventObj)
	{
		hideCurrentPopup();
		eventObj.cancelBubble = true;

		var newX = (eventObj.pageX)?
			(eventObj.pageX + xOffset):
			(eventObj.x + xOffset + ((document.body.scrollLeft)?document.body.scrollLeft:0));
		var newY = (eventObj.pageY)?
			(eventObj.pageY + yOffset):
			(eventObj.y + yOffset + ((document.body.scrollTop)?document.body.scrollTop:0));
		newX = newX - displayDivLeft;	  // Adjust for location of left edge of display DIV
		if (newX < 0) {
			newX = 0;
		}
		newY = newY - displayDivTop;	  // Adjust for location of top edge of display DIV
		moveObject(targetObjectId, newX, newY);
		// and make it visible
		if( changeVisibility(targetObjectId, 'visible') )
		{
			window.currentlyVisiblePopup = targetObjectId;
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}

function hideCurrentPopup()
{
	// note: we've stored the currently-visible popup on the global object window.currentlyVisiblePopup
	if(window.currentlyVisiblePopup)
	{
		changeVisibility(window.currentlyVisiblePopup, 'hidden');
		window.currentlyVisiblePopup = false;
	}
}

function initializeHacks() {
	// this ugly little hack resizes a blank div to make sure you can click
	// anywhere in the window for Mac MSIE 5
	if ((navigator.appVersion.indexOf('MSIE 5') != -1)
	&& (navigator.platform.indexOf('Mac') != -1)
	&& getStyleObject('blankDiv')) {
	window.onresize = explorerMacResizeFix;
	}
	resizeBlankDiv();
	// this next function creates a placeholder object for older browsers
	createFakeEventObj();
}

function createFakeEventObj() {
	// create a fake event object for older browsers to avoid errors in function call
	// when we need to pass the event object to functions
	if (!window.event) {
	window.event = false;
	}
} // createFakeEventObj

function resizeBlankDiv() {
	// resize blank placeholder div so IE 5 on mac will get all clicks in window
	if ((navigator.appVersion.indexOf('MSIE 5') != -1)
	&& (navigator.platform.indexOf('Mac') != -1)
	&& getStyleObject('blankDiv')) {
	getStyleObject('blankDiv').width = document.body.clientWidth - 20;
	getStyleObject('blankDiv').height = document.body.clientHeight - 20;
	}
}

function explorerMacResizeFix () {
	location.reload(false);
}

/**
 *	@brief Finish Field Validation
 *
 *	@par Description
 *	Finishes off the field validation. If the error message
 *	is blank then the validated value is placed back in the field
 *	value. Otherwise the error message is output and focus is
 *	placed back on the offending field.
 *
 *	@param[out] objId	The ID of the field being validated
 *	@parma[in]	msg		The Error message
 *	@param[in]	val		The validated value
 */
function fieldFin(objId, msg, val)
{
	var valObj = getObject(objId);
	if (valObj)
	{
		var errId = errorLoc[objId];
		var errObj = getObject(errId);
		if (errObj)
		{
			if (msg != "")
			{
				errObj.innerHTML = msg;
				changeVisibility(errId, 'visible');
				valObj.style.backgroundColor = "#FF6666";
//				valObj.focus();
			}
			else
			{
				changeVisibility(errId, 'hidden');
				errObj.innerHTML = "&nbsp;"
				valObj.style.backgroundColor = "white";
				valObj.value = val;
			}
		}
	}
	return (msg == "");
}

function checkNumField(fieldId,minValue,maxValue)
{
	var msg = "";
	var valObj = getObject(fieldId);
	if (valObj)
	{
		val = valObj.value;
		val = val.replace(/^ +/gi, "");		// Remove leading spaces
		val = val.replace(/ +$/gi, "");		// Remove trailing spaces
		if ((val.match(/ /gi) != null) ||
			(val.match(/,/gi) != null))
		{
			msg = "Spaces and commas are not allowed";
		}
		if (val.length == 0)
		{
			msg = "Value cannot be blank"
		}
		var num = val - 0;
		if ((msg == "") &&
			(num.toString() != val)) {
			msg = "Not a valid number";
		}
		if ((msg == "") && (minValue == 0) && (maxValue == 0))	{
			return fieldFin(fieldId, msg, val);
		}
		if ((msg == "") &&
			((num < minValue) || (num > maxValue))) {
			msg = "Must be in range " + minValue + ".." + maxValue;
		}

		return fieldFin(fieldId, msg, val);
	}
	return false;
}

/** @brief Validate a text entry field
 *
 *	@par Description
 *	Verifies that the text entered in the text input field
 *	consists of a single non-empty token. It will remove leading and
 *	trailing spaces to normalize it. If any error is detected
 *	an error message will be placed in the innerHTML of the HTML
 *	element specified by msgId.
 *
 *	@param[in]	fieldId		ID of field to perform a validity
 *							check on.
 *	@param[in]	eventObj	The event that caused this function to
 *							be run.
 */
function checkTextField(fieldId, maxLen)
{
	var msg = "";
	var valObj = getObject(fieldId);
	if (valObj)
	{
		val = valObj.value;
		val = val.replace(/^ +/gi, "");		// Remove leading spaces
		val = val.replace(/ +$/gi, "");		// Remove trailing spaces
		if (val.length > maxLen) {
 			msg = "Too long...maximum length is " + maxLen;
 		}
// 		if ((val.match(/ /gi) != null) ||
// 			(val.match(/,/gi) != null)) {
// 			msg = "Spaces and commas are not allowed";
// 		} else if (val.length == 0) {
// 			msg = "Value cannot be blank"
// 		}
		return fieldFin(fieldId, msg, val);
	}
	return false;
}

function checkNonBlankTextField(fieldId, maxLen)
{
	var msg = "";
	var valObj = getObject(fieldId);
	if (valObj)
	{
		val = valObj.value;
		val = val.replace(/^ +/gi, "");		// Remove leading spaces
		val = val.replace(/ +$/gi, "");		// Remove trailing spaces
		if (val.length > maxLen) {
 			msg = "Too long...maximum length is " + maxLen;
 		} else if (val.length == 0) {
 			msg = "Value cannot be blank";
 		}
// 		if ((val.match(/ /gi) != null) ||
// 			(val.match(/,/gi) != null)) {
// 			msg = "Spaces and commas are not allowed";
// 		} else if (val.length == 0) {
// 			msg = "Value cannot be blank"
// 		} else if (val.length > maxLen) {
// 			msg = "Too long...maximum length is " + maxLen;
// 		}
		return fieldFin(fieldId, msg, val);
	}
	return false;
}

/** @brief Validate a text entry field that can be empty
 *
 *	@par Description
 *	Verifies that the text entered in the text input field
 *	consists of a single non-empty token. It will remove leading and
 *	trailing spaces to normalize it. If any error is detected
 *	an error message will be placed in the innerHTML of the HTML
 *	element specified by msgId.
 *
 *	@param[in]	fieldId		ID of field to perform a validity
 *							check on.
 *	@param[in]	eventObj	The event that caused this function to
 *							be run.
 */
function checkTextBlankField(fieldId, maxLen)
{
	var msg = "";
	var valObj = getObject(fieldId);
	if (valObj)
	{
		val = valObj.value;
		val = val.replace(/^ +/gi, "");		// Remove leading spaces
		val = val.replace(/ +$/gi, "");		// Remove trailing spaces
		if ((val.match(/ /gi) != null) ||
			(val.match(/,/gi) != null))
		{
			msg = "Spaces and commas are not allowed";
		}
		else if (val.length > maxLen) {
			msg = "Too long...maximum length is " + maxLen;
		}
		return fieldFin(fieldId, msg, val);
	}
	return false;
}

/**
 *	@brief Validate a text list entry field
 *
 *	@par Description
 *	Verifies that the text entered in the text input field
 *	consists of a at least non-empty token. It will remove leading and
 *	trailing spaces and it will replace runs of commas and spaces with a
 *	single space to normalize it. If any error is detected an error
 *	message will be placed in the innerHTML of the HTML element
 *	specified by msgId.
 *
 *	@param[in]	fieldId		ID of field to perform a validity
 *							check on.
 *	@param[in]	eventObj	The event that caused this function to
 *							be run.
 */
function checkTextListField(fieldId, maxLen)
{
	var msg = "";
	var valObj = getObject(fieldId);
	if (valObj)
	{
		val = valObj.value;
		val = val.replace(/[, ]+/gi, " ");// Make into canonical form
		val = val.replace(/^ +/gi, "");		// Remove leading spaces
		val = val.replace(/ +$/gi, "");		// Remove trailing spaces
		if (val.length == 0) {
			msg = "Value cannot be blank"
		} else if (val.length > maxLen) {
			msg = "Too long...maximum length is " + maxLen;
		}
		return fieldFin(fieldId, msg, val);
	}
	return false;
}


/**
 *	@brief Copy help text from into help display DIV
 *
 *	@param[in]	helpId		ID for hidden DIV that contains help
 *							text to be copied into help DIV.
 *	@param[in]	fieldId		ID for field that help is for. The
 *							help DIV will be moved vertically
 *							to match the location of the entry
 *							field.
 */
function set_help(helpId, fieldId)
{
	var helpDivObj = getObject('help');
	var helpSrcObj = getObject(helpId);
	if (helpDivObj && helpSrcObj)
	{
		helpDivObj.innerHTML = helpSrcObj.innerHTML;
	}
}


var numbers = '0123456789';
var lowercase = 'abcdefghijklmnopqrstuvwxyz';
var uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var windomain = '!@#$%^&()-_\'{}~';

function isValidChar(param, validchars)
{
	if (param == "")
		return false;
	for (i = 0; i < param.length; i += 1)  {
		if (validchars.indexOf(param.charAt(i), 0) == -1)
			return false;
	}
	return true;
}

function hasInvalidChar(param, invalidchars)
{
	if (param == "")
		return false;
	for (i = 0; i < param.length; i += 1)  {
		if (invalidchars.indexOf(param.charAt(i), 0) != -1)
			return true;
	}
	return false;
}

function isNumber(param) { return isValidChar(param, numbers); }
function isLower(param) { return isValidChar(param, lowercase); }
function isUpper(param) { return isValidChar(param, uppercase); };
function isAlpha(param) { return isValidChar(param, lowercase + uppercase); }
function isAlphanum(param) { return isValidChar(param, lowercase + uppercase + numbers); }

