/**
 * 
 * Function finds the index of matching option based on the text or value passed,
 * and then sets the matching option as selected.
 * Usefull when repopulating forms for viewing.
 * 
 * @param {Object} HTML Select element.
 * 
 * @param {Object} option text or option value.
 * 
 * @param {String} "text" or "value".
 * 
 * @return {void}
 * 
 */
function setSelectedOption(element, str, valueType)
{
	try
	{
		switch (valueType)
		{
		    case 'value':
		        for (var i=0; i<element.options.length; i++)
				{
					if (element.options[i].value==str)
					{
						element.selectedIndex=i;
					}
				}
		    break;
			case 'text':
			    for (var i=0; i<element.options.length; i++)
				{
					if (element.options[i].text==str)
					{
						element.selectedIndex=i;
					}
				}
			break;
		}		
	}
	catch (e)
	{
		alert('setSelectedOption()\n'+e.name+'\n'+e.message);
	}
}

/**
 * Validates that a string is a valid integer.
 * 
 * @param: {integer} Integer to validate.
 * 
 * @param: {integer} Optional - If not supplied, infinite whole numbers are allowed
 * 
 * @return {boolean} 
*/
function isInt(myNum,size)
{
	var myRegex;
	if(size)
	{
		temp01 ="^([0-9]{"+size+"})$$"
	    myRegex = new RegExp(temp01);
	}
	else
	{
		myRegex=/^((\d+))$$/
	}
	
    if (!myRegex.test(myNum))
    {
   	    return false;
    }
	else
	{
		return true;
	}
}

/**
 * Validates that a string is a valid real number.
 * 
 * @param: {integer} Number to validate.
 * 
 * @param: {integer} Optional - validates the whole number to a certain size.
 * 
 * @param: {integer} Optional - Validates the decimal point to xx decimal points.
 * 
 * @return {boolean}
*/
function isReal(myNum,whole,point)
{
	if(whole&&point)
	{
		temp01="^(\\d{"+whole+"}\\.\\d{"+point+"})$$"
	}
	else if (whole&&!point)
	{
		
		temp01="^(\\d{"+whole+"}\\.\\d+)$$"
	}
	else if(!whole&&point)
	{
		temp01="^(\\d+\\.\\d{"+point+"})$$"
	}
	else
	{
		temp01="^(\\d+\\.\\d+)$$"
	}	
	var myRegex = new RegExp(temp01);
	if (!myRegex.test(myNum))
   	{
       		return false;
    }
	else
	{
		return true;
	}
}

/**
 * Validates that a string is a valid email.
 * 
 * @param {String} Email
 * 
 * @return {boolean}
 */
function isEmail(input) 
{
	var myRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[(2([0-4]\d|5[0-5])|1?\d{1,2})(\.(2([0-4]\d|5[0-5])|1?\d{1,2})){3} \])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
	
	if(!myRegex.test(input))
    {
        return false;
    }
	else
	{
		return true;
	}			
}

/**
 *Application:   Utility Function
 *Author:        John Gardner
 *
 *Version:       V1.0
 *Date:          25th December 2004
 *Description:   Used to check the validity of a UK postcode
 *
 *Version:       V2.0
 *Date:          8th March 2005
 *Description:   BFPO postcodes implemented.
 *              The rules concerning which alphabetic characters are alllowed in 
 *              which part of the postcode were more stringently implementd.
 * 
 *Version:       V3.0
 *Date:          8th August 2005
 *Description:   Support for Overseas Territories added            
 *  
 *Version:       V3.0
 *Date:          23rd March 2008
 *Description:   Problem corrected whereby valid postcode not returned, and 
 *							 'BD23 DX' was invalid treated as 'BD2 3DX'.            
 *  
 *Parameters:    $postcode - postcode to be checked. This is returned reformatted 
 *               if valid.
 *
 *This function checks the value of the parameter for a valid postcode format. The 
 *space between the inward part and the outward part is optional, although is 
 *inserted if not there as it is part of the official postcode.
 *
 *The functions returns a value of false if the postcode is in an invalid format, 
 *and a value of true if it is in a valid format. If the postcode is valid, the 
 *parameter is loaded up with the postcode in capitals, and a space between the 
 *outward and the inward code to conform to the correct format.
 *  
 *Example call:
 *  
 *    if (!isPostcode ($postcode) ) {
 *      echo 'Invalid postcode <br>';
 *    }
 *                    
 */

function isPostcode(toCheck)
{

    // Permitted letters depend upon their position in the postcode.
    var alpha1 = "[abcdefghijklmnoprstuwyz]"; // Character 1
    var alpha2 = "[abcdefghklmnopqrstuvwxy]"; // Character 2
    var alpha3 = "[abcdefghjkstuw]"; // Character 3
    var alpha4 = "[abehmnprvwxy]"; // Character 4
    var alpha5 = "[abdefghjlnpqrstuwxyz]"; // Character 5
    // Array holds the regular expressions for the valid postcodes
    var pcexp = new Array();
    
    // Expression for postcodes: AN NAA, ANN NAA, AAN NAA, and AANN NAA
    pcexp.push(new RegExp("^(" + alpha1 + "{1}" + alpha2 + "?[0-9]{1,2})(\\s*)([0-9]{1}" + alpha5 + "{2})$", "i"));
    
    // Expression for postcodes: ANA NAA
    pcexp.push(new RegExp("^(" + alpha1 + "{1}[0-9]{1}" + alpha3 + "{1})(\\s*)([0-9]{1}" + alpha5 + "{2})$", "i"));
    
    // Expression for postcodes: AANA  NAA
    pcexp.push(new RegExp("^(" + alpha1 + "{1}" + alpha2 + "?[0-9]{1}" + alpha4 + "{1})(\\s*)([0-9]{1}" + alpha5 + "{2})$", "i"));
    
    // Exception for the special postcode GIR 0AA
    pcexp.push(/^(GIR)(\s*)(0AA)$/i);
    
    // Standard BFPO numbers
    pcexp.push(/^(bfpo)(\s*)([0-9]{1,4})$/i);
    
    // c/o BFPO numbers
    pcexp.push(/^(bfpo)(\s*)(c\/o\s*[0-9]{1,3})$/i);
    
    // Overseas Territories
    pcexp.push(/^([A-Z]{4})(\s*)(1ZZ)$/i);
    
    // Load up the string to check
    var postCode = toCheck;
    
    // Assume we're not going to find a valid postcode
    var valid = false;
    
    // Check the string against the types of post codes
    for (var i = 0; i < pcexp.length; i++) 
	{
        if (pcexp[i].test(postCode)) 
		{
        
            // The post code is valid - split the post code into component parts
            pcexp[i].exec(postCode);
            
            // Copy it back into the original string, converting it to uppercase and
            // inserting a space between the inward and outward codes
            postCode = RegExp.$1.toUpperCase() + " " + RegExp.$3.toUpperCase();
            
            // If it is a BFPO c/o type postcode, tidy up the "c/o" part
            postCode = postCode.replace(/C\/O\s*/, "c/o ");
            
            // Load new postcode back into the form element
            valid = true;
            
            // Remember that we have found that the code is valid and break from loop
            break;
        }
    }
    
    // Return with either the reformatted valid postcode or the original invalid 
    // postcode
    if (valid) 
	{
        return postCode;
    }
    else 
        return false;
}


/**
 * Validates that a string is not all blank (whitespace) characters.
 * 
 * @param {String} String to be tested for validity
 * 
 * @return {boolean}
 */
function isNotEmpty(input) 
{
	try
	{
		var strTemp = input;
		strTemp = strTrim(strTemp);
		
		if(strTemp.length > 0)
		{
			return true;
		}
		
		return false;
	}
	catch(e)
	{
		alert('isNotEmpty() ERROR:\n'+e.message);
	}
}

/**
 * Validates that a string only contains characters A-Z or a-z.
 * 
 * @param {String} String to be tested for validity
 * 
 * @return {boolean}
 */
function isString(input)
{
	var myRegex = /^[a-zA-z]+$/;  /*/^([a-z]|[A-Z]| )*$/;*/
	if(!myRegex.test(input))
	{
		return false;
	}
	else
	{
		return true;
	}
}

/**
 * Validates that a string only contains characters A-Z or a-z or 0-9.
 * 
 * @param {String} String to be tested for validity
 * 
 * @return {boolean}
 */
function isAlphanumeric(input)
{
	var myRegex = /^[0-9A-Za-z]+$/;
	
	if(!myRegex.test(input))
	{
		return false;
	}
	else
	{
		return true;
	}
}

/**
 * This routine checks the value of the string variable specified by the parameter
 * for a valid UK telphone number. It returns false for an invalid number and the
 * reformatted telephone number false a valid number.
 * 
 * If false is returned, the global variable telNumberError contains an error
 * number, which may be used to index into the array of error descriptions 
 * contained in the global array telNumberErrors.
 * 
 * The definition of a valid telephone number has been taken from:
 * 
 * http://www.ofcom.org.uk/telecoms/ioi/numbers/numplan310507.pdf
 *   and
 * http://www.ofcom.org.uk/telecoms/ioi/numbers/num_drama
 * 
 * All inappropriate telephone numbers are disallowed (e.g. premium lines, sex 
 * lines, radio-paging services etc.)
 * 
 * Author:    John Gardner
 * Date:      16th November 2003
 * 
 * Version:   V1.1  4th August 2006       
 * 					 Updated to include 03 numbers being added by Ofcom in early 2007.
 * 
 * Version:   V1.2  9th January 2007
 *            Isle of Man mobile numbers catered for 
 * 
 * Version:   V1.3  6th November 2007
 *            Support for mobile numbers improved - thanks to Natham Lisgo
 * 
 * Version:   V1.4  14th April 2008
 *            Numbers allocated for drama excluded - thanks to David Legg
 * 			
 * Example calling sequnce:
 * 
 *   if (!isPhoneNumber (myTelNo)) 
 *   {
 *      alert (telNumberErrors[telNumberErrorNo]);
 *   }
 *   
 * @param {String}
 *   
 * @return {String}
 */ 
function isPhoneNumber(telephoneNumber)
{

	// Convert into a string and check that we were provided with something
	var telnum = telephoneNumber + " ";
	if (telnum.length == 1) 
	{
		return false
	}
	telnum.length = telnum.length - 1;
	
	// Don't allow country codes to be included (assumes a leading "+")
	var exp = /^(\+)[\s]*(.*)$/;
	if (exp.test(telnum) == true) 
	{
		return false;
	}
	
	// Remove spaces from the telephone number to help validation
	while (telnum.indexOf(" ") != -1) 
	{
		telnum = telnum.slice(0, telnum.indexOf(" ")) + telnum.slice(telnum.indexOf(" ") + 1)
	}
	
	// Remove hyphens from the telephone number to help validation
	while (telnum.indexOf("-") != -1) 
	{
		telnum = telnum.slice(0, telnum.indexOf("-")) + telnum.slice(telnum.indexOf("-") + 1)
	}
	
	// Now check that all the characters are digits
	exp = /^[0-9]{10,11}$/;
	if (exp.test(telnum) != true) 
	{
		return false;
	}
	
	// Now check that the first digit is 0
	exp = /^0[0-9]{9,10}$/;
	if (exp.test(telnum) != true) 
	{
		return false;
	}
	
	// Disallow numbers allocated for dramas.
	
	// Array holds the regular expressions for the drama telephone numbers
	var tnexp = new Array();
	tnexp.push(/^(0113|0114|0115|0116|0117|0118|0121|0131|0141|0151|0161)(4960)[0-9]{3}$/);
	tnexp.push(/^02079460[0-9]{3}$/);
	tnexp.push(/^01914980[0-9]{3}$/);
	tnexp.push(/^02890180[0-9]{3}$/);
	tnexp.push(/^02920180[0-9]{3}$/);
	tnexp.push(/^01632960[0-9]{3}$/);
	tnexp.push(/^07700900[0-9]{3}$/);
	tnexp.push(/^08081570[0-9]{3}$/);
	tnexp.push(/^09098790[0-9]{3}$/);
	tnexp.push(/^03069990[0-9]{3}$/);
	
	for (var i = 0; i < tnexp.length; i++) 
	{
		if (tnexp[i].test(telnum)) 
		{
			return false;
		}
	}
	
	// Finally check that the telephone number is appropriate.
	exp = (/^(01|02|03|05|070|071|072|073|074|075|07624|077|078|079)[0-9]+$/);
	if (exp.test(telnum) != true) 
	{
		return false;
	}
	
	// Telephone number seems to be valid - return the stripped telehone number  
	return telnum;
}

function isAddress(input)
{
	try
	{
		var myRegex = /^[0-9A-Za-z\s]+$/;
	
		if(!myRegex.test(input))
		{
			return false;
		}
		else
		{
			return true;
		}
	}
	catch(e)
	{
		
	}
}

function isValidCreditCard(ccnum, type) 
{
	try
	{
		var myRegex;
		
		if (type == "Visa") 
		{
			// Visa: length 16, prefix 4, dashes optional.
			myRegex = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/;
		} 
		else if (type == "MasterCard") 
		{
			// Mastercard: length 16, prefix 51-55, dashes optional.
			myRegex = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/;
		} 
		else if (type == "Discover") 
		{
			// Discover: length 16, prefix 6011, dashes optional.
			myRegex = /^6011-?\d{4}-?\d{4}-?\d{4}$/;
		} 
		else if (type == "Amex") 
		{
			// American Express: length 15, prefix 34 or 37.
			myRegex = /^3[4,7]\d{13}$/;
		} 
		else if (type == "Diners") 
		{
			// Diners: length 14, prefix 30, 36, or 38.
			myRegex = /^3[0,6,8]\d{12}$/;
		}
		else if(type == "Switch")
		{
			myRegex = /^4903|4936|4911|5641|6333|6759\d{12}$/;
		}
		else if(type == "Solo")
		{
			myRegex = /^6334|6767\d{12}$/;
		}
		
		if (!myRegex.test(ccnum)) 
			return false;
		
		// Remove all dashes for the checksum checks to eliminate negative numbers
		ccnum = ccnum.split("-").join("");
		
		// Checksum ("Mod 10")
		// Add even digits in even length strings or odd digits in odd length strings.
		var checksum = 0;
		for (var i=(2-(ccnum.length % 2)); i<=ccnum.length; i+=2) 
		{
			checksum += parseInt(ccnum.charAt(i-1));
		}
		
		// Analyze odd digits in even length strings or even digits in odd length strings.
		for (var i=(ccnum.length % 2) + 1; i<ccnum.length; i+=2) 
		{
			var digit = parseInt(ccnum.charAt(i-1)) * 2;
			if (digit < 10) 
			{ 
				checksum += digit; 
			} 
			else 
			{ 
				checksum += (digit-9); 
			}
		}
		
		if ((checksum % 10) == 0) 
			return true; 
		else 
			return false;
	}
	catch(e)
	{
		alert('isValidCreditCard()\nERROR:\n'+e.message);
	}
}

function isValidcvv2Number(cvv2, cardType)
{
	var validLength;
	
	cvv2 = strTrim(cvv2);
	
	if(cardType == "Amex")
	{
		validLength = 4;
	}
	else
	{
		validLength = 3;
	}
	
	if(cvv2.length == validLength && isInt(cvv2))
	{
		return true;
	}
	else
	{
		return false;
	}
}

/**
 * Removes all white space characters from the string.
 * 
 * @param: {String} String to trim.
 * 
 * @return {String} Trimed string.
*/
function strTrim(strTrim) 
{
	return strTrim.replace(/^\s+|\s+$/g, '');
}

/**
 * Removes the white space character from the start of string.
 * 
 * @param: {string} String to trim.
 * 
 * @return {string} Trimed string.
*/
function strLTrim(strTrim) 
{
	return strTrim.replace(/^\s+/, '');
}

/**
 * Removes the white space character from the end of string.
 * 
 * @param: {string} String to trim.
 * 
 * @return {string} Trimed string.
*/
function strRTrim(strTrim)
{
	return strTrim.replace(/\s+$/, '');
}

/**
 * This function provides a couple of advantages for debugging. 
 * First, it allows you to verify what object you are working with during your script. 
 * It also allows you to verify the properties of that object (maybe you can't remember the property name or don't know how to spell it). 
 * It is also good if you are working with a heirarchy of properties. For example, if you think it might be document.body.referer for 
 * the property you want, but aren't sure, you can show all the document properties, recursively, to find out which one it is. 
 * (it's actually document.referer). 
 * 
 * @author: Taken from Breaking Par Consulting, Inc. http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256DA3007B8FBB
 * 			 Breaking Par Consulting, Inc. has closed its doors and is no longer in business.
 * 
 * @param: {Object} Object which properties will be displayed:
 * 
 * @param: [parent] Note that the "parent" variable is optional and not needed for the initial call to the function. It is only used during the recursion.
 * 
 * @return {void}
 * 
*/
function dumpObjectProperties(obj, parent) 
{
	// Go through all the properties of the passed-in object 
	for (var i in obj)
	{
		// if a parent (2nd parameter) was passed in, then use that to 
		// build the message. Message includes i (the object's property name) 
		// then the object's property value on a new line 
		if (parent) 
		{
			var msg = parent + "." + i + "\n" + obj[i]; 
		} 
		else 
		{
			var msg = i + "\n" + obj[i]; 
		}
		
		// Display the message. If the user clicks "OK", then continue. If they 
		// click "CANCEL" then quit this level of recursion 
		if (!confirm(msg)) 
		{
			return; 
		}
		
		// If this property (i) is an object, then recursively process the object 
		if (typeof obj[i] == "object") 
		{ 
			if (parent) 
			{
				dumpObjectProperties(obj[i], parent + "." + i); 
			} 
			else
			{
				dumpObjectProperties(obj[i], i); 
			}
		}
 	}
}

function hideBlock(objElement)
{
	try
	{
		objElement.style.display = 'none';
		objElement.style.visibility = 'hidden';
	}
	catch(e){}
}

function displayBlock(objElement)
{
	try
	{
		objElement.style.display = 'block';
		objElement.style.visibility = 'visible';
	}
	catch(e){}
}

