// Correctly handle PNG transparency in Win IE 5.5 or higher.
// http://homepage.ntlworld.com/bobosola. Updated 02-March-2004

function isTelNum( str )
{
	// Remove whitespace
	str = str.replace(/\s*/g, '' );
	
	// Optional leading + followed by 8 to 20 digits.
	var expr = /^\+?\d{8,20}$/;
	
	return expr.test(str);
}


function CustomValidateTelNum(source, arguments)
{
	arguments.IsValid = isTelNum( arguments.Value );
}


function isNationalInsuranceNumber( str )
{
	// http://regexlib.com/REDetails.aspx?regexp_id=527
	var expr = /^[A-CEGHJ-PR-TW-Z]{1}[A-CEGHJ-NPR-TW-Z]{1}\s?[0-9]{2}\s?[0-9]{2}\s?[0-9]{2}\s?[A-DFM]{0,1}$/i;
	
	return expr.test(str);
}

function CustomValidateNationalInsuranceNumber(source, arguments)
{
	arguments.IsValid = isNationalInsuranceNumber( arguments.Value );
}


// Builds a URL from the specified parameters and opens it in the specified window with the specified features.
function OpenObfuscatedLink( scheme, host1, host2, host3, pathAndQuery, targetWindow, features )
{
	if( host1 == undefined || host1 == null || host1.length == 0 )
	{
		throw 'host1 must be specified.';
		return;
	}
	
	// Build hostname from 3 possible values.
	var sHost = host1;
	sHost = AppendIfDefined( sHost, host2, '.' );
	sHost = AppendIfDefined( sHost, host3, '.' );
	
	// Default to / if pathAndQuery wasn't specified.
	if( pathAndQuery == undefined || pathAndQuery == null || pathAndQuery.length == 0 )
		pathAndQuery = '/';
	
	var sUrl = scheme + '://' + sHost + pathAndQuery;
	
	// Default to _self if targetWindow wasn't specified.
	if( targetWindow == undefined || targetWindow == null || targetWindow == '' )
		targetWindow = '_self';
	
	// Open window with or without features.
	if( features == undefined || features == null || features.length == 0 )
		window.open( sUrl, targetWindow );
	else
		window.open( sUrl, targetWindow, features );
}


// Appends valueToAppend to appendTo if valueToAppend is defined/not null/not empty string. Delimits values with separator.
function AppendIfDefined( appendTo, valueToAppend, separator )
{
	if( valueToAppend != undefined && valueToAppend != null && valueToAppend.length > 0 )
		return appendTo + separator + valueToAppend;
}


// Sets each of the current page's anchor tags' target attribute to '_blank' if the anchor's rel attribute is 'external'.
// Gets around XHTML's issue with Target attributes in anchors.
function externalLinks()
{ 
	if (!document.getElementsByTagName)
		return; 
	var anchors = document.getElementsByTagName("a"); 
	for (var i=0; i<anchors.length; i++)
	{ 
		var anchor = anchors[i]; 
		if (anchor.getAttribute("href") && anchor.getAttribute("rel") == "external") 
			anchor.target = "_blank";
	} 
}

// Always run this function.
window.onload = externalLinks;


function ExistParameter ( ParameterName )
{
	var url = window.document.URL.toString();

	if ( url.indexOf ( '?' ) > 0 )
	{
		var Parameters = url.split ( '?' ) [ 1 ].split ( '&' );
		for ( i = 0; i < Parameters.length; i++ )
		{
			if ( Parameters [ i ].indexOf ( '=' ) > 0 )
			{
				if ( Parameters [ i ].split ( '=' )[ 0 ] == ParameterName )
					return true; 
			}
		}
	}
	return false;
}


function GetParamterValue ( ParameterName )
{
	var url = window.document.URL.toString();

	if ( url.indexOf ( '?' ) > 0 )
	{
		var Parameters = url.split ( '?' ) [ 1 ].split ( '&' );
		for ( i = 0; i < Parameters.length; i++ )
		{
			if ( Parameters [ i ].indexOf ( '=' ) > 0 )
			{
				var ParameterValue = Parameters [ i ].split ( '=' );
				if ( ParameterValue [ 0 ] == ParameterName )
					return ParameterValue [ 1 ];
			}
		}
	}
	return '';
}



// Validates that the length of a textarea's text does not exceed MaxLen.
function imposeMaxLength(Object, MaxLen)
{
  return (Object.value.length <= MaxLen);
}


function padLeft ( str, maxLen, padChar )
{
	// Quit if nothing to do.
	if ( ( (! maxLen ) || ( maxLen < 1 ) ) || ( (! str ) || str == '' || str.length >= maxLen ) )
		return str;

	// This is string of 100 spaces
	var padding = '                                                                                                    ';

	if ( padChar )
	{
		// replace the SPACES defined here with the given character(s)
		padding = padding.replace( / /g, padChar );
	}
	
	// Add some padding.
	var s = padding + str;
	
	// Get just the necessary part of the padding plus all the original string.
	return s.substring(s.length - maxLen);

}


function parseDateTimeFromDropDowns( ddlDay, ddlMonth, ddlYear, ddlHour, ddlMinute )
{
	var dtDate = parseDateFromDropDowns( ddlDay, ddlMonth, ddlYear );
	var dtTime = parseTimeFromDropDowns( ddlHour, ddlMinute );
	
	if( dtDate == null || dtTime == null )
		return null;
	else
		return new Date( dtDate.getFullYear(), dtDate.getMonth(), dtDate.getDate(), dtTime.getHours(), dtTime.getMinutes(), 0 );
}


function parseDateFromDropDowns( ddlDay, ddlMonth, ddlYear )
{
	var day = ddlDay.options[ddlDay.selectedIndex].value;
	var month = ddlMonth.options[ddlMonth.selectedIndex].value;
	var year = ddlYear.options[ddlYear.selectedIndex].value;
	
	var sDate = day + '/' + month + '/' + year;
	
	if( isDate( sDate ) )
		return new Date( year, parseInt( month, 10 ) - 1, day );
	else
		return null;
}


function parseTimeFromDropDowns( ddlHour, ddlMinute )
{
	var hour =  ddlHour.options[ddlHour.selectedIndex].value;
	var minute = ddlMinute.options[ddlMinute.selectedIndex].value;
	var sTime = padLeft( hour, 2, '0' ) + ':' + padLeft( minute, 2, '0' );
	
	if( isTime( sTime ) )
		return new Date( 1, 0, 1, hour, minute );
	else
		return null;
}


// Parses a date string from dd/MM/yyyy format. Returns null if any error occurs.
function parseDateFromTextBox( value )
{
	if(!isDate(value))
		return null;
	
	var arr = value.split('/');
	if(arr.length != 3)
		return null;
	
	var day = parseInt( arr[0], 10 );
	var month = parseInt( arr[1], 10 );
	var year = parseInt( arr[2], 10 );
	
	if(isNaN(day) || day < 1 || day > 31) // Valid Day of Month?
		return null;
		
	if(isNaN(month) || month < 1 || month > 12) // Valid Month of year?
		return null;
		
	if(isNaN(year) || year < 1 || year > 9999) // Valid year?
		return null;
		
	return new Date( year, month - 1, day );
}


// Parses a time string from HH:mm format. Returns null if any error occurs.
function parseTimeFromTextBox( value )
{
	if(!isTime(value))
		return null;
	
	var arr = value.split(':');
	if(arr.length != 2)
		return null;
	
	var hour = parseInt( arr[0], 10 );
	var minute = parseInt( arr[1], 10 );
	
	if(isNaN(hour) || hour < 0 || hour > 23) // Valid Hour?
		return null;
		
	if(isNaN(minute) || minute < 0 || minute > 59) // Valid Minute?
		return null;
		
	return new Date( 0, 0, 0, hour, minute );
}


function toggleTagVisibility(toggleCtl, toggleCtlText, tagId, hiddenFieldId)
{
	var tag = document.getElementById( tagId );
	var hiddenField = document.getElementById( hiddenFieldId );
	
	if( tag.style.display == '' )
	{
		tag.style.display = 'none';
		hiddenField.value = 'false';
		if (toggleCtl.tagName == 'A')
			toggleCtl.innerText = toggleCtlText.replace( '{0}', 'Show' );
		else
			toggleCtl.value = toggleCtlText.replace( '{0}', 'Show' );
	}
	else
	{
		tag.style.display = '';
		hiddenField.value = 'true';
		if (toggleCtl.tagName == 'A')
			toggleCtl.innerText = toggleCtlText.replace( '{0}', 'Hide' );
		else
			toggleCtl.value = toggleCtlText.replace( '{0}', 'Hide' );
	}
}


/*
function toggleTagVisibility(toggleCtl, toggleCtlText, tagId, hiddenFieldId)
{
	var tag = document.getElementById( tagId );
	var hiddenField = document.getElementById( hiddenFieldId );
	
	if( tag.style.display == '' )
	{
		tag.style.display = 'none';
		hiddenField.value = 'false';
		if (toggleCtl.tagName == 'A')
			toggleCtl.innerText = 'Show ' + toggleCtlText;
		else
			toggleCtl.value = 'Show ' + toggleCtlText;
	}
	else
	{
		tag.style.display = '';
		hiddenField.value = 'true';
		if (toggleCtl.tagName == 'A')
			toggleCtl.innerText = 'Hide ' + toggleCtlText;
		else
			toggleCtl.value = 'Hide ' + toggleCtlText;
	}
}
*/

// This allows us to output HTML <object> tags for Flash movies that prevent user from having to "click to activate this control" in Internet Explorer.
function writeObjectTag( height, width, clientId, src, cssClass, altImgSrc, altImgHref )
{
	var attributes = "";
	if (height > 0 && width > 0) attributes += ' height="' + height + '" width="' + width + '"';
	if (clientId != '') attributes += ' id="' + clientId + '"';
	if (cssClass != '') attributes += ' class="' + cssClass + '"';

	if(FlashDetect.installed || (altImgSrc == "")){
		document.write( '\n<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0"' );
		document.write( attributes + '>' );
		document.write( '\n<param name="movie" value="' + src + '">' );
		document.write( '\n<param name="quality" value="high">' );
		document.write( '\n<param name="wmode" value="transparent">' );
		document.write( '\n<embed wmode="transparent" pluginspage="https://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" quality="high" type="application/x-shockwave-flash" ' );
		if (height > 0 && width > 0)
			document.write( ' height="' + height + '" width="' + width + '"' );
		document.write( ' src="' + src + '">' );
		document.write( '\n</embed>' );
		document.write( '\n</object>' );
	}else{
		// Display a static image for users without flash.
		if(altImgHref != "") document.write('<a href="' + altImgHref + '">');
		document.write('<img alt="" src="' + altImgSrc + '"' + attributes + ' />');
		if(altImgHref != "") document.write('</a>');
	}
}

// Flash detection script.  Uncompressed version available from http://www.featureblend.com/javascript-flash-detection-library.html
var FlashDetect=new function(){var self=this;self.installed=false;self.major=-1;self.minor=-1;self.revision=-1;self.revisionStr="";self.activeXVersion="";var activeXDetectRules=[{"name":"ShockwaveFlash.ShockwaveFlash.7","version":function(obj){return getActiveXVersion(obj);}},{"name":"ShockwaveFlash.ShockwaveFlash.6","version":function(obj){var version="6,0,21";try{obj.AllowScriptAccess="always";version=getActiveXVersion(obj);}catch(err){}
return version;}},{"name":"ShockwaveFlash.ShockwaveFlash","version":function(obj){return getActiveXVersion(obj);}}];var getActiveXVersion=function(activeXObj){var version=-1;try{version=activeXObj.GetVariable("$version");}catch(err){}
return version;};var getActiveXObject=function(name){var obj=-1;try{obj=new ActiveXObject(name);}catch(err){}
return obj;};var parseActiveXVersion=function(str){var versionArray=str.split(",");return{"major":parseInt(versionArray[0].split(" ")[1],10),"minor":parseInt(versionArray[1],10),"revision":parseInt(versionArray[2],10),"revisionStr":versionArray[2]};};var parseRevisionStrToInt=function(str){return parseInt(str.replace(/[a-zA-Z]/g,""),10)||self.revision;};self.majorAtLeast=function(version){return self.major>=version;};self.FlashDetect=function(){if(navigator.plugins&&navigator.plugins.length>0){var type='application/x-shockwave-flash';var mimeTypes=navigator.mimeTypes;if(mimeTypes&&mimeTypes[type]&&mimeTypes[type].enabledPlugin&&mimeTypes[type].enabledPlugin.description){var desc=mimeTypes[type].enabledPlugin.description;var descParts=desc.split(' ');var majorMinor=descParts[2].split('.');self.major=parseInt(majorMinor[0],10);self.minor=parseInt(majorMinor[1],10);self.revisionStr=descParts[3];self.revision=parseRevisionStrToInt(self.revisionStr);self.installed=true;}}else if(navigator.appVersion.indexOf("Mac")==-1&&window.execScript){var version=-1;for(var i=0;i<activeXDetectRules.length&&version==-1;i++){var obj=getActiveXObject(activeXDetectRules[i].name);if(typeof obj=="object"){self.installed=true;version=activeXDetectRules[i].version(obj);if(version!=-1){var versionObj=parseActiveXVersion(version);self.major=versionObj.major;self.minor=versionObj.minor;self.revision=versionObj.revision;self.revisionStr=versionObj.revisionStr;self.activeXVersion=version;}}}}}();};FlashDetect.release="1.0.2";

// Validates a string as a UK Postcode.
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);

	// 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';
}


// Used by ASP.NET CustomValidator controls that need to validate a postcode in a textbox.
function CustomValidatePostcode(source, arguments)
{
	arguments.IsValid = isPostcode( arguments.Value ) != 'false';
}


// Used by Tapestry CheckBoxValidator controls that need to validate an ASP.NET CheckBox control.
function CheckBoxValidatorEvaluateIsValid(val)
{
	var control = document.getElementById(val.controltovalidate);
	var mustBeChecked = val.mustBeChecked == 'true' ? true : false;

	return control.checked == mustBeChecked;
}


// Used by Tapestry CheckBoxListValidator controls that need to validate an ASP.NET CheckBoxList control.
function CheckBoxListValidatorEvaluateIsValid(val)
{
	var control = document.getElementById(val.controltovalidate);
	var minimumNumberOfSelectedCheckBoxes = parseInt(val.minimumNumberOfSelectedCheckBoxes);

	var selectedItemCount = 0;
	var liIndex = 0;
	var currentListItem = document.getElementById(control.id + '_' + liIndex.toString());
	
	while (currentListItem != null)
	{
		if (currentListItem.checked) selectedItemCount++;
			liIndex++;
			
		currentListItem = document.getElementById(control.id + '_' + liIndex.toString());
	}

	return selectedItemCount >= minimumNumberOfSelectedCheckBoxes;
}


// Displays Calendar.aspx in a popup window with predefined properties.
function calendarPopup( appRootFolder, targetControlId )
{
	var targetControl = document.getElementById( targetControlId );
	var calendar_window = window.open( appRootFolder + 'Calendar.aspx?TargetControlId=' + targetControl.id + '&InitialDate=' + escape( targetControl.value ), 'calendar_window', 'width=202,height=182' );
	calendar_window.focus();
}


// Removes whitespace characters from the ends of the specified string. Equivalent of Visual Basic Trim() function.
function trim( str )
{
   return str.replace(/^\s*|\s*$/g, '' );
}


// Returns a reference to a client-side control whose ID property was generated by ASP.NET.
function findControl( ParentID, ChildID, ChildPosition )
{
	// Build the control's client-side ID, e.g. 'repChildren__ctl1_ddlChildrenTitle'.
	var sID = ParentID + '__ctl' + ChildPosition + '_' + ChildID;
	// Return a reference to that control.
	var ctl = document.getElementById( sID );
	return ctl;
}


// Determines if the specified variable is a valid JavaScript object.
// Useful for determining if a particular HTML control exists on the page.
function isObject( a )
{
	return( a && typeof( a ) == 'object' ) || isFunction( a );
}	


// Determines if the specified variable is a JavaScript Function.
function isFunction( a )
{
	return typeof( a ) == 'function';
}


// Determines if the specified variable is a JavaScript Array or not.
function isArray( Variable )
{
	if( (typeof( Variable ) == 'object') && (Variable.constructor == Array) )
		return true;
	else
		return false;
}


// Calculates the age in whole years on the current date.
function age( dob )
{
	var Now = new Date();
	
	// Get the difference in years.
	var iAge = Now.getFullYear() - dob.getFullYear(); 
	
	if( Now.getMonth() < dob.getMonth() || ( Now.getMonth() == dob.getMonth() && Now.getDate() < dob.getDate() ) )
		iAge--;
	
	return iAge;
}


// Calculates the age in whole years on the specified date.
function ageAt( dob, onDate )
{
	// Get the difference in years.
	var iAge = onDate.getFullYear() - dob.getFullYear(); 
	
	if( onDate.getMonth() < dob.getMonth() || ( onDate.getMonth() == dob.getMonth() && onDate.getDate() < dob.getDate() ) )
		iAge--;
	
	return iAge;
}

// Opens a popup window at the specified page. width and height params are optional.
function popup( url, width, height )
{
	if (width == null)
		width = '500';
	
	if (height == null)
		height = '400';
		
	//window.open( url, '_blank', 'height=400,width=500,toolbar=no,status=yes,menubar=no,resizable=yes,scrollbars=yes' );
	window.open( url, '_blank', 'height=' + height + ',width=' + width + ',toolbar=no,status=yes,menubar=no,resizable=yes,scrollbars=yes' );
}


// Checks if the specified credit card number is valid for the specified credit card type.
function validateCreditCardNumber( ccno, cctype )
{
	var sMsg = '';
	var vlengthgood = 0;
	var ccsum = 0;
	var cclen = ccno.length;
	
	if( cctype == '' )
		sMsg += '\nPlease select a credit card type.';
	
	if( ccno.replace(/\s/ig, '' ) == '' )
		sMsg += '\nPlease supply a valid credit card number.';
	
	return sMsg;

	if (cctype=='')
		sMsg += "\nPlease select a card type from the list.";

	if (cclen<13)
		sMsg += "\nCredit cards must have at least 13 digits.";
	else
	{
		for (i=1; i<cclen; i++)
		{
			var ccdig = parseInt(ccno.charAt(cclen-(i+1)));
			if (i%2==1)
			{
				ccdig*=2;
				if (ccdig.toString().length==2)
				{
					ccdig=(parseInt(ccdig.toString().charAt(0))+parseInt(ccdig.toString().charAt(1)));
				} 
			}
			ccsum+=ccdig;
		}
		ccsum+=parseInt(ccno.charAt(cclen-1));
		if (ccsum%10==0)
		{
			cc_type_id = 'NOT VALID TYPE';
			
			if (ccno.match(/^4/) )
				{cc_type_id = 'VISA';   if (cclen==13 || cclen==16) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^50|^56|^57|^58|^6/) )
				{cc_type_id = 'MAESTRO';   vlengthgood=1;}
			if (ccno.match(/^51|^52|^53|^54|^55/) )
				{cc_type_id = 'MC';   if (cclen==16) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^413733|^413734|^413735|^413736|^413737|^4462|^453978|^453979|^454313|^454313|^454432|^454433|^454434|^454435|^454742|^456725|^456726|^456727|^456728|^456729|^45673|^456740|^456741|^456742|^456743|^456744|^456745|^46583|^46584|^46585|^46586|^46587|^484409|^484410|^49096|^49097|^492181|^492182|^498824/) )
				{cc_type_id = 'DELTA';   if (cclen==16) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^450875|^484406|^484407|^484408|^484411|^484412|^484413|^484414|^484415|^484416|^484417|^484418|^484419|^48442|^48443|^48444|^484450|^484451|^484452|^484453|^484454|^484455|^49173|^49174|^49175|^491880/) )
				{cc_type_id = 'ELECTRON';   if (cclen==16) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^405501|^405502|^405503|^405504|^405550|^405551|^405552|^405553|^405554|^415928|^424604|^424604|^427533|^4288|^443085|^4484|^4485|^4486|^4715|^4716|^4804/) )
				{cc_type_id = 'VISA';   if (cclen==16) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^490300|^490301|^49031|^49032|^490330|^490331|^490332|^490333|^490334|^49034|^49035|^49036|^49037|^49038|^49039|^49040|^490419|^490451|^490459|^490467|^490475|^490476|^490477|^490478|^4905|^491103|^491104|^491105|^491106|^491107|^491108|^491109|^49111|^49112|^49113|^49114|^49115|^49116|^491170|^491171|^491172|^491173|^491183|^491184|^491185|^491186|^491187|^491188|^491189|^49119|^4928|^4987/) )
				{cc_type_id = 'VISA ATM ONLY';   if (cclen==16) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^60/) )
				{cc_type_id = 'DISCOVER';   if (cclen==16) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^63345|^63346|^63347|^63348|^63349|^6767/) )
				{cc_type_id = 'SOLO';   if (cclen==16 || cclen==18 || cclen==19) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^490302|^490303|^490304|^490305|^490306|^490307|^490308|^490309|^490335|^490336|^490337|^490338|^490339|^491101|^491102|^491174|^491175|^491176|^491177|^491178|^491179|^491180|^491181|^491182|^4936|^564182|^63330|^63331|^63332|^63333|^63334|^6759/) )
				{cc_type_id = 'SWITCH';   if (cclen==16 || cclen==18 || cclen==19) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^34|^37/) )
				{cc_type_id = 'AMEX';   if (cclen==13 || cclen==15) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^3528|^3529|^353|^354|^355|^356|^357|^358|^2131|^1800/) )
				{cc_type_id = 'JCB';   if (cclen==15 || cclen==16) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^300|^301|^302|^303|^304|^305|^36|^380|^381|^382|^383|^384|^385|^386|^387|^388/) )
				{cc_type_id = 'DINERS CLUB';   if (cclen==14) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^389/) )
				{cc_type_id = 'CARTE BLANCHE';   if (cclen==14) {vlengthgood=1;}   else {vlengthgood=0;} }
			if (ccno.match(/^2014|^2149/) )
				{cc_type_id = 'ENROUTE';   if (cclen==15) {vlengthgood=1;}   else {vlengthgood=0;} }
			if( cctype == 'ACCESS' )
				{cc_type_id = 'ACCESS'; vlengthgood = 1; }

			if (vlengthgood==1) 
				{
					if(cctype!=cc_type_id)
					{
						sMsg += "\nCard type does not match card number.";
					}
				}
			else
				{
					sMsg += "\nThis card number is not valid.";
				}
		} 
		else
		{
			sMsg += "\nThis card number is not valid.";
		}
	}
	
	return sMsg; // Empty string means the credit card number IS valid.
}


// Determines if the specified string represents an integer.
function isInt( s )
{
	var i = parseInt (s);

	if( isNaN( i ) )
		return false;

	i = i.toString();
	if( i != s )
		return false;

	return true;
}

// Used by ASP.NET CustomValidator controls that need to validate an integer textbox.
function CustomValidateIsInt(source, arguments)
{
	arguments.IsValid = isInt( arguments.Value );
}


// Same as VB IsNumeric() function.
function isNumeric( sText )
{
	return !isNaN( sText );
} // EOF IsNumeric()


// Used by ASP.NET CustomValidator controls that need to validate a number textbox.
function CustomValidateIsNumeric(source, arguments)
{
	arguments.IsValid = isNumeric( arguments.Value );
}


// Validates a string is a valid email address.
function isEmailAddress( str )
{
	if( str.replace( ' ', '' ) == '' )
		return false;
		
	var filter=/^.+@.+\..{2,3}$/;
	return (filter.test(str));
}


// Used by ASP.NET CustomValidator controls that need to validate an email address in a textbox.
function CustomValidateEmailAddress(source, arguments)
{
	arguments.IsValid = isEmailAddress( arguments.Value );
}


// Validates a string as a time.
function isTime(timeStr)
{
	// Checks for the following valid time format:
	// HH:mm
	var timePat = /^(\d{2}):(\d{2})$/;
	var matchArray = timeStr.match(timePat); // Is the format OK?
	
	if(matchArray == null )
		return false;

	var hour = parseInt( matchArray[1], 10 );
	var minute = parseInt( matchArray[2], 10 );
	
	if(isNaN(hour) || hour < 0 || hour > 23) // Valid Hour?
		return false;
	
	if(isNaN(minute) || minute < 0 || minute > 59) // Valid Minute?
		return false;
	
	return true; // Yes, it's a time!
}

// Used by ASP.NET CustomValidator controls that need to validate a time.
function CustomValidateTime(source, arguments)
{
	arguments.IsValid = isTime( arguments.Value );
}


// Validates a string as a date.
function isDate(dateStr)
{ 
	// Checks for the following valid date formats: 
	// DD/MM/YYYY DD-MM-YYYY
	// 2 Digit Year pattern.
	// var datePat = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{2}|\d{4})$/; 
	// 4 Digit Year pattern.
	var datePat = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{4})$/; 

	var matchArray = dateStr.match(datePat); // Is the format OK? 
	if (matchArray == null)
	{
		//alert("Date is not in a valid format.") 
		return false; 
	} 
	//month = matchArray[1]; // parse date into variables 
	//day = matchArray[3]; 
	day = matchArray[1];
	month = matchArray[3];
	year = matchArray[4]; 
	if (month < 1 || month > 12)
	{
		// check month range 
		//alert("Month must be between 1 and 12."); 
		return false; 
	} 
	if (day < 1 || day > 31)
	{
		//alert("Day must be between 1 and 31."); 
		return false; 
	} 
	if ((month==4 || month==6 || month==9 || month==11) && day==31)
	{
		//alert("Month "+month+" doesn't have 31 days!") 
		return false;
	} 
	if (month == 2)
	{
		// check for february 29th 
		var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); 
		if (day>29 || (day==29 && !isleap))
		{
			//alert("February " + year + " doesn't have " + day + " days!"); 
			return false; 
		} 
	} 
	return true; // date is valid if we get this far.
}


// Used by ASP.NET CustomValidator controls that need to validate a date.
function CustomValidateDate(source, arguments)
{
	arguments.IsValid = isDate( arguments.Value );
}


// Determines if the value of the ASP.NET control is not an empty string or whitespace.
function isPopulated(source, arguments)
{
	if( trim( arguments.Value ) == '' )
		arguments.IsValid = false;
	else
		arguments.IsValid = true;
}


// Determines if the specified string is null, empty or whitespace.
function isNullOrEmptyOrWhiteSpace( str )
{
	if( str == null )
		return true;
		
	else if( trim( str ) == '' )
		return true;
	
	else
		return false;
}

// Displays the number of bytes in a user friendly format
function filesizeFormat(bytes)
{
	if (Number(bytes)>1073741824) 
		return (bytes/1073741824).toFixed(2)+" Gb";
	else if (Number(bytes)>1048576) 
		return (bytes/1048576).toFixed(2)+" Mb";
	else if (Number(bytes)>1024) 
		return (bytes/1024).toFixed(2)+" Kb";
	else
		return bytes+" bytes";
}

// Displays the number of seconds as Hours Minutes Seconds
function timeFormat(secs)
{
	// Based on code from http://www.math.com/everyone/calculators/calc_source/download.htm
	var hr=Math.floor((secs/3600));
	var hrMod=(secs%3600);
	var min=Math.floor(hrMod/60);
	var minMod=(hrMod%60);
	var sec=Math.floor(minMod);
	var time="";

	if(hr>1)time+=hr+" hours ";
	else if(hr==1)time+=hr+" hour ";

	if(min>1)time+=min+" mins ";
	else if(min==1)time+=min+" min ";

	if(sec>1)time+=sec+" secs";
	else if(sec==1)time+=sec+" sec";
	else if(time=="")time="Less than 1 second";

	return time;
}

// Similar to C# String.Format
function format(str)
{
	if (!str)
		return '';

	for (i = 1; i < arguments.length; i++)
		str = str.replace('{' + (i - 1) + '}', arguments[i]);

	return str;
}

// Add <textarea id="aslDebug"></textarea> to your html to see debug messages
function aslDebugWrite(message){
	var ta=document.getElementById("aslDebug");
	if(ta!=undefined)ta.value+=message+"\n";
}

function aslFader(divId){
	// === PRIVATE FUNCTIONS ===
	function debug(txt){aslDebugWrite("aslFader: "+txt+"\n");}
	
	function nextSlide(){
		try{
			var oldSlide=document.getElementById(divId+"_s"+currentSlide);
			oldSlide.style.zIndex="100";
			
			currentSlide++;
			if(currentSlide==slideCount)currentSlide=0;
			var newSlide=document.getElementById(divId+"_s"+currentSlide);
			newSlide.style.zIndex="90";
			setOpacity(divId+"_s"+currentSlide,100);

			// Smooth fade away...
			var timer=0;
			for(i=96;i>=0;i-=4)
			{window.setTimeout("setOpacity('"+ oldSlide.id +"',"+ i +")",timer);timer+=50;}
		}
		catch(ex){
			debug("nextSlide failed ["+currentSlide+"] "+ex.description)
		}
	}
	
	// === INIT ===
	var slideCount=0;
	var currentSlide=0;
	var holder=document.getElementById(divId);
	if(holder==undefined)debug("holder DIV ["+divId+"] not found!");
	else holder.style.position="relative";

	// === PROPERTIES ===
	this.interval=5000; // Default time between fades (ms)
	
	// === METHODS ===
	this.add=function(imageUrl,linkUrl,text,linkCSS){
		try{
			var newdiv=document.createElement('div');
			newdiv.setAttribute("id",divId+"_s"+slideCount);
			newdiv.style.position="absolute";
			newdiv.style.top="0";
			newdiv.style.left="0";
			newdiv.style.zIndex="0";
			newdiv.style.display="none";

			newdiv.innerHTML = '';
			if(linkUrl!=undefined)newdiv.innerHTML +='<a href="'+linkUrl+'" class="aslFaderImg">';
			newdiv.innerHTML +='<img src="'+imageUrl+'" alt=""/>';
			if(linkUrl!=undefined)newdiv.innerHTML +='</a>';
			if(linkCSS!=undefined)linkCSS=' style="'+linkCSS+'"';
			else linkCSS="";
			if(text!=undefined)newdiv.innerHTML+='<a href="'+linkUrl+'" class="aslFaderText"'+linkCSS+'>'+text+'</a>';
			
			holder.appendChild(newdiv);
			
			slideCount++;
		}
		catch(ex){
			debug("add ["+imageUrl+"] failed "+ex.description);
		}
	}

	this.go=function(){
		if(slideCount==0){
			debug("Slides must be added first!");
			return false;
		}
		try{
			var firstSlide=document.getElementById(divId+"_s"+currentSlide);
			firstSlide.style.zIndex="90";
			firstSlide.style.display="block";
			if(slideCount>1)window.setInterval(nextSlide,this.interval);
		}
		catch(ex){
			debug("go failed "+ex.description);
		}
	}
}//aslFader

// Cross-browser opacity setting... (0-100)
function setOpacity(elemId,opacity) {
	var elem=document.getElementById(elemId);
	elem.style.opacity=(opacity/100);
	elem.style.MozOpacity=(opacity/100);
	elem.style.KhtmlOpacity=(opacity/100);
	elem.style.filter="alpha(opacity="+opacity+")";
	if(opacity==0){elem.style.display="none";}
	if(opacity==100){elem.style.display="block";}
}

function aslImageSwap(newSrc,targetId) {
	var elem = document.getElementById(targetId);
	if(newSrc.indexOf("?")>0) newSrc = newSrc.substring(0,newSrc.indexOf("?"));
	if(elem != null)
		if(elem.tagName == "IMG")
			elem.src = newSrc;
}