/*
	Javascript code written by PSLWeb.co.uk for Stamford Renewables Limited (www.stamfordrenewables.com)
	Copyright ©2008 PSLWeb.co.uk - All Rights Reserved.
*/
/*
	Globals
*/
var FFVDataTypes = new Array(); // Regex patterns for the defined datatypes
FFVDataTypes['PrintNL'] = "^[\\x20-\\x7E\\r\\n\\xA3]+$";
FFVDataTypes['Print'] = "^[\\x20-\\x7E\\xa3]+$";
FFVDataTypes['PrintNLAll'] = "^[\\x20-\\xFF\\r\\n\\xA3]+$";
FFVDataTypes['PrintAll'] = "^[\\x20-\\xFF\\xa3]+$";
FFVDataTypes['Hex'] = "^[A-Fa-f0-9]+$";
FFVDataTypes['Digits'] = "^[\\d]+$";
FFVDataTypes['Real'] = "^[\\+-]?[\\d]*[\\.]?[\\d]+$";
FFVDataTypes['Decimal'] = "^[\\d]*[\\.]?[\\d]+$";
FFVDataTypes['Email'] = "^([\\w-]+)(\\.[\\w-]+)*@([A-Za-z0-9-]+)(\\.[A-Za-z0-9-]+)*(\\.[a-z]{2,4})$";
FFVDataTypes['Alpha'] = "^[A-Za-z]+$";
FFVDataTypes['Alnum'] = "^[A-Za-z0-9]+$";
FFVDataTypes['DBDate'] = "^[\\d]{4}\\-[\\d]{2}\\-[\\d]{2}$";
FFVDataTypes['Pwd'] = "^[A-Za-z0-9]*[\\d][A-Za-z0-9]*$";
FFVDataTypes['URL'] = "^(([\\w]+:)?\\/\\/)?(([\\d\\w]|%[a-fA-f\\d]{2,2})+(:([\\d\\w]|%[a-fA-f\\d]{2,2})+)?@)?([\\d\\w][-\\d\\w]{0,253}[\\d\\w]\\.)+[\\w]{2,4}(:[\\d]+)?(\\/([-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})*)*(\\?(&?([-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})=?)*)?(#([-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})*)?$";
FFVDataTypes['Telephone'] = "^[\\d-\\(\\)\\+\\x20\\.]+$";
FFVDataTypes['Postcode'] = "^[A-Za-z0-9]{2,4}(\\x20)?\\d[A-Za-z0-9]{2}$";
FFVDataTypes['Name'] = "^[A-Za-z-\\'\\x20]+$";
FFVDataTypes['AddrLines'] = "^[A-Za-z0-9-\\x20\\.\\,\\'\\(\\)\\/]+$";
FFVDataTypes['AddrCCC'] = "^[A-Za-z0-9-\\x20\\.\\(\\)]+$";
FFVDataTypes[''] = ""; // Default case
// User defined Datatypes here
//FFVDataTypes[''] = ""; // User defined Datatype
FFVDataTypes['Digits19'] = "^[1-9]{1}$"; // Digits 1-9
// End User defined Datatypes

var FFVFormID = ''; // Declare global
var FFVCancelForce = false; // Assume we'll validate form on submission
var FFVCancelConfirm = false; // Assume we'll validate form on submission
var FFVDeleteConfirm = false; // Assume we'll validate form on submission
var FFVPathPrefix = generatePathToRoot(); // Generate prefix path to the image directory
var FFVPwdMinLen = 7; // Minimum length for Password fields

/*
	Function:    generatePathToRoot
	Called From: Global Scope (see above)
	Inputs:		 None
	Output:		 Returns: String - prefix file path to get back to the root directory (e.g. '../../')
	Description: Generates a path prefix to ensure portability between dev and live
*/
function generatePathToRoot() {
	var count = 0;
	var pathPrefix = "";
	var location = window.location.toString();
	// Count up number of occurences of the '/' char
	var i = location.indexOf('/');
	while (i != -1) {
	   count++;
	   i = location.indexOf('/', i + 1);
	}
	var regex = new RegExp("^http\\:\\/\\/localhost"); // Dev environment?
	count = (regex.test(location)) ? count - 4 : count - 3;
	// Build string of '../' to get back to the document root
	for (i = 0; i < count; i++)
		pathPrefix = pathPrefix + '../';
	return pathPrefix;
};

/*
	Function:    setFieldError
	Called From: Ad hoc
	Inputs:		 field: Object - a Form Field Object (e.g. 'input' element)
				 altText: String - the text for the error image ALT tag
	Output:		 none
	Description: Set a form field's error image and highlights the label in red.
*/
function setFieldError(field, altText) {
	labelObj = document.getElementById(field.id + 'Label');
	if (labelObj) {
		classNameSeparate = (labelObj.className != '') ? ' ' : '';
		labelObj.className += classNameSeparate + 'error'; // Set Class to 'error'
	}
	var imgObj = document.getElementById(field.id + 'Img');
	if (imgObj) { 
		imgObj.src = FFVPathPrefix + "images/misc/field0.gif";
		imgObj.alt = altText;
	}
}

/*
	Function:    checkFormField
	Called From: checkAllFormFields and from Form Field 'onkeyup' events
	Inputs:		 field: String - a Form Field Object (e.g. 'input' element)
	Output:		 Returns: Bool - TRUE if field is in error, FALSE if field is OK
	Description: Checks a form field to see if required data is input and if that input is in the
					correct format. It set the appropriate form field image (red cross or green tick)
					and changes that image's ALT tag. It returns TRUE if the field is in error or
					FALSE is the field is ok.
*/
function checkFormField(field) {
	var imgObj = document.getElementById(field.id + 'Img');
	if (!(imgObj)) // If imgObj not defined create an empty object
		//alert('FFV WARNING: No corresponding Image for field: "' + field.id + '"');
		imgObj = new Image(); // Assign dummy image object
	// If field is a textarea AND there is a TinyMCE object shadowing it
	if ((field.type == 'textarea') && document.getElementById(field.id + '_ifr')) {
		tinyMCE.execCommand('mceFocus', false, field.id); // Give focus to the field
		tinyMCE.triggerSave(); // Save the content back to the textarea
	}
	var classNames = new Array();
	classNames = field.className.split(' '); // Split into separate Class Names
	var idfr;
	var regexClass = new RegExp("^FFV[01]{1}"); // Pattern to identify Class Name beginning 'FFV[0|1]'
	var fieldType = ""; // Set default
	var fieldRequired = false; // Set default
	var NumOfClasses = classNames.length;
	for (var i = 0; i  < NumOfClasses; i++) // Examine each Class Name (if any)
		if (regexClass.test(classNames[i].substr(0, 4))) { // Found a FFV Class Name?
			fieldRequired = (classNames[i].substr(3, 1) == '1'); // Test Flag in Class Name
			fieldType = classNames[i].substr(4); // Extract Datatype from Class Name
		}
	var fieldData = field.value;
	if (fieldData == "") // If data is empty
		if (fieldRequired) { // If this field is required
			imgObj.src = FFVPathPrefix + "images/misc/field0.gif";
			imgObj.alt = "Data is required for this field";
			return true;
		}
		else { // This is not a required field
			imgObj.src = FFVPathPrefix + "images/misc/fieldnull.gif";
			imgObj.alt = "";
			return false;
		}
	else { // Data is not empty
		var pattern = FFVDataTypes[fieldType]; // Get Regex pattern for this datatype
		var regex = new RegExp(pattern);
		if (regex.test(fieldData)) { // Is this data in a valid format (based on its datatype)?
			// Build the name of a (optional) field-specific function for additional validation
			var extValFunName = field.id + 'FFVExtVal';
			if (window[extValFunName]) // Does this function exist?
				extValValid = window[extValFunName](fieldData); // Execute the additonal validation
			else
				extValValid = true; // If no additional validation then validation is OK
			// If valid so far AND field is type Pwd and data length too short then flag as invalid
			if ((extValValid) && (fieldType == 'Pwd') && (fieldData.length < FFVPwdMinLen))
				extValValid = false;
			if (extValValid) { // All validation has been passed
				imgObj.src = FFVPathPrefix + "images/misc/field1.gif";
				imgObj.alt = "Data is in the correct format";
				labelObj = document.getElementById(field.id + 'Label');
				labelObj.className = null; // Remove field's Label Class (clear any 'error')
				return false;
			}
			else { // Data is not in a valid format
				imgObj.src = FFVPathPrefix + "images/misc/field0.gif";
				imgObj.alt = "Data is not in the correct format for this field";
				return true;
			}
		}
		else { // Data is not in a valid format
			imgObj.src = FFVPathPrefix + "images/misc/field0.gif";
			imgObj.alt = "Data is not in the correct format for this field";
			return true;
		}
	}
};

/*
	Function:    checkAllFormFields
	Called From: init and validate
	Inputs:		 hilite: Bool - TRUE if we want to hilight errors (color the 'Label', set focus and
					change the Field Image) or FALSE if we only want to set the field image.
	Output:		 Returns: Bool - TRUE if at least one field is in error, FALSE if all fields are OK
	Description: Checks an entire form to examine all input and textarea fields for errors. It sets
					the Field Image (red cross or green tick) in all events and, if the input is TRUE,
					sets the Field Label class to 'error' and sets the focus to the topmost field
					that is in error.
*/
function checkAllFormFields(hilite) {
	var thisForm = document.getElementById(FFVFormID);
	var errors = false; // Assume no errors are found
	var labelObj, classNameSeparate;
	for (var i = thisForm.length - 1; i >= 0; i--) { // Reverse order so we hilight the top-most error
		field = thisForm[i];
		if ((field.type == 'text') || (field.type == 'textarea') || (field.type == 'password')) {
			if (checkFormField(field)) { // Is this field in error?
				errors = true; // Found at least one error
				if (hilite) { // Hilight this field?
					// If field is a textarea AND there is a TinyMCE object shadowing it
					if ((field.type == 'textarea') && document.getElementById(field.id + '_ifr'))
						tinyMCE.execCommand('mceFocus', false, field.id);
					else
						field.focus();
					labelObj = document.getElementById(field.id + 'Label');
					if (!(labelObj)) // If imgObj not defined create an empty object
						alert('FFV WARNING: No corresponding Label for field: "' + field.id + '"');
					else {
						classNameSeparate = (labelObj.className != '') ? ' ' : '';
						labelObj.className += classNameSeparate + 'error'; // Set Class to 'error'
					}
				}
			}
		}
	}
	return errors;
};

/*
	Function:    init
	Called From: onload event on the Body element
	Inputs:		 formID: String - the name of the form (its ID) that we want to process
				 fieldID: String - the name of the field (its ID) that we want to have the focus
				 inError: Bool - if TRUE then this field's Label will be highlighted, if FALSE then
				 	it won't be highlighted
	Output:		 None
	Description: Initialises. It sets the global Form ID and sets the initial field focus.
*/
function init(formID, fieldID, inError) {
	FFVFormID = formID; // Set global to inputted Form Identifier (Form ID)
	if (window['initExtraPre']) // Any User defined extra Pre-initialisation?
		window['initExtraPre'](); // Execute the additonal Pre-initialisation
	checkAllFormFields(false); // Initialise all field validation images
	var fieldObj = document.getElementById(fieldID);
	if (fieldObj) { // Object exists?
		fieldObj.focus(); // If so set focus here
		if (inError) { // Is this field in Error? Is so highlight the Label
			labelObj = document.getElementById(fieldObj.id + 'Label');
			var classNameSeparate = (labelObj.className != '') ? ' ' : '';
			labelObj.className += classNameSeparate + 'error'; // Set Class to 'error'
			labelObj.className = 'error'; // Set field's Label Class to 'error'
		}
	}
	if (window['initExtraPost']) // Any User defined extra post-initialisation?
		window['initExtraPost'](); // Execute the additonal post-initialisation
};

/*
	Function:    validate
	Called From: onsubmit event of the Form element
	Inputs:		 None
	Output:		 Returns: Bool - TRUE is the form is to be submitted (no errors or validation to
					be skipped)
	Description: Validates the form fields (unless skipped, e.g. Cancel button or Delete button pressed)
					and submits the form if OK or returns (with a pop-up error message window) otherwise.
*/
function validate() {
	//return true; // TESTING - bypass validation
	if (FFVCancelForce) // Cancel without confirmation?
		return true;
	else if (FFVCancelConfirm) { // Cancel button was pressed, ask user for confirmation
		FFVCancelConfirm = false; // Reset flag
		return confirm("Please confirm CANCEL (form data will be lost)");
	}
	else if (FFVDeleteConfirm) { // Delete button was pressed, ask user for confirmation
		FFVDeleteConfirm = false; // Reset flag
		return confirm("WARNING: Please confirm DELETE (this cannot be undone)");
	}
	else if (checkAllFormFields(true)) { // If there is at least one error
		alert("Please correct form fields that are in error");
		return false; // Don't submit form
	}
	else if (window['validateExtra']) // Any User defined extra validation?
		return window['validateExtra'](); // Execute the additonal validation
	return true; // No errors so submit form
};

/*
	Function:    rteHandleEvent
	Called From: Rich Text Editor (TinyMCE) on event handler
	Inputs:		 e: Object - an event object
	Output:		 None. Updates validation image based as a side-effect
	Description: Validates a TinyMCE textare onkeyup event, checks if there is content in the textarea
					and alters the image accordingly.
*/
function rteHandleEvent(e) {
	if (e.type == 'keyup') { // Is this an onkeyup event?
		var field = tinyMCE.activeEditor.id; // Get the ID of the textarea for which this event relates
		var imgObj = document.getElementById(field + 'Img');
		if (!(imgObj)) // If imgObj not defined create an empty object
			alert('FFV WARNING: No corresponding Image for field: "' + field.id + '"');
		if (tinyMCE.get(field).getContent().length > 0) { // Is there content here?
			imgObj.src = FFVPathPrefix + "images/misc/field1.gif";
			imgObj.alt = "Data required is present";
			labelObj = document.getElementById(field + 'Label');
			labelObj.className = null; // Remove field's Label Class (clear any 'error')
		}
		else {
			imgObj.src = FFVPathPrefix + "images/misc/field0.gif";
			imgObj.alt = "Data is required for this field";
		}
	}
};

/*
	Function:    confirmReset
	Called From: onclick event of the Reset Button
	Inputs:		 None
	Output:		 None
	Description: Asks the user to confirm the Reset action and, if confirmed, invokes the Reset method
					on the Form object thereby resetting the form fields.
*/
function confirmReset() {
	if (confirm("Please confirm RESET of all form field data to their starting values")) {
		var thisForm = document.getElementById(FFVFormID);
		thisForm.reset(); // Reset form fields
		checkAllFormFields(false); // Initialise all field validation images
	}
};

/*
	Function:    updateCounter
	Called From: onkeyup event of a textarea element
	Inputs:		 field: Object - the form element initiating this event
				 maxSize: Integer - the maximum number of chars in the elements (value) attribute
	Output:		 None
	Description: Keeps a running total of chars in the elements (value) attribute and write this out
					to a specified paragraph. Truncates the elements value attribute if the maximum
					permitted size is exceeded.
*/
function updateCounter(field, maxSize) {
	var counter = document.getElementById(field.id + 'Counter'); // The paragraph containing the count
	if (counter) { // Is this a valid object?
		var charCount = field.value.length; // Number of characters in the field (value)
		if (charCount > maxSize) { // Have we exceeded the maximum permitted size?
			field.value = field.value.substr(0, maxSize); // If so truncate the field (value)
			charCount = maxSize;
		}
		var newText = 'Characters remaining = ' + (maxSize - charCount);
		counter.childNodes[0].nodeValue = newText; // Set Text in the paragraph
	}
	else
		alert('FFV WARNING: No corresponding Counter for field: "' + field.id + '"');
};

/*
	Function:    showHelp
	Called From: onmouseover event on help icon images
	Inputs:		 element: Image Object - the help icon image which triggered this event 
	Output:		 None
	Description: Displays a pop-up CSS box next to the help icon image which contains the help text.
*/
function showHelp(element) {
	if (!(popupBoxActive)) { // Don't show Help if it's already active
		var popupBox = document.getElementById('popupBox');
		var id = element.id; // ID of the help icon - used to derive the Help Text ID
		var helpTextId = id.substr(0, id.length - 7) + 'HelpText'; // Build ID of help text
		var helpText = document.getElementById(helpTextId).innerHTML;
		var x = 0;
		var y = 0;
		while((element) && (element.id != 'page')) {
			//alert(element.id);
			x += element.offsetLeft;
			y += element.offsetTop;
			element = element.offsetParent;
		}
		x += 20;
		if (x >= 600) // If no room to show the Summary to the right of the image...
			x -= 204; // Show it to the left instead
		popupBox.style.left = x + 'px';
		popupBox.style.top = y + 'px';
		popupBox.innerHTML = helpText;
		popupBoxActive = true; // Set the Summary layer flag as active
		popupBox.style.visibility = "visible";
	}
};

/*
	Function:    hideSummary
	Called From: onmouseout event on icon images in projects.php
	Inputs:		 None
	Output:		 None
	Description: Hides a pop-up CSS box that has previously been displayed.
*/
function hideHelp() {
	popupBoxActive = false; // Reset the Summary Popup layer flag (i.e. hide any Summary layer)
	document.getElementById('popupBox').style.visibility = "hidden";
};

/********* Additional Validation Functions Here ************

Function Name format: <field name>FFVExtVal
Input (fieldData) the value of the field
Return: Bool - TRUE if valid, FALSE is NOT valid

NB: functions are determined and called automatically, no need to change above functions */

/*
	Function:    sortOrderFFVExtVal
	Called From: checkFormField
	Inputs:		 fieldData: String - the data in the sortOrder form field
	Output:		 Returns: Bool - TRUE if the additional validation is OK, False otherwise
	Description: Peforms additional validation, checking that the field contains values 1-9 (i.e. not 0).

Example:

function sortOrderFFVExtVal(fieldData) {
	var regex = new RegExp("^[1-9]{1}$");
	return regex.test(fieldData);
};*/