// Suffixes used in ins_javascript_formcheck.cfm
// '_validURL'		used to define fields used for URLS
// '_validDate' 	used to define fields used for dates.
// '_validEmail' 	used to define fields used for email addresses.
// '_required'  	used to check if  required fields are filled.
// '_number'		used to check if the field is numeric
// '_validTime24'		use to check valid 24 hour time
// '_validTime12'		used to check valid 12 hour time
// '_validDatetime24'		used to check valid date 24 time
// '_validDatetime12'		used to check valid date 12 time

/*

You can supply a function that fires when the form field validator focuses on the first 
invalid field the function must be added to functionDefArray with the key 'onFieldFocus'.

*/

// strAlert is updated if an invalid field is found.	
var strAlert = '';

// Regular Expression Patterns
// URL:  /https?:\/\/.+/i
// File Path:  /^[a-z]:\\([^\\]+\\)*[^\.]+\.([a-z]|[0-9])+$/i
// Email:  /^[\w'']+([\.-]?[\w'']+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/
var regexPatternArray = new Array();
regexPatternArray [ "url" ] = "^(ftp|https?)://.+";
regexPatternArray [ "filepath" ] = "^([a-z]:\\\\|\\\\\\\\)([^\\\\]+\\\\)*[^\\\\]+$";
regexPatternArray [ "email" ] = "^[\\w']+([\\.-]?[\\w']+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,4})+$";



// Function Arrays
var preCheckFunctionDefArray = new Array();
var postCheckFunctionDefArray = new Array();
var functionDefArray = new Array();
functionDefArray [ "_isNumeric" ] = ibc_isNumeric;
functionDefArray [ "_number" ] = ibc_isNumeric;
functionDefArray [ "_required" ] = ibc_required;
functionDefArray [ "_validDate" ] = ibc_validDate;
functionDefArray [ "_validEmail" ] = regexPatternArray [ "email" ];
functionDefArray [ "_validURL" ] = regexPatternArray [ "url" ];
functionDefArray [ "_filePath" ] = regexPatternArray [ "filepath" ];

// Function to add custom functions or regex strings to the functionDefArray.
function AssignCustomCheck ( checkFunctionSuffix, checkFunction )
{
	functionDefArray [ checkFunctionSuffix ] = checkFunction;
}

// Function to add functions to preCheckFunctionDefArray.
// functions added to this array will be run before the main checkForm proccesses.
function AssignPreCheckFunction ( formID, checkFunction )
{
	if ( ! preCheckFunctionDefArray [ formID ] )
		preCheckFunctionDefArray [ formID ] = new Array();
		
	preCheckFunctionDefArray [ formID ] [ preCheckFunctionDefArray [ formID ].length ] = checkFunction;
}

// Function to add functions to postCheckFunctionDefArray.
// functions added to this array will be run after the main checkForm proccesses.
function AssignPostCheckFunction ( formID, checkFunction )
{
	if ( ! postCheckFunctionDefArray [ formID ] )
		postCheckFunctionDefArray [ formID ] = new Array();
	postCheckFunctionDefArray [ formID ] [ postCheckFunctionDefArray [ formID ].length ] = checkFunction;
}


// If user does not supply a fieldNamePrefix 
// Call the overloaded function and just pass an empty string.
function checkForm ( theForm ) 
{
	checkForm( theForm, '' );
}

// check / submit the form
function checkForm ( theForm, fieldNamePrefix )
{		
	// Default strAlert. Need to set this to empty string so it does 
	// not grow with multiple function calls between page refreshes.
	strAlert = '';
	var fieldValid = false;
	var referenceElement;
	var focusField = 'unfocused';
	
	// strAlertIntro is the text that is used to introduce the main issues list that is alerted 
	// to the user if the main validation proccess finds anything that does not pass validation rules.
	var strAlertIntro = 'You have not entered some required data, please check the following:\n\n';	
	var i = 0;
	var j = 0;
	var fieldNamePrefixLength = 0;
	
	// Required for backwards compatability.
	// Check for the existence of the old preFormCheck and postFormCheck and add
	// them to the pre or post check function arrays.
	if ( window.preFormCheck != null )
	{
		AssignPreCheckFunction ( theForm.id, preFormCheck );
	}	
	if ( window.postFormCheck != null )
	{
		AssignPostCheckFunction ( theForm.id, postFormCheck );
	}
	
	//control used to ensure external checks passed (pre and post form checks)
	var externalCheck = true;
	
	
	// Run all functions added to the post  check function array.
	if ( preCheckFunctionDefArray [ theForm.id ] )
	{
		for ( i = 0; i < preCheckFunctionDefArray [ theForm.id ].length; i++ )
		{	
			externalCheck = preCheckFunctionDefArray [ theForm.id ] [ i ] ( theForm );
					
			if ( ! externalCheck )
			{			
				break;
			}
		}
	}

	
	if ( externalCheck )
	{	
		if (fieldNamePrefix) 
		{
			fieldNamePrefixLength = fieldNamePrefix.length;
		}
	
		// loop over all elements of the form
		for ( i=0; i<theForm.elements.length; i++ )
		{	
			referenceElement = theForm.elements[i];
				
			
			// We want to test all hidden elements names to check if they contain
			// referneces for functions held in our function array.
			if ( referenceElement.name && referenceElement.type && ( fieldNamePrefixLength == 0 || theForm.elements[i].name.substring( 0, fieldNamePrefixLength ) == fieldNamePrefix ) )
			{	
				// Only check hidden fields.		
				if ( referenceElement.type == 'hidden' )
				{
					var suffixName = '';
					var suffixRegex = /_[^_]*$/;					
					var matchArray = suffixRegex.exec ( referenceElement.name );
					if ( matchArray != null )
					{
						suffixName = matchArray [ 0 ];
						
						// Check to ensure the referenced function exists before running it.
						if ( functionDefArray [ suffixName ] && typeof functionDefArray [ suffixName ] == 'function' || typeof functionDefArray [ suffixName ] == 'string' )
						{
							fieldValid = checkFieldValid ( suffixName, theForm, referenceElement );							
						}
						else
						{
							// Write debug to firebug console.
							if ( window.console )
							{
								console.log ( 'Attempted call to a function that does not exist. suffixName: ' + suffixName );
							}			
						}
					}
				}
				
					
				// If a field has not passed the required validation and focusField has not yet been set to anything:
				// We will set the focusField.
				if ( strAlert != '' && focusField == 'unfocused' && fieldValid == false )
				{				
					var checkFieldName = '';
					var checkFieldNameRegex = /.*?(?=_[^_]*$)/;
					var matchArray = checkFieldNameRegex.exec ( referenceElement.name );
					if ( matchArray != null )
					{
						checkFieldName = matchArray [ 0 ];
					}					
					if ( theForm.elements [ checkFieldName ] );
					{
						focusField = eval( 'theForm.' + checkFieldName );
					}
				}		
			}		
		}				
		
		// if strAlert is still empty (has not been appended to), all good, submit the form.	
		if ( strAlert == '' )
		{			
			// You can define functions to run after the general form validation checks.
			// the functions defined here should return a boolean which when false voids form submission
			// and terminates further check form functions from executing.
			// Functions must produce and alert there own error messages.
		
			// Run all functions added to the post check function array.
			if ( postCheckFunctionDefArray [ theForm.id ] )
			{
				for ( i = 0; i < postCheckFunctionDefArray [ theForm.id ].length; i++ )
				{			
					externalCheck = postCheckFunctionDefArray [ theForm.id ] [ i ] ( theForm );
							
					if ( ! externalCheck )
					{			
						break;
					}
				}		
			}		
			
			if ( externalCheck )
			{				
				return true;
			}
			else
			{
				// from postform check
				return false;
			}			
		}
		else
		{	
			// if the user has supplied their own user alert intro text, overwrite the default alert into text.
			if ( theForm.checkFormAlertIntro )
			{
				strAlertIntro = theForm.checkFormAlertIntro.value + '\n\n';
			}
			
			strAlert = strAlertIntro + strAlert;
			// tell the user whats wrong.
			alert ( strAlert );
						
			if ( focusField.focus && focusField.type != 'hidden' && focusField.style.visibility != 'hidden' )
			{				
				// Check if the user has provided a focus field handling function and run it if it exists.	
				if ( functionDefArray [ 'onFieldFocus' ] && typeof functionDefArray [ 'onFieldFocus' ] == 'function' )
				{
					functionDefArray [ 'onFieldFocus' ] ( theForm, focusField );
				}
				focusField.focus();
			}
			
			return false;					
		}
	}
	else
	{
		// from preform check
		return false;
	}
}



function checkFieldValid ( suffixName, theForm, referenceElement )
{
	var fieldValid = true;
	// Create Field Element to test based on reference element.
	// field name minus suffixName		
	var checkFieldName = '';
	var checkFieldNameRegex = /.*?(?=_[^_]*$)/;
	var matchArray = checkFieldNameRegex.exec ( referenceElement.name );
	if ( matchArray != null )
	{	
		checkFieldName = matchArray[0];
		var checkFieldElement = theForm.elements [ checkFieldName ];
		if ( checkFieldElement != null )
		{
			if ( typeof functionDefArray [ suffixName ] == 'function' )
			{
				fieldValid = functionDefArray [ suffixName ] ( theForm, checkFieldElement );
			}
			else if ( typeof functionDefArray [ suffixName ] == 'string' )
			{
				if ( checkFieldElement.value != '' )
				{				
					fieldValid = ibc_regexMatch ( functionDefArray [ suffixName ], checkFieldElement.value );
				}
			}
		}
		else if ( typeof functionDefArray [ suffixName ] == 'function' )
		{
			fieldValid = functionDefArray [ suffixName ] ( theForm );
		}
	}
	
	// if field is not valid
	if ( fieldValid == false )
	{
		// add the value of the required field to the alert
		strAlert = strAlert + referenceElement.value + '\n';	
	}
	
	return fieldValid;
	
}



//  '_required'
// check if any fields need to contain some value
function ibc_required ( theForm, checkFieldElement )
{
	var i = 0;
	var fieldValid = false;			
						
	/* field type so we can figure out what to do
		valid field types:
			text
			textarea
			checkbox
			radio
			select-one
			select-multi
	*/	

	// if the field contains multiple instances, get the type of the first one
	var fieldType;
	fieldType = checkFieldElement.type;					
	if ( fieldType == null )
	{
		var fieldType = checkFieldElement[0].type;
	}
		
	// Validation Tests (based on field type)
	
	// Text
	// if the field is a straight text input
	if ( fieldType == 'text' || fieldType == 'textarea' || fieldType == 'password' || fieldType == 'file' ) // || fieldType == 'hidden' 
	{
		// check to see if a value has been entered
		if ( checkFieldElement.value != '' )
		{
			// if is has field is valid
			fieldValid = true;
		}
	}
	
	// Checkboxen / Radio
	// if the field is a checkbox or radio button or array of the same.
	else if ( fieldType == 'checkbox' || fieldType == 'radio' )
	{	
		if ( checkFieldElement.length )
		{								
			for ( i=0; i<checkFieldElement.length; i++ )
			{
				// make sure at least one is checked
				if ( checkFieldElement[i].checked == true )
				{
					fieldValid = true;
				}
			}
		}
		else if ( checkFieldElement.checked == true )
		{
			fieldValid = true;							
		}
	}
	
	// Select Boxen
	// if the field is a select box of some type
	else if ( ( fieldType == 'select-multiple' && checkFieldElement.selectedIndex != -1 ) || ( fieldType == 'select-one' && checkFieldElement[checkFieldElement.selectedIndex].value != '' ) )
	{		
		fieldValid = true;
	}		
	
	return fieldValid
}


//  '_isNumeric'
// this function checks to ensure a provided value is a numerical value.
function ibc_isNumeric ( theForm, checkFieldElement )
{
	var fieldValid = true;
		
	// Validation Test			
	if ( checkFieldElement.value != '' )
	{
		if ( ( parseInt ( checkFieldElement.value ) * 0 ) == 0 )
		{
			fieldValid = true;
		}
		else
		{
			fieldValid = false;
		}
	}
	
	return fieldValid;
}



function ibc_validDate ( theForm, checkFieldElement )
{
	var fieldValid = true;
	
	if ( checkFieldElement.value != '' )
	{
		// Validation Test			
		if ( checkValidDate ( checkFieldElement.value ) == false )
		{
			fieldValid = false;		
		}
	}
	
	return fieldValid;
}

//this function returns true or false based on whether the date passed to it is in a valid format
function checkValidDate(theDate)
{
	var delimiter
	//create an array containing all the months
	var monthArr = new Array('january','february','march','april','may','june','july','august','september','october','november','december')
	//create an array containing the months with 30 days as numbers
	var int30Arr = new Array(9,4,6,11)
	var proceed = true
	//firstly, find the date's delimiter
	//if a space is found in the date
	if(theDate.indexOf(' ') > -1)
	{
		//set the delimiter to ' '
		delimiter = ' '
	}
	//else if a - is found
	else if(theDate.indexOf('-') > -1)
	{
		//set the delimiter to '-'
		delimiter = '-'
	}
	//else if a / is found
	else if(theDate.indexOf('/') > -1)
	{
		//set the delimiter to '/'
		delimiter = '/'
	}
	else
	{
		proceed = false
	}
	//if a delimiter was found
	if(proceed == true)
	{
		//now i will split the field into the various sections. day, month, year.
		var dateArr = theDate.split(delimiter)
		//if the date has the correct number of attributes
		if(dateArr.length == 3)
		{
			var yearOK = false
			var monthOK = false
			var dayOK = false
			//create variables for each attribute
			var theDay = dateArr[0]
			var theMonth = dateArr[1]
			var theYear = dateArr[2]
			//i will check the attributes from year to day because the day validation will depend on the year and month.
			//make sure the year is a number.
			if(isNaN(theYear) == false)
			{
				if(theYear > 999)
				{
					yearOK = true
				}
			}
			//if the year is ok, move onto the month
			if(yearOK == true)
			{
				//if the month is a number, make sure it is less than or equal to 12
				//if the month is a number
				if(isNaN(theMonth) == false)
				{
					if(theMonth <= 12 && theMonth > 0)
					{
						//the month is valid so we will set the ok flag to true
						monthOK = true
						var monthAsInt = theMonth
					}
				}
				//else if the month is a string
				else
				{
					//loop over each item in the month array
					for(i=0;i<monthArr.length;i++)
					{
						//check if the month = the current element or the first 3 chars of the element
						if(theMonth.toLowerCase() == monthArr[i].toLowerCase() || theMonth.toLowerCase() == monthArr[i].substring(0,3).toLowerCase())
						{
							//the month is valid so we will set the ok flag to true
							monthOK = true
							//create a var of the month as an integer
							var monthAsInt = i + 1
							//break out of the loop
							break
						}
					}
				}
				//if the month is ok, continue to the day
				if(monthOK == true)
				{
					/*The day part of the validation is going to be a bit more difficult than the other validation
					because I need to check that it is not more than the month allows (ie, 30 days for sept
					,april,jun,nov and 28 and 29 based on whether it is a leap year)*/
					
					//firstly, make sure the day is a number
					if(isNaN(theDay) == false)
					{
						var is30 = false
						//loop over the 30 day month array
						for(i=0;i<int30Arr.length;i++)
						{
							//if the month is in the 30 list
							if(monthAsInt == int30Arr[i])
							{
								//set the is30 flag to true
								is30 = true
								//break out of the loop
								break
							}
						}
						//if the month is a 30 day month
						if(is30 == true)
						{
							//make sure the day is lte 30
							if(theDay <= 30 && theDay > 0)
							{
								dayOK = true
							}
						}
						//else if the month is feb
						else if (monthAsInt == 2)
						{
							//check to see if the year is a leap year and the day is 29 or less or the year is not a leap year and the day is 28 or less.
							if((checkYear(theYear) && theDay < 30 && theDay > 0) || (!checkYear(theYear) && theDay > 0 && theDay < 29))
							{
								dayOK = true
							}
						}
						//else if the day is 31 or less
						else if(theDay < 32 && theDay > 0)
						{
							dayOK = true
						}
						//if the day is valid
						if(dayOK == false)
						{
							return false								
						}
						else
						{
							return true;
						}
					}
					//else if the day is not a number
					else
					{
						//return false
						return false
					}
				}
				//else if the month is not valid, return false
				else
				{
					return false
				}
			}
			//else if the year is no good, return false
			else
			{
				return false
			}
		}
		//else if the date does not have the correct number of attributes, return false.
		else
		{
			return false
		}	
	}
	//else if a delimiter was not found, return false
	else
	{
		return false
	}
}
//this function checks if a year is a leap year
function checkYear(theYear) 
{ 
	return (((theYear % 4 == 0) && (theYear % 100 != 0)) || (theYear % 400 == 0)) ? 1 : 0;
}




// URL:  /https?:\/\/.+/i
// File Path:  /^[a-z]:\\([^\\]+\\)*[^\.]+\.([a-z]|[0-9])+$/i
// Email:  /^[\w'']+([\.-]?[\w'']+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/

// ibc_runRegexMatch
// Runs ibc_regexMatch if a regex pattern is found in regexPatternArray
// using regExReference as a key.
// Returns bool value.
function ibc_runRegexMatch ( regExReference, checkString ) 
{
	// If we find a regex pattern in regexPatternArray: 
	// Call ibc_regexMatch passing the pattern.
	if ( regexPatternArray [ regExReference.toLowerCase() ] ) 
	{
		var regExPattern = regexPatternArray [ regExReference.toLowerCase() ];		
		return ibc_regexMatch ( regExPattern, checkString );
	} 
	else
	{
		// Write debug to firebug console.
		if ( window.console )
		{
			console.log ( 'There is no regex pattern available for the provided reference: ' + regExReference );
		}		
		return false;
	}	
}	
	
// ibc_regexMatch
// Returns true if provided text sting matches regex pattern.
function ibc_regexMatch ( regExPattern, checkString ) 
{
	var regex = new RegExp ( regExPattern, "i" )
	if ( checkString.match ( regex ) ) 
	{
		return true;
	} 
	else 
	{
		return false;
	}
}


	
/* :: [restrictLength] ::
This function will stop a user from entering more than a specified number of characters into 
a text area. The function should be run in the onBlur event of the text area.
Args are:
theField: Text area field object
fieldTitle: Name you want displayed in the alert.
maxLength: the maximum length you want the text to reach.
*/
function restrictLength ( theField, fieldTitle, maxLength ) 
{
	//if the field value is too long
	if ( theField.value.length > maxLength ) 
	{
		//alert the user that the string will be truncated.
		alert( 'Your entry for ' + fieldTitle + ' is longer than the maximum allowed length (' + maxLength + ') and will be truncated.' );
		theField.value = theField.value.substr ( 0, maxLength );
		theField.focus();
	}
}



/* :: [checkSearchCriteria] ::
This function will stop a user from entering searchCriteria with more than 8 words and does not allow searchCriteria to start with 'and ' or 'or '.
*/
function checkSearchCriteria ( searchCriteria )
{
	if(searchCriteria.substring(0,4) == 'and ' || searchCriteria.substring(0,3) == 'or '  || searchCriteria == 'and' || searchCriteria == 'or')
	{
		alert( "You can not start a query with \"and\" or \"or\"" );
		return false;
	}
	else if(searchCriteria.split(" ").length > 8)
	{
		alert( "please simplify your query" );
		return false;
	}
	
	return true;
}	



// confirm form reset
function conReset ( theForm )
{
	if ( confirm ('Return the form to the last saved values?' ) )
	{
		theForm.reset();
	}
}


// Confirm Record Delete
function conDel ( ) 
{
	var conMsg = confirm ( 'Are you sure you wish to delete the selected item?' );		
	if ( conMsg )
	{
		return true;
	}
	return false;
}



// addJavaScriptEvent
// Enables us to hook into the browser JavaScript events.
function addJavaScriptEvent ( func, domEventName, ieEventName )
{
	//DOM method for binding an event
	if ( window.addEventListener )
	{
		window.addEventListener ( domEventName, func, true );
	}
	//IE exclusive method for binding an event
	else if ( window.attachEvent )
	{
		window.attachEvent ( ieEventName, func );
	}
	//Older browsers
	else
	{
		window.onload = func;
	}
}


// removeJavaScriptEvent
// Enables remove browser JavaScript events.
function removeJavaScriptEvent ( func, domEventName, ieEventName )
{
	//DOM method for binding an event
	if ( window.removeEventListener )
	{
		window.removeEventListener ( domEventName, func, true );
	}
	//IE exclusive method for binding an event
	else if ( window.detachEvent )
	{
		window.detachEvent ( ieEventName, func );
	}
	//Older browsers - do nothing	
}



function firebugCheck ( messageDivID, siteUrl, currFile )
{	
	var messageDivEl = document.getElementById ( messageDivID );
	messageDivEl.innerHTML = "<div style=\"float: right; margin-left: 15px;\"><a href=\"" + currFile + "?setHideBugIssue=1\" onclick=\"showHideDiv ( 'fBugIssue', 'none' );\"><strong style=\"color: white;\">X</strong></a></div> <div style=\"float: left;\"> 	You are running Firebug version: \"" + window.console.firebug + "\".<br /> 	Firebug is known to cause errors when using the popup calendar date selection tool used by this website.<br />  	We suggest that you disable Firebug for this site. <a href=\"Disable Firebug instructions\" style=\"color: white; text-decoration: underline;\" onclick=\"showHideDiv ( 'fBugIssueMoreInfo', 'block' ); return false;\">Disable information</a>. </div> <div style=\"clear: both;\"></div>  <div id=\"fBugIssueMoreInfo\" style=\"display: none; color: white; padding: 8px 12px 12px 12px; background: black; position: absolute; top: 15px; left: 30px; width: 450px; border: 1px solid #cecece;\"> 	<div style=\"float: right; margin-left: 15px;\"><a href=\"\" onclick=\"showHideDiv ( 'fBugIssueMoreInfo', 'none' ); return false;\"><strong style=\"color: white;\">X</strong></a></div> 	 	<p><strong style=\"font-size: larger;\">Windows or Linux Users</strong></p> 	<p>To disable Firebug:</p> 	<ol style=\"color: white;\"> 	  <li>Click the green or red icon in the bottom right corner of the browser window to open Firebug.</li> 	  <li>Click the bug icon in the top left corner of Firebug and select 'Disable Firebug for " + siteUrl + ".'</li> 	</ol> 	 	<p><strong style=\"font-size: larger;\">Mac Users</strong></p> 	 	<p>To disable Firebug:</p> 	<ol style=\"color: white;\"> 	  <li>Click the green or red icon in the bottom right corner of the browser window to open Firebug.</li> 	  <li>Click the bug icon in the top left corner of Firebug and select 'Disable Firebug for " + siteUrl + ".'</li> 	</ol>  </div>";	
	messageDivEl.style.display = 'block';	
}	
function showHideDiv ( messageDivID, elDisplay )
{			
	var theDivEl = document.getElementById ( messageDivID );	
	theDivEl.style.display = elDisplay;		
}	


function showHideDivAuto ( messageDivID )
{			
	var theDivEl = document.getElementById ( messageDivID );
	var styleDisplayStr = 'block';
	if ( theDivEl.style.display == 'block' )
	{
		styleDisplayStr = 'none';
	}
	theDivEl.style.display = styleDisplayStr;		
}	