/*
    Obtain a reference to the form object
*/

function GetForm(formID)
{
    var objForm = document.forms[formID];
    if (!objForm) eval("objForm = document." + formID);
    return objForm;
}

// Gains scope on a field in a manner that works for all browsers.
function objField(thisForm, uniqueId, fieldSuffix)
{
	eval("var objField=GetForm('" + thisForm + "')['" + uniqueId + fieldSuffix + "'];");
	return objField;
}

/*

Login box homepage.

*/

function LoginboxValid(thisForm, logincodeName, passwordName,  defaultValue )
{
	var objLogincode = objField(thisForm, logincodeName, "");
	var objPasswordcode = objField(thisForm, passwordName, "");
	
	var objStringUtils = new CSoftixUtils();

	//FireFox2 has implemented window.external but does not have this method
	if (window.external)// && typeof(window.external.AutoCompleteSaveForm) != 'undefined')
	{
		try{
		window.external.AutoCompleteSaveForm(myform);
		}catch(e){}
	}

	if (objStringUtils.strTrim(objLogincode.value) == defaultValue)
	{
		objLogincode.focus();
		alert(_messages['loginboxMissingCode']);
		return false;
	}		
	
	// Add the charset validation		
	if (!ValidateCharSet(objLogincode)) return false;
	if (!ValidateCharSet(objPasswordcode)) return false;
	
	return true;	
}


/*

Call by an instance of ValidateButton when performing client-side validation
after the user has clicked the button.

If this function returns TRUE then the form is submitted.

*/
function ValidateButton_IsValid(thisForm, validationArray)
{
	var success = true;
	for (var i=0; i< validationArray.length; i++)
	{	
		eval("success = " + validationArray[i]);
		if (!success) break;
	}
	return success;
}

/*

Each validation control that participates in a validation via the ValidateButton
(i.e. implements IValidationParticipant) must implement a javascript function that
validates its own data and registers itself with the corresponding ValidateButton.

The ValidateButton will then iterate thru its validation array and evaluate each
participating function. If any return false then execution terminates and the form
is not submitted.

*/
function ValidateDataControl(thisForm, idToValidate)
{
	var firstname = objField(thisForm, idToValidate, ":firstname");
	var emailaddress = objField(thisForm, idToValidate, ":email");
	
	if (firstname.value == "")
	{
		firstname.focus();
		alert("Firstname may not be blank.");
		return false;
	}
	
	if (emailaddress.value == "")
	{
		emailaddress.focus();
		alert("Email address may not be blank.");
		return false;
	}
	
	return true;	
}

/*

Validate the Account Controls

*/
function ValidateAccountBasicDetails(thisForm, idToValidate
	, emailClientId             , emailReq 
	, loginClientId             , loginReq
	, passwordClientId          , passwordConfirmClientId   , passwordReq       , passwordLength      
	, salutationClientId        , salutationReq
	, firstNameClientId         , firstNameReq
	, middleNameClientId        , middleNameReq
	, lastNameClientId          , lastNameReq
	, dobDayClientId      
	, dobMonthClientId
	, dobYearClientId           , dobReq
	, homePhoneCCodeClientId    , homeCCodeReq
	, homePhoneACodeClientId    , homeACodeReq
	, homePhoneClientId         , homeReq
	, otherPhoneCCodeClientId   , otherCCodeReq
	, otherPhoneACodeClientId   , otherACodeReq
	, otherPhoneClientId        , otherReq
	, mobilePhoneCCodeClientId  , mobCCodeReq
	, mobilePhoneClientId       , mobReq 
)
{	
	// Get form fields back
	var email			= objField(thisForm, emailClientId, "");
	var login			= objField(thisForm, loginClientId, "");
	var password1		= objField(thisForm, passwordClientId, "");
	var password2		= objField(thisForm, passwordConfirmClientId, "");	
	var salutation		= objField(thisForm, salutationClientId, "");
	var firstName		= objField(thisForm, firstNameClientId, "");
	var middleName		= objField(thisForm, middleNameClientId, "");
	var lastName		= objField(thisForm, lastNameClientId, "");
	var dobDay			= objField(thisForm, dobDayClientId, "");
	var dobMonth		= objField(thisForm, dobMonthClientId, "");
	var dobYear			= objField(thisForm, dobYearClientId, "");
	
	var homePhoneCC     = objField(thisForm, homePhoneCCodeClientId, "");
	var homePhoneAC     = objField(thisForm, homePhoneACodeClientId, "");
	var homePhoneNo     = objField(thisForm, homePhoneClientId, "");

	var mobilePhoneCC	= objField(thisForm, mobilePhoneCCodeClientId, "");
	var mobilePhoneNo	= objField(thisForm, mobilePhoneClientId, "");

	var otherPhoneCC	= objField(thisForm, otherPhoneCCodeClientId, "");
	var otherPhoneAC	= objField(thisForm, otherPhoneACodeClientId, "");
	var otherPhoneNo    = objField(thisForm, otherPhoneClientId, "");	
	
	var objStringUtils = new CSoftixUtils;
	
	//Validate UniCode for all input field for AccountBasicDetails
	if (!ValidateCharSet(email)) return false;
	if (!ValidateCharSet(login)) return false;
	if (!ValidateCharSet(password1)) return false;
	if (!ValidateCharSet(password2)) return false;
	if (!ValidateCharSet(salutation)) return false;
	if (!ValidateCharSet(firstName)) return false;	
	if (!ValidateCharSet(middleName)) return false;
	if (!ValidateCharSet(lastName)) return false;
	if (!ValidateCharSet(dobDay)) return false;
	if (!ValidateCharSet(dobMonth)) return false;
	if (!ValidateCharSet(dobYear)) return false;
	if (!ValidateCharSet(homePhoneCC)) return false;
	if (!ValidateCharSet(homePhoneAC)) return false;
	if (!ValidateCharSet(homePhoneNo)) return false;
	if (!ValidateCharSet(mobilePhoneCC)) return false;
	if (!ValidateCharSet(mobilePhoneNo)) return false;	
	if (!ValidateCharSet(otherPhoneCC)) return false;
	if (!ValidateCharSet(otherPhoneAC)) return false;
	if (!ValidateCharSet(otherPhoneNo)) return false;
	

	// Email Not Blank
	if ((typeof(email) != 'undefined') && (emailReq) && (objStringUtils.strTrim(email.value) == ""))
	{
		email.focus();
		alert(_messages["EmailBlank"]);
		return false;
	}
	
	// Email Invalid
	if ((typeof(email) != 'undefined') && (emailReq) && (!ValidateEmail(email.value)))
	{
		email.focus();
		alert(_messages["EmailInvalid"]);
		return false;
	}

	// Login Code Not Blank
	if ((typeof(login) != 'undefined') && (loginReq) && (objStringUtils.strTrim(login.value) == ""))
	{
		login.focus();
		alert(_messages["LoginBlank"]);
		return false;
	}


	// Password1 Blank
	if ((typeof(password1) != 'undefined') && (passwordReq) && (objStringUtils.strTrim(password1.value) == ""))
	{
		password1.focus();
		alert(_messages["PasswordBlank"]);
		return false;
	}

	// Password1 Min length
	if ( (typeof(password1) != 'undefined') && (passwordReq || password1.value != "") && ( parseInt(passwordLength) > (objStringUtils.strTrim(password1.value)).length ) ) 
	{	
		password1.focus();		
		alert(_messages["PasswordLength"].replace(/\{0\}/g, passwordLength));
		return false;
	}
	

	// Password Confirmation
	if ((typeof(password2) != 'undefined') && (passwordReq) && (objStringUtils.strTrim(password1.value) != objStringUtils.strTrim(password2.value)))
	{
		password2.focus();
		alert(_messages["PasswordUnConfirmed"]);
		return false;
	}


	// Salutation Selected
	if ((typeof(salutation) != 'undefined') && (salutationReq) && (salutation.options.selectedIndex == 0))
	{
		salutation.focus();
		alert(_messages["SalutationUnSelected"]);
    	return false;
	}

	// First Name Blank
	if ((typeof(firstName) != 'undefined') && (firstNameReq) && (objStringUtils.strTrim(firstName.value) == ""))
	{
		firstName.focus();
		alert(_messages["FirstNameBlank"]);
		return false;
	}

	// Middle Name Blank
	if ((typeof(middleName) != 'undefined') && (middleNameReq) && (objStringUtils.strTrim(middleName.value) == ""))
	{
			middleName.focus();
			alert(_messages["MiddleNameBlank"]);
			return false;
	}

	// Last Name Blank
	if ((typeof(lastName) != 'undefined') && (lastNameReq) && (objStringUtils.strTrim(lastName.value) == ""))
	{
			lastName.focus();
			alert(_messages["LastNameBlank"]);
			return false;
	}
	
	// Date of birth day blank
	if  ((typeof(dobDay) != 'undefined') && (dobReq) && (objStringUtils.strTrim(dobDay.value) == ""))
	{
			dobDay.focus();
			alert(_messages["DateOfBirthBlank"]);
			return false;
	}
	
	// Date of birth month blank
	if  ((typeof(dobMonth) != 'undefined') && (dobReq) && (objStringUtils.strTrim(dobMonth.value) == ""))
	{
			dobMonth.focus();
			alert(_messages["DateOfBirthBlank"]);
			return false;
	}
	
	// Date of birth year blank
	if  ((typeof(dobYear) != 'undefined') && (dobReq) && (objStringUtils.strTrim(dobYear.value) == ""))
	{
			dobYear.focus();
			alert(_messages["DateOfBirthBlank"]);
			return false;
	}
	
	// Date of birth valid
	if  ((typeof(dobYear) != 'undefined') && (typeof(dobMonth) != 'undefined') && 
	  (typeof(dobYear) != 'undefined'))
	{
		dobYear.value = objStringUtils.strTrim(dobYear.value);
		dobMonth.value = objStringUtils.strTrim(dobMonth.value);
		dobDay.value = objStringUtils.strTrim(dobDay.value);
		
		if (dobYear.value.length > 0 || dobMonth.value.length > 0 || dobDay.value.length > 0)
		{	
			var invalid = false;
			
			if (IsNumeric(dobYear) && IsNumeric(dobMonth) && IsNumeric(dobDay))
			{
				var day = dobDay.value[0] == '0' ? dobDay.value.substring(1) : dobDay.value;
				var month = dobMonth.value[0] == '0' ? dobMonth.value.substring(1) : dobMonth.value;
				var year = dobYear.value;
				
				if (objStringUtils.blnIsDate(year, month, day)) 
				{//months: 0 - 11
					var dobDate = new Date(year, month - 1, day);
					//not future birth?
					if (objStringUtils.CompareDates(dobDate, new Date()) < 0)
					{
						// >= 1900
						if (objStringUtils.CompareDates(dobDate, new Date(1900, 0, 1)) >= 0)
						{
							//OK
						}
						else
						{
							invalid = true;
						}
					}
					else
					{
						invalid = true;
					}
				}
				else
				{
					invalid = true;
				}
			}
			else
			{
				invalid = true;
			}
			if (invalid)
			{
				dobDay.focus();
				alert(_messages["DateOfBirthInvalid"]);
				return false;
			}
		}
	}	

	// Validate home phone.
	if ( !IsValidNumber(homePhoneCC, homeCCodeReq, "PhoneCountryCodeBlank", "HomePhoneNonNumeric" ))
			return false;

	if ( !IsValidNumber(homePhoneAC, homeACodeReq, "PhoneAreaCodeBlank", "HomePhoneNonNumeric" ))
			return false;

	if ( !IsValidNumber(homePhoneNo, homeReq, "HomePhoneBlank", "HomePhoneNonNumeric" ))
			return false;


	// Validate mobile phone	
	if ( !IsValidNumber(mobilePhoneCC, mobCCodeReq, "PhoneCountryCodeBlank", "MobilePhoneNonNumeric" ))
			return false;		

	if ( !IsValidNumber(mobilePhoneNo, mobReq, "MobilePhoneBlank", "MobilePhoneNonNumeric" ))
			return false;			


	// Validate Phone Other.	
	if ( !IsValidNumber(otherPhoneCC, otherCCodeReq, "PhoneCountryCodeBlank", "OtherPhoneNonNumeric" ))
			return false;
	
	if ( !IsValidNumber(otherPhoneAC, otherACodeReq, "PhoneAreaCodeBlank", "OtherPhoneNonNumeric" ))
			return false;
	
	if ( !IsValidNumber(otherPhoneNo, otherReq, "OtherPhoneBlank", "OtherPhoneNonNumeric" ))
			return false;
			
	return true;
}	
	
function ValidateAccountCheckBox(thisForm, idToValidate)
{
	return true;
}

function ValidateAccountRadioButtons(thisForm, idToValidate)
{
	return true;
}

function ValidateAccountUserPrefs(thisForm, idToValidate)
{
	return true;
}

function ValidateEmail(emailAddress)
{
	var regex = new RegExp(RegExp.EmailPattern);
	return regex.test(emailAddress);
}

function ValidateCharSet(obj)
{
	var regex = new RegExp(RegExp.ValidCharSetPattern);		
	
	if (obj != null && obj != '')
	{		
		if (!regex.test(obj.value))
		{
			obj.focus();
			alert(_messages['InvalidCharSet']);
			return false;
		}

		if (!ForbiddenCharsCheck(obj))
			return false;		
	}

	return true;
}


function ForbiddenCharsCheck(obj)
{
	var regex = new RegExp(RegExp.ForbiddenCharsPattern);		

	if (regex.test(obj.value))
	{
		obj.focus();
		alert(_messages['ForbiddenChars']);	
		return false;
	}		
	return true;
}

function ValidatePhone(CC, AC, N, phoneCCVisible, phoneACVisible)
{	
	var number = "";
	var objStringUtils = new CSoftixUtils;	

	if ((typeof(CC) != 'undefined') && (typeof(CC.value) != 'undefined') && (phoneCCVisible))
	{	
		CC.value = objStringUtils.CCStripSpaces(CC.value);
		number += CC.value;
	}

	if ((typeof(AC) != 'undefined') && (typeof(AC.value) != 'undefined') && (phoneACVisible))
	{
		AC.value = objStringUtils.CCStripSpaces(AC.value);
		number += AC.value;
	}

	if (typeof(N.value) != 'undefined')
	{
		N.value = objStringUtils.CCStripSpaces(N.value);
		number += N.value;
	}
	
    var numberReg = "^[0-9]*$";
    var regex = new RegExp(numberReg);

    return regex.test(number);
}

/*
ShowTickets.aspx Page 
*/

// Validates that a ticket selection has been made and that it is within the defined
// limites - up to 4 ptypes and less than pcat's max tickets.
function TicketSelectorValid(thisForm, uniqueID)
{
	if (typeof(ticketSelector) == 'undefined' || !ticketSelector)
	{
		return false;
	}
	
	var allTickets = new Tickets(ticketSelector.maxTickets, false, null, ticketSelector.PriceTypeRules);
	var priceTypesValid = true;
	
	var allPasswordsAllocatedTo = true;
	
	for (var i = 0; i < ticketSelector.ticketLimits.length; i++)
	{
		var div = document.getElementById('PriceTypes_' + i);
		var ticketContainers = CreateTicketContainersForPriceTypes(ticketSelector.ticketLimits[i]);
		var thisPasswordAllocatedTo = false;
		var hasOtherPurchase = false;
		var requiresOtherPurchaseTickets = null;

		// Loop through the price types until there are no more price types.
		ForEachTicketPriceType(div, function(objPtype, objTickets)
		{
			var number = parseInt(objTickets.options[objTickets.options.selectedIndex].value);
			var priceType = objPtype.value;
		
			// Add the tickets to the total first, then add to the entitlement specific tickets
			// object.  The first will fail if too many tickets are selected in total, the second
			// will fail if too many tickets are selected for a group of price types belonging to
			// a single entitlement.
			if (number > 0)
			{
			   if (!allTickets.Add(priceType, number) || !ticketContainers[priceType].Add(priceType, number))
			    {
				    priceTypesValid = false;
				    return false;
			    }
			
			    if (ticketContainers[priceType].RequiresOtherPurchase)
			    {
			        requiresOtherPurchaseTickets = ticketContainers[priceType];
			    }
			    else
			    {
			        hasOtherPurchase = true;
			    }
			
			    thisPasswordAllocatedTo = true;
		    }
		});

		if (!priceTypesValid) return false;
		
		if (requiresOtherPurchaseTickets != null && !hasOtherPurchase)
		{
		    alert(_messages["ShowTicketsOtherPriceTypeRequired"].replace(/\{0\}/g, 
		        requiresOtherPurchaseTickets.PriceTypes.join(", ")));
		    return false;
		}
		
		if (!thisPasswordAllocatedTo) allPasswordsAllocatedTo = false;
	}
	
	if (allTickets.ToString() == '')
	{
		alert(_messages["NoTickets"]);
		return false;
	}
	
	if (!allPasswordsAllocatedTo)
	{
	    var confirmationMessage = ticketSelector.confirmNotAllPasswordsAllocatedTo;	    
	    if (typeof(confirmationMessage) == 'undefined' || !confirmationMessage || confirmationMessage == '')
	    {
	        confirmationMessage = _messages["ShowTicketsConfirmNotAllPasswordAllocatedTo"];
	    }
	    if (!confirm(confirmationMessage)) return false;
	}

	if (!allTickets.ValidateRules()) return false;

	return true;
}

// Creates an object that can be used to look up a Ticket object by price type.
// One ticket object is created for each entitlement in priceTypeGroups.
function CreateTicketContainersForPriceTypes(priceTypeGroups)
{
	var ticketContainers = {};
	
	for (var i = 0; i < priceTypeGroups.length; i++)
	{
		var priceTypes = [];
		
		for (var priceType in priceTypeGroups[i].priceTypes)
		{
			priceTypes[priceTypes.length] = priceTypeGroups[i].priceTypes[priceType];
		}
	
		var tickets = new Tickets(priceTypeGroups[i].limit, 
		priceTypeGroups[i].requiresOtherPurchase, priceTypes, null);
		
		for (var priceType in priceTypeGroups[i].priceTypes)
		{
			ticketContainers[priceType] = tickets;
		}
	}
	
	return ticketContainers;
}

function DeliveryMethodValid(thisForm, uniqueId)
{
	var isValid = true;
	
	// Check delivery optios selected.
    var objDelivery = objField(thisForm, uniqueId, "$deliverymethod");
	if (!IsRadioSelected(objDelivery))
	{
		alert(_messages["NoDelivery"]);
		isValid = false;
	}
	return isValid;
}

// Check if a group of radio buttons has a choice selected.
function IsRadioSelected(objRadios)
{
	if (typeof(objRadios) == 'undefined' || objRadios == null)
	{
		return false;
	}
	if (typeof(objRadios.length) != 'undefined')
	{
		for (var i=0; i<objRadios.length; i++)
		{
			if (objRadios[i].checked) return true;
		}
		return false;
	}
	return objRadios.checked;
}

// This object captures users ticket selection. checks it is within limits (Add()) and 
// formats valid selection into single string (ToString()).
function Tickets(maxTickets, requiresOtherPurchase, priceTypes, priceTypeRules)
{
 this.MaxTickets = maxTickets;
 this.RequiresOtherPurchase = requiresOtherPurchase;
 this.PriceTypes = priceTypes;
 this.Selection = {};
 this.Count = 0;     // Current ticket count.
 this.PriceTypeCount = 0;
 
 this.Add = TicketsAdd;
 this.ToString = TicketsToString;
 this.PriceTypeRules = priceTypeRules;
 this.ValidateRules = TicketsValidateRules;
}


function TicketsAdd(ptype, number)
{
	if (this.Count + number > this.MaxTickets)
	{
		// Alert max tickets for price category. (replaces {0} with max tickets)
		if (this.PriceTypes == null || this.PriceTypes.length == 0)
		{
			alert(_messages["MaxTickets"].replace(/\{0\}/g, this.MaxTickets));
		}
		else
		{
			alert(
				_messages["MaxEntitlementTickets"]
					.replace(/\{0\}/g, this.MaxTickets)
					.replace(/\{1\}/g, this.PriceTypes.join(", ")));
		}
		return false;
	}
	
	if (!this.Selection[ptype])
	{
		if (this.PriceTypeCount >= 4)
		{
			alert(_messages["MaxPTypes"]);
			return false;
		}
		
		this.Selection[ptype] = 0;
		this.PriceTypeCount++;
	}
	
	this.Count += number;
	this.Selection[ptype] += number;
	
	return true;
}

// Check the tickets collection against the rules
function TicketsValidateRules() {
    for (var i = 0; i < this.PriceTypeRules.length; i++) {
        var countParent = 0, countChild = 0;
        for (var ptype in this.Selection) {
            if (this.PriceTypeRules[i].parentPriceTypes[ptype] != null) countParent += this.Selection[ptype];
            if (this.PriceTypeRules[i].childPriceTypes[ptype] != null) countChild += this.Selection[ptype];
        }
        var ruleMulitples = Math.ceil(countChild / this.PriceTypeRules[i].maxChild);
        if (ruleMulitples * this.PriceTypeRules[i].minParent > countParent) {
            var parentPriceTypes = [];
            for (var ptype in this.PriceTypeRules[i].parentPriceTypes) {
                parentPriceTypes[parentPriceTypes.length] = this.PriceTypeRules[i].parentPriceTypes[ptype];
            }
            var childPriceTypes = [];
            for (var ptype in this.PriceTypeRules[i].childPriceTypes) {
                childPriceTypes[childPriceTypes.length] = this.PriceTypeRules[i].childPriceTypes[ptype];
            }
            alert(
    _messages["ShowTicketsRuleValidation"]
     .replace(/\{0\}/g, countChild)
     .replace(/\{1\}/g, childPriceTypes.join(", "))
     .replace(/\{2\}/g, (ruleMulitples * this.PriceTypeRules[i].minParent))
     .replace(/\{3\}/g, parentPriceTypes.join(", ")));
            return false;
        }
    }
    return true;
}


function TicketsToString()
{
	var buffer = [];
	
	for (var ptype in this.Selection)
	{
		buffer[buffer.length] = ptype + this.Selection[ptype];
	}

	return buffer.join(",");
}


function RestrictDeliveryForSelectedPriceTypes(thisForm, uniqueId, dTypeControlID)
{
	if (typeof(_dtypeRestrictions) == 'undefined' || _dtypeRestrictions.length == 0)
	{
		return;
	}
	
	EnableDeliveryTypes(thisForm, dTypeControlID);
	
	var selectedPriceTypes = [];
	
	// Loop throught the price types until there are no more price types.
	ForEachTicketPriceType(document, function(objPtype, objTickets)
	{
		if (parseInt(objTickets.options[objTickets.selectedIndex].value) > 0)
		{
			selectedPriceTypes[selectedPriceTypes.length] = objPtype.value;
		}
	});
	
	if (selectedPriceTypes.length > 0)
	{
		DisableDeliveryTypes(thisForm, dTypeControlID, selectedPriceTypes);
	}
	
	// Make sure that now disabled delivery types aren't highlighted.
	highlightCurrentDeliveryMethod('', 'altTRrow');
}

function ForEachTicketPriceType(context, priceTypeHandler)
{
	$("input[id*='uiPriceType']", context).each(function()
		{
			var priceTypeElement = this;
			var quantityElement = $("#" + this.id.substring(0, this.id.length - 11) + 'uiQuantity').get(0);
			
			if (priceTypeHandler(priceTypeElement, quantityElement) == false)
			{
				return false;	// Returning false exits the each loop
			}
		});
}

/* 
	This functions will iterate through all available delivery methods in the current form
	and re-enable them all.
*/
function EnableDeliveryTypes(thisForm, uniqueId)
{
	// retrieve delivery method radio collection object
	
	// NB after async post back uniqueid is empty so use a like comparisson to find control
    var objDelivery = $("input[type='radio'][id*='deliverymethod']"); 

	// validate that the object is defined in the form
	if (typeof(objDelivery) != 'undefined')
	{
		// loop through available selections and enable them 
		for (var i = 0; i < objDelivery.length; i++)
		{
			objDelivery[i].disabled = false;
		}	
	}
}

function DisableDeliveryTypes(thisForm, uniqueId, selectedPriceTypes)
{
	// Check delivery options selected.
	
	// NB after async post back uniqueid is empty so use a like comparisson to find control
    var objDelivery = $("input[type='radio'][id*='deliverymethod']"); 
    
    // validate that the delivery object is defined
	if (typeof(objDelivery) != 'undefined')
	{	
		// loop through restricted prices and disable only for the requested price type
		for (var i = 0; i < _dtypeRestrictions.length; i++)
		{
			if (Array.contains(selectedPriceTypes, _dtypeRestrictions[i][0]))
			{
				for (var k = 0; k < _dtypeRestrictions[i][1].length; k++)
				{
					for (var j = 0; j < objDelivery.length; j++)
					{
						if (objDelivery[j].value == _dtypeRestrictions[i][1].charAt(k))
						{
							objDelivery[j].checked = false;
							objDelivery[j].disabled = true;
							break;
						}
					}			
				}
			}
		}
	}
}

/* 
	This functions will validate that the delivery method is not disabled prior to selecting it.
	Primarily used for the onclick on the delivery method name.
	
*/
function SelectDeliveryMethod(thisForm, uniqueId, dtypePos)
{
	// Check delivery optios disabled or not before allowing the selection of it
    var objDelivery = objField(thisForm, uniqueId, dtypePos);

	if (typeof(objDelivery) != 'undefined' && !objDelivery.disabled)
	{
		objDelivery.checked = true;
    }
}

/*
    This function (called only when hold control is displayed) asks user
    to agree to losing hold information when clicking back button - if they
    have entered any
*/
function showTicketsBackButtonClick(thisForm, holdQtyID, backUrl)
{
    var objHoldQtyControl = objField(thisForm, holdQtyID, "");
	if (typeof(objHoldQtyControl) != 'undefined') 
	{
	    if (objHoldQtyControl.selectedIndex > 0)
	    {
	        if (window.confirm(_messages["ShowTicketsConfirmLoseHoldInfo"]))
	        {
	            document.location.href = backUrl;
	        }
	    }
	    else
	    {
	        document.location.href = backUrl;
	    }
	}
	else
	{
	    document.location.href = backUrl;
	}
	return false;
}

/*

Performance Selector Control

*/

function CanChangeVenue(thisForm, venuename)
{
    var uiDropdown = objField(thisForm, venuename, "");

    if (uiDropdown.options[uiDropdown.options.selectedIndex].value == '') 
    {
	    alert(_messages["VenueSoldout"]);
	    for (var i=0; i < uiDropdown.options.length; i++)
	    {
		    if (uiDropdown.options[i].value == _currentVenue)
		    {
			    uiDropdown.options.selectedIndex = i;
	        }
	    }
	    return false;
    }

    return true;	
}

function CanChangePerformance(thisForm, name)
{
    var uiDropdown = objField(thisForm, name, "");
    if (uiDropdown.options[uiDropdown.options.selectedIndex].value == '') 
    {
	    alert(_messages["PerformanceSoldout"]);
	    for (var i=0; i < uiDropdown.options.length; i++)
	    {
		    if (uiDropdown.options[i].value == _currentPerf)
		    {
			    uiDropdown.options.selectedIndex = i;
		    }
	    }
	    return false;
    }
    return true;		
}

/*
*	BASKET RELATED FUNCTIONS
*/
var gblnProcessing = false;
var gobjBasketPurchasingWindow;

// VerifyPurchase.ascx - form validation.
function blnBasketOffersValidate(thisForm, idToValidate)
{
	var objRef;	

	if (gblnProcessing) 
	{
		alert(_messages["PurchaseAlreadyClicked"]);
		return false;
	}

	objStringUtils = new CSoftixUtils;
	objRef = objField(thisForm, idToValidate, ":chkObstr");

	if (objRef != null && !objRef.checked) 
	{
		objRef.focus();
		alert(_messages["BasketObstructedView"]);
		return false;
	}

	return true;
}

function blnRemoveOffer(dibsid, thisForm, fieldName)
{
	if (confirm(_messages["PurchaseRemoveOffer"]))
	{
	    var removeOffer = objField(thisForm, fieldName, "");
		removeOffer.value = dibsid;
		return true;
	}

	return false;
}

function AutoReducedAlert(dibsid, thisForm, fieldName, performance, venue, perfDate, tickets)
{
	var message = _messages["AutoReducedTicketsConfirm"];
	var detail = "\n\n";
	if (tickets.length != 'undefined')
	{
		for(i=0; i<tickets.length; i++)
		{
			detail += "\t" + tickets[i] + "\n";
		}
	}
	detail += "\n\t" + performance + "\n\t" + perfDate + "\n\t" + venue + "\n\n";
	if (window.confirm(message.replace(/\{0\}/g, detail)))
	{
		return false;
	} 
	else 
	{
	    var removeOffer = objField(thisForm, fieldName, "");
		removeOffer.value = dibsid;
		return true;
	}
}

// CreditCardDetails.ascx - form validation.
function blnCreditCardDetailsValidate(thisForm, idToValidate, cardTypeContainerID)
{
	if (gblnProcessing) 
	{
		alert(_messages["PurchaseAlreadyClicked"]);
		return false;
	}

	objStringUtils = new CSoftixUtils;

	objtxtCCNumberRef = objField(thisForm, idToValidate, "$uiCardNumber");
	objtxtCCCvcRef = objField(thisForm, idToValidate, "$uiCardCvc");
	objtxtCCNameRef = objField(thisForm, idToValidate, "$uiCardName");
	objselCCExpiryMonthRef = objField(thisForm, idToValidate, "$uiExpiryMonth");
	objselCCExpiryYearRef = objField(thisForm, idToValidate, "$uiExpiryYear");
	objhdnMonthRef = objField(thisForm, idToValidate, "$uiHiddenMonth");
	objhdnYearRef = objField(thisForm, idToValidate, "$uiHiddenYear");
	
	//Unicode Validation
	if (!ValidateCharSet(objtxtCCNumberRef)) return false;
	if (!ValidateCharSet(objtxtCCCvcRef)) return false;
	if (!ValidateCharSet(objtxtCCNameRef)) return false;
	if (!ValidateCharSet(objselCCExpiryMonthRef)) return false;
	if (!ValidateCharSet(objselCCExpiryYearRef)) return false;
	
	// Validate CC Details if not a 0 value trans
	if (objtxtCCNumberRef.value == '')
	{					
		objtxtCCNumberRef.focus();
		alert(_messages["CreditCardNumber"]);
		return false;
	}
		
	objtxtCCNumberRef.value = objStringUtils.CCStripSpaces(objtxtCCNumberRef.value)
															
	if (!objStringUtils.CCMod10Check(objtxtCCNumberRef.value))
	{
		objtxtCCNumberRef.focus();
		alert(_messages["CreditCardNumberInvalid"]);

		return false;
	}

	var cardType = $('#' + cardTypeContainerID).find('input:radio:checked,option:selected').val();

	if (cardType && !ccfCreditCardTypes[cardType].pattern.test(objtxtCCNumberRef.value))
	{
		objtxtCCNumberRef.focus();

		if (_messages.CreditCardInvalidTypeNumber && _messages.CreditCardInvalidTypeNumber[cardType])
		{
			alert(_messages.CreditCardInvalidTypeNumber[cardType]);
		}
		else
		{
			alert(_messages["CreditCardNumberInvalid"]);
		}
		return false;
	}
	
	if (objtxtCCCvcRef != null)
	{
		if (objtxtCCCvcRef.value == '')
		{					
			objtxtCCCvcRef.focus();
			alert(_messages["CreditCardCvc"]);
			return false;
		}
						
		objtxtCCCvcRef.value = objStringUtils.CCStripSpaces(objtxtCCCvcRef.value);
		
		var regex = new RegExp("^[0-9]{3,4}$");    									
		if (!regex.test(objtxtCCCvcRef.value))
		{
			objtxtCCCvcRef.focus();
			alert(_messages["CreditCardCvcInvalid"]);

			return false;
		}
	}
												
	if (objtxtCCNameRef.value == '')
	{
		objtxtCCNameRef.focus();
		alert(_messages["CreditCardName"]);
		return false;
	}

	strSelectedMonth = objselCCExpiryMonthRef.options[objselCCExpiryMonthRef.options.selectedIndex].value;
	strSelectedYear = objselCCExpiryYearRef.options[objselCCExpiryYearRef.options.selectedIndex].value;
							
	if (objselCCExpiryMonthRef.options.selectedIndex <= 0)
	{
		objselCCExpiryMonthRef.focus();
		alert(_messages["CreditCardMonth"]);
		return false;
	}
		
	if (objselCCExpiryYearRef.options.selectedIndex <= 0)
	{
		objselCCExpiryYearRef.focus();
		alert(_messages["CreditCardYear"]);

		return false;
	}
						
	strPassedMonth = objhdnMonthRef.value;
	strPassedYear = objhdnYearRef.value;

	if ((parseInt(strSelectedYear,10) < parseInt(strPassedYear,10)) || 
	    ((parseInt(strSelectedYear,10) == parseInt(strPassedYear,10)) && 
	    parseInt(strSelectedMonth,10) < parseInt(strPassedMonth,10)))
	{
		alert(_messages["CreditCardExpiryDate"]);
		return false;
	}		
	
	return true;
}


// VerifyShowAttributes.ascx - form validation.
function blnVerifyShowAttributesValidate(thisForm, idsToValidate)
{	
	if (gblnProcessing) 
	{
		alert(_messages["PurchaseAlreadyClicked"]);
		return false;
	}

	// Iterate through all the show attribute checkboxes on the page
	for (var i = 0; i < idsToValidate.length; i++)
	{
		var objRef;
		objStringUtils = new CSoftixUtils;

		objRef = objField(thisForm, idsToValidate[i], "");

		if (!objRef.checked) 
		{
			objRef.focus();
			alert(_messages["ShowConditionAgreed"]);
			return false;
		}
	}

	return true;	
}

// VerifyPurchase.ascx - form validation.
function blnAgreeToPurchaseValidate(thisForm, idToValidate)
{
	var objRef;

	if (gblnProcessing) 
	{
		alert(_messages["PurchaseAlreadyClicked"]);
		return false;
	}

	objStringUtils = new CSoftixUtils;
	objRef = objField(thisForm, idToValidate, "$uiAgree");

	if (!objRef.checked) 
	{
		objRef.focus();
		alert(_messages["PurchaseAgreed"]);
		return false;
	}

	gblnProcessing = true;
	gobjBasketPurchasingWindow = OpenWindow("PurchasePopup.aspx", 400, 260);

	return true;
}

function PopUpWindow(strURL, intWidth, intHeight, strName)
{
	OpenWindow(strURL, intWidth, intHeight, 'windowPopup');
}	

function OpenWindow(strURL, intWidth, intHeight, strName)
{
	var newWindows = null;
	strName =  strName || 'popWindow';	//Trick to replace deault to popwindow if strName is not supplied

	if (screen == null)
	{
		if (document.all || document.getElementById)
		{
		    newWindows = window.open(strURL, strName,
			    "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,copyhistory=no,width=" + intWidth + ",height=" + intHeight);		
		}
		else
		{
		    // NN4	
		    newWindows = window.open(strURL, strName,
			    "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,copyhistory=no,width=" + intWidth + ",height=" + intHeight);
		}
	}
	else	//Position in centre of screen if possible
	{
		if (document.all || document.getElementById)
		{
		    newWindows = window.open(strURL, strName,
			    "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,copyhistory=no,width=" + intWidth + ",height=" + intHeight + ',left=' + (screen.width-intWidth)/2 + ',top=' + (screen.height-intHeight)/2);
		}
		else
		{
		    // NN4
		    newWindows = window.open(strURL, strName,
			    "toolbar=no,location=no,directories=no,status=yes,menubar=no,scrollbars=yes,resizable=yes,copyhistory=no,width=" + intWidth + ",height=" + intHeight + ',left=' + (screen.width-intWidth)/2 + ',top=' + (screen.height-intHeight)/2);
		}
	}
	
	// IE6 doesn't like it when we try to set focus!
	try
	{
		newWindows.focus();
	}
	catch (e) { }
	
	return newWindows;
}

function CloseWindow()
{
	if (gobjBasketPurchasingWindow)
	{
		// IE6 doesn't like it when we try to set focus!
		try
		{
			gobjBasketPurchasingWindow.close();
		}
		catch (e) { }
	}
}

/*

Centralised user alert messages. This needs to be externalised and made multilingual.

*/
var _messages = new Messages();

/*

AccountAddressDetails User Control

*/

function AddressAsAbove(thisForm, uniqueId)
{
	var objCheckbox = objField(thisForm, uniqueId, "$chkAsAbove");

	var objAddressApmt = objField(thisForm, uniqueId, "$tbAddressAppartment");
	var objAddressHouse = objField(thisForm, uniqueId, "$tbAddressHouse");
	var objAddressLine1 = objField(thisForm, uniqueId, "$tbAddressLine1");
	var objAddressLine2 = objField(thisForm, uniqueId, "$tbAddressLine2");
	var objAddressCity = objField(thisForm, uniqueId, "$tbAddressCity");
	var objAddressState = objField(thisForm, uniqueId, "$selAddressState");
	var objAddressStateOther = objField(thisForm, uniqueId, "$tbAddressStateOther");
	var objAddressCountry = objField(thisForm, uniqueId, "$ddlAddressCountry");
	var objAddressCountryOther = objField(thisForm, uniqueId, "$tbAddressCountryOther");	
	var objAddressPostCode = objField(thisForm, uniqueId, "$tbAddressPostcode");
	
	if (typeof(objCheckbox.disabled) != 'undefined')
	{
		var disableField = false;
		if (objCheckbox.checked) disableField = true;
		
		if (typeof(objAddressApmt) != 'undefined') objAddressApmt.disabled = disableField;
		if (typeof(objAddressHouse) != 'undefined') objAddressHouse.disabled = disableField;
		if (typeof(objAddressLine1) != 'undefined') objAddressLine1.disabled = disableField;
		if (typeof(objAddressLine2) != 'undefined') objAddressLine2.disabled = disableField;
		if (typeof(objAddressCity) != 'undefined') objAddressCity.disabled = disableField;
		if (typeof(objAddressState) != 'undefined') objAddressState.disabled = disableField;
		if (typeof(objAddressStateOther) != 'undefined') objAddressStateOther.disabled = disableField;
		if (typeof(objAddressCountry) != 'undefined') objAddressCountry.disabled = disableField;
		if (typeof(objAddressCountryOther) != 'undefined') objAddressCountryOther.disabled = disableField;
		if (typeof(objAddressPostCode) != 'undefined') objAddressPostCode.disabled = disableField;
	}
}

function ErrorMessageWithPrefix(contentIdPrefix, contentId)
{	
	if (contentIdPrefix.length != 0 && _messages[contentIdPrefix + contentId] != null)
	{
		return _messages[contentIdPrefix + contentId];
	}
	else
	{
		return _messages[contentId];
    }
}


// Address user control field validation function.
function ValidateAddress(
    thisForm, 
    uniqueId, 
    AddressLine1Id          , line1Req, 
    AddressLine2Id          , line2Req, 
    AddressAppartmentId     , apmtReq, 
    AddressHouseId          , houseReq, 
    AddressCityId           , cityReq, 
    AddressStateId          , stateReq, 
    AddressStateOtherId,
    AddressCountryId,        
    AddressCountryOtherId   , countryReq,
    AddressPostcodeId       , postCodeReq, 
    contentIdPrefix)
{	    
	var isValid = true;
	var objCheckbox = objField(thisForm, uniqueId, "$chkAsAbove");
	if ((typeof(objCheckbox) != 'undefined' && !objCheckbox.checked) || 
	    typeof(objCheckbox) == 'undefined')
	{
		var objLine1 = objField(thisForm, AddressLine1Id, "");
		var objLine2 = objField(thisForm, AddressLine2Id, "");
		var objAppartment = objField(thisForm, AddressAppartmentId, "");
		var objHouse = objField(thisForm, AddressHouseId, "");		
		var objCity = objField(thisForm, AddressCityId, "");
		var objState = document.getElementById(AddressStateId);
		var objStateOther = objField(thisForm, AddressStateOtherId, "");		
		var objCountry = objField(thisForm, AddressCountryId, "");
		var objCountryOther = objField(thisForm, AddressCountryOtherId, "");
		var objPostCode = objField(thisForm, AddressPostcodeId, "");
		
		// Unicode validation
		if (!ValidateCharSet(objLine1)) return false;
		if (!ValidateCharSet(objLine2)) return false;
		if (!ValidateCharSet(objAppartment)) return false;
		if (!ValidateCharSet(objHouse)) return false;
		if (!ValidateCharSet(objCity)) return false;
		if (!ValidateCharSet(objState)) return false;
		if (!ValidateCharSet(objStateOther)) return false;		
		if (!ValidateCharSet(objCountry)) return false;
		if (!ValidateCharSet(objCountryOther)) return false;
		if (!ValidateCharSet(objPostCode)) return false;
				
		if (typeof(objLine1) != 'undefined' && line1Req && objLine1.value == "")
		{
			alert(ErrorMessageWithPrefix(contentIdPrefix, "AddressLine1Error"));
			objLine1.focus();
			return false;
		}

		if (typeof(objLine2) != 'undefined' && line2Req && objLine2.value == "")
		{
			alert(ErrorMessageWithPrefix(contentIdPrefix, "AddressLine2Error"));
			objLine2.focus();
			return false;
		}

		if (typeof(objAppartment) != 'undefined' && apmtReq && objAppartment.value == "")
		{
			alert(ErrorMessageWithPrefix(contentIdPrefix, "AddressAppartmentError"));
			objAppartment.focus();
			return false;
		}
		
		if (typeof(objHouse) != 'undefined' && houseReq && objHouse.value == "")
		{
			alert(ErrorMessageWithPrefix(contentIdPrefix, "AddressHouseError"));
			objHouse.focus();
			return false;
		}
		
		if (typeof(objCity) != 'undefined' && cityReq && objCity.value == "")
		{
			alert(ErrorMessageWithPrefix(contentIdPrefix, "AddressCityError"));
			objCity.focus();
			return false;
		}

        if (objState != null && objState.style.display != 'none' && stateReq &&
                      objState.value == "") {
            alert(ErrorMessageWithPrefix(contentIdPrefix, "AddressStateError"));
            objState.focus();
            return false;
        }


		
		if (typeof(objStateOther) != 'undefined' && objStateOther.style.display != 'none' && 
		    stateReq && objStateOther.value == "")
		{
			alert(ErrorMessageWithPrefix(contentIdPrefix, "AddressStateError"));
			objStateOther.focus();	
			return false;
		}
		
		if (typeof(objCountry) != 'undefined')
		{
			var countryValue = objCountry.options[objCountry.selectedIndex].value;

            if (countryReq && countryValue == '')
            {
				alert(ErrorMessageWithPrefix(contentIdPrefix, "AddressCountryError"));
				objCountry.focus();
				return false;            
            }
			else if (countryReq && countryValue == 'other' && objCountryOther.value == "")
			{
				alert(ErrorMessageWithPrefix(contentIdPrefix, "AddressCountryError"));
				objCountryOther.focus();
				return false;
			}
		}
		
		if (typeof(objPostCode) != 'undefined' && postCodeReq && objPostCode.value == "")
		{
			alert(ErrorMessageWithPrefix(contentIdPrefix, "AddressPostCodeError"));
			objPostCode.focus();
			return false;
		}
	}
	// copy the state dropdown value into the state textbox if needed.
    if (objState != null && typeof (objStateOther) != 'undefined' && objState.value != "" && objState.style.display != 'none') {
        objStateOther.value = objState.value;
    }
	
	return true;
}

// Address user control field validation function.
function ValidateAddress_nl(thisForm, uniqueId, line1Req, apmtReq, houseReq, cityReq, stateReq, 
    countryReq, postCodeReq)
{
	var isValid = true;
	
	var objCheckbox = objField(thisForm, uniqueId, ":asabove");
	if ((typeof(objCheckbox) != 'undefined' && !objCheckbox.checked) || 
	    typeof(objCheckbox) == 'undefined')
	{
		var objLine1 = objField(thisForm, uniqueId, ":line1");
		var objHouse = objField(thisForm, uniqueId, ":house");
		var objApmt = objField(thisForm, uniqueId, ":apmt");
		var objCity = objField(thisForm, uniqueId, ":city");
		var objState = objField(thisForm, uniqueId, ":state");
		var objCountry = objField(thisForm, uniqueId, ":country");
		var objCountryOther = objField(thisForm, uniqueId, ":countryother");
		var objPostCode = objField(thisForm, uniqueId, ":postcode");

		// Unicode validation
		if (!ValidateCharSet(objLine1)) return false;
		if (!ValidateCharSet(objHouse)) return false;
		if (!ValidateCharSet(objApmt)) return false;
		if (!ValidateCharSet(objCity)) return false;
		if (!ValidateCharSet(objState)) return false;
		if (!ValidateCharSet(objCountry)) return false;
		if (!ValidateCharSet(objCountryOther)) return false;
		if (!ValidateCharSet(objPostCode)) return false;

		if (typeof(objLine1) != 'undefined' && line1Req && objLine1.value == "")
		{
			alert(_messages["AddressLine1Error"]);
			objLine1.focus();
			return false;
		}

		if (typeof(objHouse) != 'undefined' && houseReq && objHouse.value == "")
		{
			alert(_messages["AddressHouseError"]);
			objHouse.focus();
			return false;
		}

		if (typeof(objApmt) != 'undefined' && apmtReq && objApmt.value == "")
		{
			alert(_messages["AddressApartmentError"]);
			objApmt.focus();
			return false;
		}

		if (typeof(objCity) != 'undefined' && cityReq && objCity.value == "")
		{
			alert(_messages["AddressCityError"]);
			objCity.focus();
			return false;
		}

		if (typeof(objState) != 'undefined' && stateReq && objState.value == "")
		{
			alert(_messages["AddressStateError"]);
			objState.focus();
			return false;
		}

		if (typeof(objCountry) != 'undefined')
		{
			var countryValue = objCountry.options[objCountry.selectedIndex].value;
			
			if (countryReq && countryValue == 'other' && objCountryOther.value == "")
			{
				alert(_messages["AddressCountryError"]);
				objCountryOther.focus();
				return false;
			}
		}
		
		if (typeof(objPostCode) != 'undefined' && postCodeReq && objPostCode.value == "")
		{
			alert(_messages["AddressPostCodeError"]);
			objPostCode.focus();
			return false;
		}
	}
	return true;
}

/*

Utility Class

*/

function CSoftixUtils() {

	//Methods
	this.IsMSBrowser = IsMSBrowser;				//Check if the browser is Internet Explorer
	this.strFormatNumber = strFormatNumber;		//Format a number to specified number of places
	this.strFormatDate = strFormatDate;			//Format a date: dd mmm yyyy 
	this.strTrim = strTrim;						//Trim leading and trailing spaces
	this.blnDateIsFuture = blnDateIsFuture;		//Check that a date is not in the past
	this.strStripBlanks = strStripBlanks;		//Strips ALL blanks from a string passed as a parameter
	this.CCStripSpaces = CCStripSpaces;			// Strips spaces and dashes from credit card number.
	this.CCMod10Check = CCMod10Check;			// Perfroms the mod10 check on a credit card number.
	this.CompareDates = CompareDates;			//Compares two dates, returns + if 1 > 2, 0 if 1 = 2, else -
	this.blnIsDate = blnIsDate;					//Checks if three params constitute a date, with optional year offset for use with 2 digit years
}

function IsMSBrowser()
{
	var objAgent = navigator.userAgent.toLowerCase();
	if (objAgent.indexOf("msie") != -1) return true;
	else return false;
}

//Formats a number to the specified decimal places
function strFormatNumber(strNumber, intPlace) 
{
	var sngNumber = parseFloat(strNumber)
	var i
	var strBuffer
	
	if (!isNaN(sngNumber)) {
		if (0 != sngNumber) {
			strBuffer = "" + Math.round(sngNumber * (Math.pow(10, intPlace)) );
			if (0 != intPlace) {
				while (strBuffer.length < intPlace) strBuffer = "0" + strBuffer;
				strBuffer = strBuffer.substr(0, strBuffer.length - intPlace) + "." + strBuffer.substr(strBuffer.length - intPlace, intPlace);
			}
			if ("." == strBuffer.substr(0,1)) strBuffer = "0" + strBuffer
		} else {
			strBuffer = "0"
			if (0 != intPlace) {
				strBuffer += "."
				for(i=0; i<intPlace; i++) strBuffer+="0";
			}
		}
	} else {
		strBuffer = "0"
		if (0 != intPlace) {
			strBuffer += "."
			for(i=0; i<intPlace; i++) strBuffer+="0";
		}
	}
	return(strBuffer);
}

//Input validation functions
function strFormatDate(strNewDate) {
	var datDate;
	var strMonthsArray = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(",");
	var str2kCorrection;
	
	if (strNewDate.indexOf("/") > 0) strNewDate = strOzDate(strNewDate, "/");
	else if (strNewDate.indexOf("-") > 0) strNewDate = strOzDate(strNewDate, "-");
	else if (strNewDate.indexOf(" ") > 0) strNewDate = strOzDate(strNewDate, " ");
	
	var strDate = Date.parse(strNewDate);

	//If cannot be interpretted as a date then exit with keyword "N.A."
	if (isNaN(strDate)) return "N.A.";
	
	//Convert to internal date format
	datDate = new Date(strDate);
	
	return (datDate.getDate() + " " + strMonthsArray[datDate.getMonth()] + " " + datDate.getFullYear());	
}
		
function strOzDate(strDate,strSeparator) {
	var strDateArray;
	var intDay;
	var intMonth;
	var intYear;
	
	strDateArray = strDate.split(strSeparator);
	if (strSeparator == " ") strSeparator = "/";
	
	//using / format in date so parse and check
	if (strDateArray.length > 2) {			
		intDay = parseInt(strDateArray[0], 10);
		intMonth = parseInt(strDateArray[1], 10);
		
		// We only accept 2 or 4 digit years 
		if (strDateArray[2] != null && !(strDateArray[2].length == 2 || strDateArray[2].length == 4))
		{
		    return;
		}
		intYear = parseInt(strDateArray[2], 10);
		// if two digit year use 2000 + unless more than 10 years in the future
		if (!isNaN(intYear) && intYear < 100)
		{
		    // can't have a 4 digit year less than 100 - e.g. 0001 - this will be interpreted as 
		    // 2001 but may be interpreted as year 1 elsewhere!
		    if (strDateArray[2].length == 4)
		    {
		        return;
		    }		
		    intYear += 2000;
		    if (intYear > parseInt((new Date()).getFullYear(), 10) + 10)
		    {
		        intYear -= 100;
		    }
		    strDateArray[2] = intYear;
		}
		
		if (!isNaN(intMonth)) {
			if (!(intMonth > 0 && intMonth <= 12)) {
				return;
			} else if (!(intDay > 0 && intDay <= 31)) {
				return;
			}
			else if ((intMonth == 4 || intMonth == 6 || intMonth == 9 || intMonth == 11) && intDay > 30) {
				return;
			}
			else if (intMonth == 2 && (intDay > 29 || (!isLeapYear(intYear) && intDay > 28))) {
				return;
			}
			return (strDateArray[1] + strSeparator + strDateArray[0] + strSeparator + strDateArray[2]);
		}
	}
	return strDate;	//Return unchanged
}

function isLeapYear(intYear)
{
	if (intYear % 4 != 0) return false;
	if (intYear % 400 == 0) return true;
	if (intYear % 100 == 0) return false;
	return true;
}
			
function strTrim(strText) {
		
	for (i=0; i<strText.length; ++i) {
		if (strText.charAt(i) != ' ') break;
	}

	//All spaces so exit
	if (i >= strText.length) return ('');
	
	//Left trim spaces
	if (i > 0) strText = strText.substring(i, strText.length);
	
	for (j=strText.length-1; j > i; --j) {
		if (strText.charAt(j) != ' ') break;
	}
	
	if (j < strText.length -1)
		strText = strText.substring(0, j+1);
		
	return strText;
}
		
function blnDateIsFuture(datDateToCheck) {
	return (CompareDates(new Date(), new Date(datDateToCheck)) <= 0);			
}
		
function CompareDates(date1, date2) {
	if (date1.getFullYear() < date2.getFullYear())
		return -1;
	if (date1.getFullYear() > date2.getFullYear())
		return 1;
	if (date1.getMonth() < date2.getMonth())
		return -1;
	if (date1.getMonth() > date2.getMonth())
		return 1;
	if (date1.getDate() < date2.getDate())
		return -1;
	if (date1.getDate() > date2.getDate())
		return 1;
	return 0;
}
		
function blnIsDate(year, month, day, year2kOffset){
	if (!IsNaturalNumber(year) || !IsNaturalNumber(month) || !IsNaturalNumber(day)) return false;
	if ((''+year).length != 4 && (''+year).length != 2) return false;
	day = (day[0] == '0' ? day.substring(1, day.length) : day);
	month = (month[0] == '0' ? month.substring(1, month.length) : month);
	year = (year.length == 4 ? year : (year < (year2kOffset ? year2kOffset : 50) ? '20' : '19') + year);
	if (day <= 0 || day > 31) return false;
	if (month <= 0 || month > 12) return false;
	//apr,jun,sep,nov have 30 days
	if (day > 30 && (month == 4 || month == 6 || month == 9 || month == 11)) return false;
	//feb has 28, unless leap year - year div by 4 and (not 100 or is by 400) - then 29
	if (month == 2 && day > 28 && !((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) && day == 29)) return false;
	return true;
}
		
function strStripBlanks(strString) {
	var strNewString = "";
	var iIter = 0;
	var jIter = 0;
	var intPosition = 0;
	var strTempString = "";

	if (strString.indexOf(" ") > 0) {
		for (iIter=0; iIter<strString.length; iIter++) {
			if (strString.charAt(iIter) == " ") {
				strTempString = strTempString + strString.substring(intPosition,iIter);
			} else {
				strTempString = strTempString + strString.charAt(iIter);
			}
			intPosition = iIter+1;
		}
		strNewString = strTempString;
	} else {
		strNewString = strString;
	}

	return strNewString;
}

// Strips spaces and dashes
function CCStripSpaces(strPassedCCNumber)
{		
	var strBuffer = '';
			
	for(var i = 0; i < strPassedCCNumber.length; i++)
	{
		if (strPassedCCNumber.charAt(i) != ' ' && strPassedCCNumber.charAt(i) != '-')
		{
			strBuffer = strBuffer + strPassedCCNumber.charAt(i);
		}
	} 
							
	return strBuffer;
}

// Perfroms the mod10 check on a credit card number.
function CCMod10Check(strPassedCCNumber)
{
	var intEvenSum = 0;
	var intOddSum = 0;
	var intTemp = 0;
			
	for(var i = strPassedCCNumber.length - 2; i >= 0; i = i - 2)
	{
		intTemp = parseInt(strPassedCCNumber.charAt(i));
		intTemp = intTemp * 2;
				
		if (intTemp > 9)
		{
			intTemp = intTemp - 9;
		}
		intEvenSum = intEvenSum + intTemp;
	} 
			
	for(var j = strPassedCCNumber.length - 1; j >= 0; j = j - 2)
	{
		intTemp = parseInt(strPassedCCNumber.charAt(j));
		intOddSum = intOddSum + intTemp;
	} 

	if (((intOddSum + intEvenSum) % 10) != 0)
	{
		return false
	}
	else 
	{
		return true
	}	
}	

function ValidateContactUs(
    thisForm, 
    typeID,
	typeReq,
    messageID,
	messageReq,
	emailID,
	emailReq,
	salutationID,
	firstNameID,
	lastNameID,
	nameReq,
	phoneCCID,
	phoneACID,
	phoneID,
	phoneReq,
	phoneCCVisible,
	phoneACVisible	
	)
{
	var type           = objField(thisForm, typeID, "");
	var message        = objField(thisForm, messageID, "");
	var email          = objField(thisForm, emailID, "");
	var nameSalutation = objField(thisForm, salutationID, "");
	var nameFirst      = objField(thisForm, firstNameID, "");
	var nameLast       = objField(thisForm, lastNameID, "");
	var phoneCC        = objField(thisForm, phoneCCID, "");
	var phoneAC        = objField(thisForm, phoneACID, "");
	var phoneN         = objField(thisForm, phoneID, "");

	//Validate UniCode
	if (!ValidateCharSet(message)) return false;
	if (!ValidateCharSet(email)) return false;
	if (!ValidateCharSet(nameSalutation)) return false;
	if (!ValidateCharSet(nameFirst)) return false;
	if (!ValidateCharSet(nameLast)) return false;
	if (!ValidateCharSet(phoneCC)) return false;
	if (!ValidateCharSet(phoneAC)) return false;
	if (!ValidateCharSet(phoneN)) return false;

	// Type is Blank
	if (typeof(type) != 'undefined' && (typeReq) && (!IsRadioSelected(type)))
	{
		type[0].focus();
		alert(_messages["TypeBlank"]);
		return false;
	}
	
	
	// Message Blank
	if ((message != 'undefined') && (messageReq) && (message.value == ""))
	{
		message.focus();
		alert(_messages["MessageBlank"]);
		return false;
	}
	
	// Email Not Blank
	if ((typeof(email) != 'undefined') && (emailReq) && (email.value == ""))
	{
		email.focus();
		alert(_messages["EmailBlank"]);
		return false;
	}
	
	// Email Invalid
	if ((typeof(email) != 'undefined') && (emailReq) && (!ValidateEmail(email.value)))
	{
		email.focus();
		alert(_messages["EmailInvalid"]);
		return false;
	}

	// Salutation Selected
	if ((typeof(nameSalutation) != 'undefined') && (nameReq) && 
	    (nameSalutation.options.selectedIndex == 0))
	{
		nameSalutation.focus();
		alert(_messages["SalutationUnSelected"]);
    	return false;
	}

	// First Name Blank
	if ((typeof(nameFirst) != 'undefined') && (nameReq) && (nameFirst.value == ""))
	{
		nameFirst.focus();
		alert(_messages["FirstNameBlank"]);
		return false;
	}

	// Last Name Blank
	if ((typeof(nameLast) != 'undefined') && (nameReq) && (nameLast.value == ""))
	{
		nameLast.focus();
		alert(_messages["LastNameBlank"]);
		return false;
	}

	// Phone CC Blank
	if ((typeof(phoneCC) != 'undefined') && (phoneReq) && (phoneCC.value == "") && (phoneCCVisible))
	{
		phoneCC.focus();
		alert(_messages["PhoneCCBlank"]);
		return false;
	}	

	// Phone AC Blank
	if ((typeof(phoneAC) != 'undefined') && (phoneReq) && (phoneAC.value == "") && (phoneACVisible))
	{
		phoneAC.focus();
		alert(_messages["PhoneACBlank"]);
		return false;
	}	

	// Phone N Blank
	if ((typeof(phoneN) != 'undefined') && (phoneReq) && (phoneN.value == ""))
	{
		phoneN.focus();
		alert(_messages["PhoneNBlank"]);
		return false;
	}	
	
	// Phone Not Numeric
	if (((((typeof(phoneCC) != 'undefined') && (phoneCCVisible)) || ((typeof(phoneAC) != 'undefined') && 
	    (phoneACVisible)) || (typeof(phoneN) != 'undefined'))) && (phoneReq) && 
	    !ValidatePhone(phoneCC, phoneAC, phoneN, phoneCCVisible, phoneACVisible))
	{		
		alert(_messages["PhoneNonNumeric"]);
		return false;
	}
	
	return true;
}

/* Contact Us Details User Control */
// Validates ContactUs detailed form
function ValidateContactUsDetailed(thisForm, 
	idToValidate, 
	performanceReq,
	performanceLocationReq,
	performanceDateReq,
	queryCategoryReq,
	querySubCategoryReq,
	messageReq,
	softixAccountNumReq,
	softixTransactionNumReq,
	nameFirstReq,
	nameLastReq,
	phoneDayReq,
	phoneEveningReq,
	emailReq
	)
{
	// Get form fields back
	var performance				= objField(thisForm, idToValidate, "$uiPerformance");
	var performanceLocation		= objField(thisForm, idToValidate, "$uiPerformanceLocation");
	var performanceDay			= objField(thisForm, idToValidate, "$uierformanceDay");
	var performanceMonth		= objField(thisForm, idToValidate, "$uiPerformanceMonth");
	var performanceYear			= objField(thisForm, idToValidate, "$uiPerformanceYear");
	var queryCategory			= objField(thisForm, idToValidate, "$uiCategory");
	var querySubCategory		= objField(thisForm, idToValidate, "$uiSubCategory");
	var message					= objField(thisForm, idToValidate, "$uiMessage");
	var softixAccountNum		= objField(thisForm, idToValidate, "$uiAccountNumber");
	var softixTransactionNum	= objField(thisForm, idToValidate, "$uiTransactionNumber");
	var nameFirst				= objField(thisForm, idToValidate, "$uiFirstName");
	var nameLast				= objField(thisForm, idToValidate, "$uiLastName");
	var phoneDay				= objField(thisForm, idToValidate, "$uiDayPhone");
	var phoneEvening			= objField(thisForm, idToValidate, "$uiEveningPhone");
	var email					= objField(thisForm, idToValidate, "$uiEmail");
		
	// Validate UniCode
	if (!ValidateCharSet(performance) ||
		!ValidateCharSet(performanceLocation) ||
		!ValidateCharSet(performanceDay) ||
		!ValidateCharSet(performanceMonth) ||
		!ValidateCharSet(performanceYear) ||
		!ValidateCharSet(queryCategory) ||
		!ValidateCharSet(querySubCategory) ||
		!ValidateCharSet(message) ||
		!ValidateCharSet(softixAccountNum) ||
		!ValidateCharSet(softixTransactionNum) ||
		!ValidateCharSet(nameFirst) ||
		!ValidateCharSet(nameLast) ||
		!ValidateCharSet(phoneDay) ||
		!ValidateCharSet(phoneEvening) ||
		!ValidateCharSet(email)) return false;

	// Performance Blank
	if ((typeof(performance) != 'undefined') && (performanceReq) && (performance.value == ""))
	{
		performance.focus();
		alert(_messages["ContactUsPerformanceBlank"]);
		return false;
	}
	
	// Performance Location Blank
	if ((typeof(performanceLocation) != 'undefined') && (performanceLocationReq) && 
		(performanceLocation.options.selectedIndex == 0))
	{
		performanceLocation.focus();
		alert(_messages["ContactUsPerformanceLocationBlank"]);
		return false;
	}
	
	// Performance Month Blank
	if ((typeof(performanceMonth) != 'undefined') && (performanceDateReq) && 
		(performanceMonth.options.selectedIndex == 0))
	{
		performanceMonth.focus();
		alert(_messages["ContactUsPerformanceMonthBlank"]);
		return false;
	}

	// Performance Day Blank
	if ((typeof(performanceDay) != 'undefined') && (performanceDateReq) && 
		(performanceDay.options.selectedIndex == 0))
	{
		performanceDay.focus();
		alert(_messages["ContactUsPerformanceDayBlank"]);
		return false;
	}	
	
	// Performance Year Blank
	if ((typeof(performanceYear) != 'undefined') && (performanceDateReq) && 
		(performanceYear.options.selectedIndex == 0))
	{
		performanceYear.focus();
		alert(_messages["ContactUsPerformanceYearBlank"]);
		return false;
	}

	// Performance Date not required but not filled appropriately
	if (((typeof(performanceMonth) != 'undefined') && (typeof(performanceDay) != 'undefined') && 
		(typeof(performanceYear) != 'undefined')) && ((performanceMonth.value != '') || 
		(performanceDay.value != '') || (performanceYear.value != '')))
	{
		if ((performanceMonth.value == '') || (performanceDay.value == '') || 
			(performanceYear.value == ''))
		{
			performanceMonth.focus();
			alert(_messages["ContactUsPerformanceDateBlank"]);
			return false;
		}
	}
	
	// Category Blank
	if ((typeof(queryCategory) != 'undefined') && (queryCategoryReq) && 
		(queryCategory.options.selectedIndex == 0))
	{
		queryCategory.focus();
		alert(_messages["ContactUsQueryCategoryBlank"]);
		return false;
	}	
		
	// Sub-Category Blank
	if ((typeof(querySubCategory) != 'undefined') && (querySubCategoryReq) && 
		(querySubCategory.options.selectedIndex == 0))
	{
		querySubCategory.focus();
		alert(_messages["ContactUsQuerySubCategoryBlank"]);
		return false;
	}		
	
	// Message Blank
	if ((typeof(message) != 'undefined') && (messageReq) && (message.value == ""))
	{
		message.focus();
		alert(_messages["ContactUsMessageBlank"]);
		return false;
	}
	
	// Softix Account Number Blank
	if ((typeof(softixAccountNum) != 'undefined') && (softixAccountNumReq) && 
		(softixAccountNum.value == ""))
	{
		softixAccountNum.focus();
		alert(_messages["ContactUsSoftixAccountNumBlank"]);
		return false;
	}
	
	// Softix Account Number Non Numeric
	if ((typeof(softixAccountNum) != 'undefined') && (softixAccountNum.value != "") && 
		(!IsNumeric(softixAccountNum)))
	{
		softixAccountNum.focus();
		alert(_messages["ContactUsSoftixAccountNumNonNumeric"]);
		return false;
	}
	
	// Softix Transaction Number Blank
	if ((typeof(softixTransactionNum) != 'undefined') && (softixTransactionNumReq) && 
		(softixTransactionNum.value == ""))
	{
		softixTransactionNum.focus();
		alert(_messages["ContactUsSoftixTransactionNumBlank"]);
		return false;
	}
	
	// First Name Blank
	if ((typeof(nameFirst) != 'undefined') && (nameFirstReq) && (nameFirst.value == ""))
	{
		nameFirst.focus();
		alert(_messages["ContactUsFirstNameBlank"]);
		return false;
	}
	
	// Last Name Blank
	if ((typeof(nameLast) != 'undefined') && (nameLastReq) && (nameLast.value == ""))
	{
		nameLast.focus();
		alert(_messages["ContactUsLastNameBlank"]);
		return false;
	}
		
	// Day Phone Blank
	if ((typeof(phoneDay) != 'undefined') && (phoneDayReq) && (phoneDay.value == ""))
	{
		phoneDay.focus();
		alert(_messages["ContactUsPhoneDayBlank"]);
		return false;
	}
	
	// Evening Phone Blank
	if ((typeof(phoneEvening) != 'undefined') && (phoneEveningReq) && (phoneEvening.value == ""))
	{
		phoneEvening.focus();
		alert(_messages["ContactUsPhoneEveningBlank"]);
		return false;
	}
	
	// Email Not Blank
	if ((typeof(email) != 'undefined') && (emailReq) && (email.value == ""))
	{
		email.focus();
		alert(_messages["ContactUsEmailBlank"]);
		return false;
	}
	
	// Email Invalid
	if ((typeof(email) != 'undefined') && (email.value != '') && (!ValidateEmail(email.value)))
	{
		email.focus();
		alert(_messages["ContactUsEmailInvalid"]);
		return false;
	}
	
	return true;
}

/* 
IsNumeric function will validate true if the value is numeric (i.e in [0-9]), 
otherwiser it will validate to false as the value contains non numeric characters 
*/
function IsNumeric(formNumber)
{	
	var objStringUtils = new CSoftixUtils;	

	if (typeof(formNumber.value) != 'undefined')
	{
		formNumber.value = objStringUtils.CCStripSpaces(formNumber.value);
	}
    
    return IsNaturalNumber(formNumber.value);
}

function IsNaturalNumber(val)
{					
    var regex = new RegExp("^[0-9]*$");    
    return regex.test(val);
}

// Updates sub category drop down list, based on the category selected
function UpdateSubCategory(thisForm, idToRetrieve, subCategories)
{	
	// retrieve objects for the drop downs
	var queryCategory		= objField(thisForm, idToRetrieve, "$uiCategory");
	var querySubCategory	= objField(thisForm, idToRetrieve, "$uiSubCategory");
	
	if ((typeof(querySubCategory) != 'undefined') && (typeof(queryCategory) != 'undefined')) 
	{
		querySubCategory.length = 0;

		var options = subCategories[queryCategory.selectedIndex];
		
		for (var key in options)
		{
			querySubCategory.options[querySubCategory.options.length] = new Option(options[key], key);
		}
	}
}

/*
confirm whether a user has agreed to delete his/her account
*/
function ConfirmAccountCancellation(thisForm, 
	idToValidate,
	selectionReq)
{
	if(confirm(_messages["AccountCancelConfirm"]))
	{
		return true;
	}	
	return false;
}

/*
validates unsubscribe form to ensure that form is filled out
*/
function ValidateAccountUnsubscribe(thisForm, 
	idToValidate,
	loginCodeReq
	)
{
	// Get form fields back
	var loginCode = objField(thisForm, idToValidate, ":loginCode");
	
	//UniCode Validation
	if (!ValidateCharSet(loginCode)) return false;
			
	// Email Not Blank
	if ((typeof(loginCode) != 'undefined') && (loginCodeReq) && (loginCode.value == ""))
	{
		loginCode.focus();
		alert(_messages["AccountUnsubscribeLoginCodeBlank"]);
		return false;
	}
	
	return true;
}

/*
this function will loop through an array of checkboxes and will validate whether at least one 
value is selected
*/
function IsCheckBoxSelected(objCheckBoxs)
{
	// check if the array is defined
	if (typeof(objCheckBoxs.length) != 'undefined')
	{
		// loop through the array of check boxes
		for (var i=0; i<objCheckBoxs.length; i++)
		{
			if (objCheckBoxs[i].checked) return true;
		}
		return false;
	}
	else return objCheckBoxs.checked;
}

/*
Unsubscribe.aspx - user control
this function will validate if user has selected at least one of the account unsubscribe 
check box options
*/
function ValidateAccountUnsubscribeCheckBox(thisForm, idToValidate)
{
	var isValid = true;
	var checkBoxIndex = 0;
	
	// define the check box values to check
	var checkBoxName = 'uiEmailAccountAttribute';
	
	// checkboxes array	
	var objAccountAttrbuteCheckBox = new Array;
	
	// get all elements on the form
	var objForm = GetForm(thisForm);
	eval("var formElements = objForm.elements");
	
	// loop through all elements on the list and build the check box array
	for (var i = 0; i < formElements.length; i++)
	{
		var formElementId = formElements[i].id;
		
		// check if the form element is a checkbox
		if (formElementId.indexOf(checkBoxName) != -1)
		{
			eval("objAccountAttrbuteCheckBox[" + checkBoxIndex + "] = objForm['" + 
			    checkBoxName + checkBoxIndex + ":checkBox']");
			checkBoxIndex += 1;
		}
	}	

	if (!IsCheckBoxSelected(objAccountAttrbuteCheckBox))
	{
		alert(_messages["AccountUnsubscribeCheckBoxBlank"]);
		isValid = false;
	}
	
	return isValid;
}


/*
Unsubscribe.aspx - user control
this function will validate if user has selected at least one of the account unsubscribe radio options
*/
	
function ValidateAccountUnsubscribeRadioButton(thisForm, idToValidate)
{
	var isValid = true;

	// Check account attributes selected
	var objAccountAttrbuteRadioButton = objField(thisForm, idToValidate, ":radioButton");
	
	if (!IsRadioSelected(objAccountAttrbuteRadioButton))
	{
		alert(_messages["AccountUnsubscribeRadioButtonBlank"]);
		isValid = false;
	}
		
	return isValid;
}
	
// Validates phone number fields for PersonalDetails user control
function IsValidNumber(formField, fieldRequired, errMsgBlankField, errMsgNonNumeric)
{	
	var objStringUtils = new CSoftixUtils;
	var errMsg = "";		

	if (typeof(formField) != 'undefined')
	{
		if (fieldRequired && objStringUtils.strTrim(formField.value) == "")	
		{
			errMsg = errMsgBlankField;
		}
		else 
		{
		    if (!IsNumeric(formField)) errMsg = errMsgNonNumeric;
		}
	}

	if (errMsg != "")
	{
		alert(_messages[errMsg]);
		formField.focus();
		return false;
	}

	return true;	
}

/*
 * ValidateAccountChangePassword for AccountChangePasswordControl
*/

// Unicode validation for ChangePassword
function ValidateAccountChangePassword(thisForm, idToValidate)
{
    // Original Password
    var oldPassword	= objField(thisForm, idToValidate, "$tbOldPassword");
    // New Password
    var newPassword	= objField(thisForm, idToValidate, "$tbNewPassword");	
    // Confirm Password
    var conPassword	= objField(thisForm, idToValidate, "$tbNewPasswordConfirm");	

    //Validate UniCode
    if (!ValidateCharSet(oldPassword)) return false;
    if (!ValidateCharSet(newPassword)) return false;
    if (!ValidateCharSet(conPassword)) return false;

    //Validate new Password and Confirm Password
    if (newPassword.value != conPassword.value)
    {
	    alert(_messages["PasswordUnConfirmed"]);
	    return false;
    }
    	
    return true;
}
 
 
/*
	This function update the states form field based on the following rules:
	
	a. If there are states available for the country selected, then a select combo box is visible with 
	the approptiate state options;
	b. If there are no states available for the country selected, the hide the select combo box and make input text field
	visible.
*/
function ChangeState(stateComboBoxAllowed, countryDropDown, stateDropDown, stateOther, countryOther, countryOtherLabel)
{
	// identifies the country form field 
	var objCountry = document.getElementById(countryDropDown);
	// identifies the countryOther form field 
	var objCountryOther = document.getElementById(countryOther);
	// identifies the countryOther label
	var objCountryOtherLabel = document.getElementById(countryOtherLabel);	
	// identifies the state input form field
	var objState = document.getElementById(stateOther);
	// identifies the state select form field
	var objStateSelect = document.getElementById(stateDropDown);
if(objStateSelect == null) return;
	// identifies if the select drop down is visible
	var stateSelectVisible = false;
    
	// validate the country state array exist
	if (_countryStateValues != 'undefined')
	{
		var states;
		if (objCountry && objCountry != 'undefined')
		{
		   states = _countryStateValues[objCountry.value];
		}
		else
		{
		    // country is not displayed so we need the states for the default country
		    var countryName;
		    for (countryName in _countryStateValues)
		    {
		        break;
		    }
		    states = _countryStateValues[countryName];
		}
		if (states != null && states.length && states.length > 0)
		{
			objStateSelect.options.length = states.length;

			for (var i = 0; i < states.length; i++)
			{		
				objStateSelect.options[i] = new Option(states[i][1], states[i][0]);
				
				if (objState.value == states[i][0])
				{
					objStateSelect.options[i].selected = true;
				}
			}
			
			stateSelectVisible = true;
		}
		
		// validate if the state select combo box is visible
		if (stateSelectVisible && stateComboBoxAllowed)
		{
			// set the style for the select combo box to be visible
			objStateSelect.style.display = 'inline';			
			// set the style for the input text field to be invisible
			objState.value = '';
			objState.style.display = 'none';
		}
		else
		{
			// set the style for the select combo box to be invisible
			objStateSelect.style.display = 'none';
			// set the style for the input text field to be visible
			objState.style.display = 'inline';
		}
	
		//hide countryother unless "other" selected.
		if (objCountry.value == 'other')
		{
		    objCountryOther.style.display = 'inline';
		    objCountryOtherLabel.style.display = 'inline';
		}
		else
		{
		    objCountryOther.style.display = 'none';
		    objCountryOther.value = '';
		    objCountryOtherLabel.style.display = 'none';
		}
	}	
}

function UpdateStateValue(thisForm, uniqueId, stateComboBoxAllowed)
{
	// identifies the state input form field
	var objState = objField(thisForm, uniqueId, ":state");
	// identifies the state select form field
	var objStateSelect = objField(thisForm, uniqueId, ":stateSelect");
	
	objState.value = objStateSelect.options[objStateSelect.options.selectedIndex].value;
}

/* Email A Friend control */
function ValidateEmailAFriend(thisForm,	idToValidate, fromNameReq, fromEmailReq, toNameReq, messageReq)
{
	// Get form fields back
	var fromName	= objField(thisForm, idToValidate, "$uiFromName");
	var fromEmail	= objField(thisForm, idToValidate, "$uiFromEmail");
	var toName		= objField(thisForm, idToValidate, "$uiToName");
	var toEmail		= objField(thisForm, idToValidate, "$uiToEmail");
	var message		= objField(thisForm, idToValidate, "$uiMessage");
			
	// FromName
	if ((typeof(fromName) != 'undefined') && (fromNameReq) && (fromName.value == ""))
	{
		fromName.focus();		
		alert(_messages["FromNameBlank"]);
		return false;
	}
	
	// FromEmail
	if ((typeof(fromEmail) != 'undefined') && (fromEmailReq) && (fromEmail.value == ""))
	{
		fromEmail.focus();		
		alert(_messages["FromEmailBlank"]);
		return false;
	}
	
	// FromEmail Invalid
	if ((typeof(fromEmail) != 'undefined') && (fromEmail.value != '') && (!ValidateEmail(fromEmail.value)))
	{
		fromEmail.focus();		
		alert(_messages["FromEmailInvalid"]);
		return false;		
	}
	
	// ToName
	if ((typeof(toName) != 'undefined') && (toNameReq) && (toName.value == ""))
	{
		toName.focus();
		alert(_messages["ToNameBlank"]);
		return false;
	}

	// ToEmail
	if ((typeof(toEmail) != 'undefined') && (toEmail.value == ""))
	{
		toEmail.focus();
		alert(_messages["ToEmailBlank"]);
		return false;
	}	
	
	// ToEmail invalid
	if ((typeof(toEmail) != 'undefined') && (toEmail.value != '') && (!ValidateEmail(toEmail.value)))
	{
		toEmail.focus();
		alert(_messages["ToEmailInvalid"]);
		return false;
	}

	// Message
	if ((typeof(message) != 'undefined') && (messageReq) && (message.value == ""))
	{
		message.focus();
		alert(_messages["MessageBlank"]);
		return false;
	}	

	return true;
}



/*
    Invite a Friend control
*/
function inviteAFriendAddRow(tableID, maxRows, isInvite)
{
	var objTable = document.getElementById(tableID);
	if (typeof(objTable) != 'undefined')	
	{
	    if (objTable.rows.length < maxRows + 1)
	    {
			// Re-index all of the name/email elements to allow for new ones
			for (var i = objTable.rows.length - 1; i > 0; i--)
			{
				inviteAFriendUpdateElementIndices(i - 1, i);
			}
	    
	        // copy the friend first row
	        var objRow = objTable.rows[1];
	        var objNewRow = objTable.insertRow(1);
	        var objFirstNewElement = null;	    
    	    
	        for (var i = 0; i < objRow.cells.length; i++)
	        {
	            var objNewCell = objNewRow.insertCell(i);
	            objNewCell.className = objRow.cells[i].className;
	            
	            for (var j = 0; j < objRow.cells[i].childNodes.length; j++)
	            {
	                objNewElement = objRow.cells[i].childNodes[j].cloneNode(true);
	                objNewCell.appendChild(objNewElement);
	                if (objNewElement.tagName == 'INPUT')
	                {
						inviteAFriendUpdateElementIndex(objNewElement, 0);
						
	                    objNewElement.value = '';
	                    if (objFirstNewElement == null)
	                    {
	                        objFirstNewElement = objNewElement;
	                    }
	                }
	            }
	        }	   
    	    
	        // hide the add button from the copied row and make sure the delete button is shown
	        inviteAFriendShowHideButtons(objRow.cells[objRow.cells.length - 1], false);
	        
	        // Hide the "To" label for all but the first row
	        objTable.rows[2].cells[0].childNodes[0].style.display = 'none';
	        
	        //if max rows reached remove the add button 
	        if (objTable.rows.length == maxRows + 1)
	        {
	            inviteAFriendShowHideButtons(
	                objTable.rows[1].cells[objTable.rows[1].cells.length - 1], false);
	        }
	        
	        //Make sure the tabbing is correct 
	        if (isInvite) inviteAFriendSetKeyHandlers();
	        
	        if (objFirstNewElement != null) objFirstNewElement.focus();
	    }
	}
	return;    
}


function inviteAFriendShowHideButtons(objParent, showAdd)
{
	// NB first span is add second span is delete
    var spanCount = 0;
    for (var i = 0; i < objParent.childNodes.length; i++)
    {
        if (objParent.childNodes[i].tagName == 'SPAN')
        {
            if ((!showAdd && spanCount == 0) || (showAdd && spanCount > 0))
            {
                objParent.childNodes[i].style.display = 'none';
                objParent.childNodes[i].style.visibility = 'hidden';
            }
            else
            {
                objParent.childNodes[i].style.display = 'inline';
                objParent.childNodes[i].style.visibility = 'visible';
            }
            spanCount++;
        }
    }
}

function inviteAFriendDeleteRow(tableID, objSource, isInvite)
{
	var objTable = document.getElementById(tableID);
	if (typeof(objTable) != 'undefined')	
	{
	    if (objTable.rows.length > 2)
	    {
	        // Our source should be an img or link in the last column of 
	        // one of the rows in the table - we need to know which row
	        for (var i = 1; i < objTable.rows.length; i++)
	        {
	            var objCell = objTable.rows[i].cells[objTable.rows[i].cells.length - 1];
	            if (isDescendantOf(objSource, objCell))
                {
                    //Remove this row
                    objTable.deleteRow(i);
                    
                    // Re-index the elements in the rows after the deleted row
                    for (var j = i; j < objTable.rows.length; j++)
                    {
						inviteAFriendUpdateElementIndices(j, j - 1);
                    }

                    //Make sure add button is visible
                    inviteAFriendShowHideButtons(
                        objTable.rows[1].cells[objTable.rows[1].cells.length - 1], true);
                        
                    // If this is the first tow, make sure the "To" label is re-displayed
                    if (i == 1)
                    {
						objTable.rows[1].cells[0].childNodes[0].style.display = '';
                    }
                        
                    if (isInvite) inviteAFriendSetKeyHandlers();
                    // Set the focus to the first name field in the first friend row
                    for (var k = 0; k < objTable.rows[1].cells.length; k++)
                    {
                        for (var m = 0; m < objTable.rows[1].cells[k].childNodes.length; m++)
                        {
	                        if (objTable.rows[1].cells[k].childNodes[m] != null
	                            && objTable.rows[1].cells[k].childNodes[m].tagName == 'INPUT')
                            {
                                objTable.rows[1].cells[k].childNodes[m].focus();
                                return;
                            }
                        }   
                    }
                    return;
                }
	        }
	    }
	    else
	    {
	        alert(_messages["InviteAFriendCannotRemoveLastRow"]);
	    }
	}
}

var elementIndexPattern = /\:\d+/;

function inviteAFriendUpdateElementIndices(oldIndex, newIndex)
{
	inviteAFriendUpdateElementIndex(document.getElementById('uiInviteAFriendName:' + oldIndex), newIndex);
	inviteAFriendUpdateElementIndex(document.getElementById('uiInviteAFriendEmail:' + oldIndex), newIndex);
}

function inviteAFriendUpdateElementIndex(element, newIndex)
{
	element.id = element.id.replace(elementIndexPattern, ':' + newIndex);
	element.name = element.name.replace(elementIndexPattern, ':' + newIndex);
}

function isDescendantOf(objNode, objParentNode)
{
    if (objNode == null || objNode.parentNode == null || 
        objNode.parentNode == document || objParentNode == null)
    {
        return false;
    }
    else
    {
        if (objNode.parentNode == objParentNode) return true;
        else return isDescendantOf(objNode.parentNode, objParentNode);
    }
}

function inviteAFriendCountBlurbLength(formID, controlID, spanID, maxLength)
{
	var objBlurb = document.forms[formID][controlID];
	var objSpan = document.getElementById(spanID);
	for (var i = objSpan.childNodes.length - 1; i >= 0; i--)
	{
	    objSpan.removeChild(objSpan.childNodes[i]);
	}
	
	var remaining = maxLength - objBlurb.value.length;
	if (remaining < 0)
	{
		remaining = 0;
		objBlurb.value = objBlurb.value.substring(0, maxLength);
	}
	
	objSpan.appendChild(document.createTextNode(remaining));
}

function HoldAdjacentSeatsValid(formID, controlID, blurbMaxLength, blurbReq)
{
    var objHoldNumber = objField(formID, controlID, '$uiHoldNumber');
    if (typeof(objHoldNumber) != 'undefined')
    {
        if (parseInt(objHoldNumber.options[objHoldNumber.selectedIndex].value, 10) > 0)
        {
            return InviteAFriendCommonValid(formID, controlID, blurbMaxLength, blurbReq);
        }
    }
    return true;
}

function InviteAFriendValid(formID, controlID, blurbMaxLength, blurbReq)
{
    return InviteAFriendCommonValid(formID, controlID, blurbMaxLength, blurbReq);
}

function InviteAFriendCommonValid(formID, controlID, blurbMaxLength, blurbReq)
{
	var objStringUtils = new CSoftixUtils;
	var objForm = GetForm(formID);
	var anyFriends = false;
	
	var index = 0;
	
	while (true)
	{
		var nameElement = document.getElementById('uiInviteAFriendName:' + index);
		var emailElement = document.getElementById('uiInviteAFriendEmail:' + index);
		
		if (nameElement == null || emailElement == null)
		{
			break;
		}
		
		var result = InviteAFriendFriendValid(nameElement, emailElement);
        if (result == 0) return false;
        else if (result > 0) anyFriends = true;
        
        index++;
	}
	
	if (!anyFriends)
	{
	    alert(_messages["InviteAFriendNoFriendsSpecified"]);
	    var firstNameElement = document.getElementById('uiInviteAFriendName:0');
	    if (firstNameElement != null) firstNameElement.focus();
	    return false;
	}
	
	// Validate the email message
	var objEmailMessage = objField(formID, controlID, "$uiEmailBlurb");
	if (!ValidateCharSet(objEmailMessage)) return false;
	//must be less than 255 characters
	var emailMessage = objStringUtils.strTrim(objEmailMessage.value);
	if((typeof(emailMessage) == 'undefined' || emailMessage.length == 0) && blurbReq)
	{
	    alert(_messages["InviteAFriendEmailMessageRequired"]);
	    objEmailMessage.focus();
	    return false;	    
	}
	if (typeof(emailMessage) != 'undefined' && emailMessage.length > blurbMaxLength)
	{
	    alert(_messages["InviteAFriendEmailMessageTooLong"]);
	    objEmailMessage.focus();
	    return false;	    
	}
	
	// Check a template has been chosen
	var objTemplateRadioButtons = objForm['uiEmailTemplate'];
	if (typeof(objTemplateRadioButtons) != 'undefined')
	{
	    var templateSelected = false;
	    if (typeof(objTemplateRadioButtons.length) != 'undefined')
	    {   
	        for (var i = 0; i < objTemplateRadioButtons.length; i++)
	        {
	            if (objTemplateRadioButtons[i].checked)
	            {
	                templateSelected = true;
	                break;
	            }
	        }
	    }
	    else
	    {
	        templateSelected = objTemplateRadioButtons.checked;
	    }
	    if (!templateSelected)
	    {
	        alert(_messages["InviteAFriendNoEmailTemplateSelected"]);
	        return false;	  
	    }
	}
	return true;	
}

function InviteAFriendFriendValid(objName, objEmail)
{
	var objStringUtils = new CSoftixUtils;
    var strName = objStringUtils.strTrim(objName.value);
    var strEmail = objStringUtils.strTrim(objEmail.value);
    if ((strName.length == 0 || typeof(strName) == 'undefined') && 
        (strEmail.length == 0 || typeof(strEmail) == 'undefined'))
    {
        return -1;
    }
    else if (strName.length == 0 || typeof(strName) == 'undefined')
    {
        alert(_messages["InviteAFriendNameEmpty"]);
        objName.focus();
        return 0;
    }
    else if (strEmail.length == 0 || typeof(strEmail) == 'undefined')
    {
        alert(_messages["InviteAFriendEmailEmpty"]);
        objEmail.focus();
        return 0;
    }
    else if (!ValidateCharSet(objName) || !ValidateCharSet(objEmail))
    {
        return 0;
    }
    else if (!ValidateEmail(strEmail))
    {
        alert(_messages["InviteAFriendEmailInvalid"]);
        objEmail.focus();
        return 0;
    }
    else
    {
        return 1;
    }
}

function resizeParentModalPopupWindow()
{
    // We want the actual height of the content not of the frame
    window.parent.resizeModalPopWindow(document.forms[0].offsetHeight);
    return;
}

function resizeAndCentreParentModalPopupWindow()
{
    //make sure we are at the top/left
    window.parent.document.body.scrollLeft=0;
    window.parent.document.body.scrollTop=0;
    //Set the size
    resizeParentModalPopupWindow();
    //Place into the centre
    window.parent.centerPopWin(null, null, true);
}

/*
    Invite a friend page methods
*/

function inviteAFriendSetKeyHandlers()
{
    if (!document.all)
    {
        var objFirstElement = getFirstTabbableNode();
        var objLastElement = getLastTabbableNode();
        if (objFirstElement != null && objLastElement != null)
        {
            if (objFirstElement == objLastElement)
            {
                // if they are the same we need to disable tab key
                objFirstElement.onkeydown = disableTabbingEventHandler;
            }
            else
            {
                objFirstElement.onkeydown = inviteAFriendHandleFirstElementTabbing;
                objLastElement.onkeydown = inviteAFriendHandleLastElementTabbing;
            }
        }
    }
}

function inviteAFriendHandleFirstElementTabbing(e)
{
    if (e.keyCode == 9 && e.shiftKey) 
    { 
        var objLastElement = getLastTabbableNode();
        if (objLastElement != null) objLastElement.focus(); 
        if (typeof(e.preventDefault) != 'undefined') e.preventDefault();
        return false; 
    }
}

function inviteAFriendHandleLastElementTabbing(e)
{
    if (e.keyCode == 9 && !e.shiftKey) 
    { 
        var objFirstElement = getFirstTabbableNode();
        if (objFirstElement != null) objFirstElement.focus(); 
        if (typeof(e.preventDefault) != 'undefined') e.preventDefault();
        return false; 
    }
}

/*
    Some generic methods to do with focus/tabbing/elements
*/

function getFirstTabbableNode()
{
    var objFirstLink = null;
    for (var i = 0; i < document.links.length; i++)
    {
        if (isNodeVisible(document.links[i]))
        {
            objFirstLink = document.links[i];
            break;    
        }   
    }
    var objFirstElement = getFirstVisibleElement();
    if (objFirstLink == null) return objFirstElement;
    else if (objFirstElement == null) return objFirstLink;
    //check which is first!      
    return whichNodeIsFirst(objFirstLink, objFirstElement);
}

function getLastTabbableNode()
{
    var objLastLink = null;
    for (var i = document.links.length - 1; i >= 0; i--)
    {
        if (isNodeVisible(document.links[i]))
        {
            objLastLink = document.links[i];
            break;    
        }   
    }
    var objLastElement = getLastVisibleElement();
    if (objLastLink == null) return objLastElement;
    else if (objLastElement == null) return objLastLink;
    //check which is first and then use the other one!      
    var objFirst = whichNodeIsFirst(objLastLink, objLastElement);
    if (objFirst == null) return null;
    else if (objFirst = objLastLink) return objLastElement;
    else objLastLink; 
}

function whichNodeIsFirst(objNodeOne, objNodeTwo)
{
    var objNodeOneParents = getParentsArray(objNodeOne);
    var objNodeTwoParents = getParentsArray(objNodeTwo);
    for (var i = 0; i < objNodeOneParents.length; i++)
    {
        if (i >= objNodeTwoParents.length) break; 
        if (objNodeOneParents[i] != objNodeTwoParents[i])
        {
            if (i == 0) break; 
            for (var j = 0; j < objNodeOneParents[i - 1].childNodes.length; j++)
            {
                if (objNodeOneParents[i - 1].childNodes[j] == objNodeOneParents[i])
                {
                    return objNodeOne;
                }
                if (objNodeOneParents[i - 1].childNodes[j] == objNodeTwoParents[i])
                {
                    return objNodeTwo;
                }
            }
            break;
        }
    }
    return null;
}

function getParentsArray(objNode)
{
    var i = 1;
    var objParentNode = objNode;
    while (objParentNode != document)
    {
        i++;
        objParentNode = objParentNode.parentNode
    }
    var objParents = new Array(i);
    objParentNode = objNode;
    for (var j = i - 1; j >= 0; j--)
    {
        objParents[j] = objParentNode;
        objParentNode = objParentNode.parentNode;
    }
    return objParents;
}

function disableTabbingEventHandler(e)
{
    if (e.keyCode == 9) 
    {
        if (typeof(e.preventDefault) != 'undefined') e.preventDefault();
        return false;
    }
}

function setFocusToFirstElement()
{
    var objElement = getFirstVisibleElement();
    if (objElement != null) objElement.focus();
}

function getFirstVisibleElement()
{
    for (var i = 0; i < document.forms.length; i++)
    {
        for (var j = 0; j < document.forms[i].elements.length; j++)
        {
            var objElement = document.forms[i].elements[j];
            if (isNodeVisible(objElement)) return objElement;
        }
    }
    return null;
}

function isNodeVisible(objNode)
{
    if (objNode.tagName.toUpperCase() != 'INPUT' || objNode.type.toLowerCase() != 'hidden')
    {
        var objCheckNode = objNode
        while (objCheckNode != null)
        {
            if (objCheckNode == document) break;
            if (typeof(objCheckNode.style) != 'undefined' && 
                    (objCheckNode.style.display == 'none' || objCheckNode.style.visibility == 'hidden'))
            {
                return false;
            }
            objCheckNode = objCheckNode.parentNode;
        }
        return true;
    }
    else
    {
        return false;
    }
}

function getLastVisibleElement()
{
    for (var i = document.forms.length - 1; i >= 0; i--)
    {
        for (var j = document.forms[i].elements.length - 1; j >= 0; j--)
        {
            var objElement = document.forms[i].elements[j];
            if (objElement.tagName.toUpperCase() != 'INPUT' || 
                objElement.type.toLowerCase() != 'hidden')
            {
                if (objElement.style.display != 'none' && objElement.style.visibility != 'hidden')
                {
                    return objElement;
                }
            }
        }
    }
    return null;
}

function inviteAFriendHoldNumberChanged(objDropDown, controlContainerID)
{
    if (typeof(objDropDown) != 'undefined')
    {
        var objContainer = document.getElementById(controlContainerID);
        if (typeof(objContainer) != 'undefined')
        {
            if (objDropDown.selectedIndex >= 0 && 
                parseInt(objDropDown.options[objDropDown.selectedIndex].value, 10) > 0)
            {
                objContainer.style.display = 'block';
            }
            else
            {
                objContainer.style.display = 'none';
            }
        }
    }
}

/*
    Two functions to add and remove prompt text from text boxes on entering and leaving the text box
*/
function removeTextBoxPrompt(objField, strPrompt)
{
    if (objField != null)
    {
        if (objField.value == strPrompt) objField.value = '';
    }
}
function addTextBoxPrompt(objField, strPrompt)
{
    if (objField != null)
    {
        var objStringUtils = new CSoftixUtils();
        if (objStringUtils.strTrim(objField.value) == '') objField.value = strPrompt;
    }
}

/*
    Validates entry in the event selector (search) control
*/
function EventSelectorValid(thisForm, keywordsControlId, categoryControlId,
    locationControlID, dateControlID, keywordPrompt, datePrompt)
{
    var isValid = false;
    var objStringUtils = new CSoftixUtils();
    var objKeywords = objField(thisForm, keywordsControlId, '');
    var objCategories = objField(thisForm, categoryControlId, '');
    var objRegions = objField(thisForm, locationControlID, '');	
    var objDate = objField(thisForm, dateControlID, '');					
	if (typeof(objKeywords) != 'undefined' &&  objStringUtils.strTrim(objKeywords.value) != '' &&
        objKeywords.value != keywordPrompt)
    {            
	    if (!ValidateCharSet(objKeywords)) 
	    {
	        isValid = false;
	    }
	    else
	    {
            isValid = true;
        }
    }
	if (typeof(objCategories) != 'undefined' && objCategories.selectedIndex > 0)
    {
        isValid = true;
    }
    if (typeof(objRegions) != 'undefined' && objRegions.selectedIndex > 0)
    {
        isValid = true; 
    }
    if (typeof(objDate) != 'undefined' &&  objStringUtils.strTrim(objDate.value) != '' &&
        objDate.value != datePrompt)
    {                    
	    if (!ValidateCharSet(objDate)) 
	    {
	        isValid = false;
	    }
	    else
	    {
	        var parsedDate = Date.parse(objStringUtils.strFormatDate(objDate.value));
	        var invalidDate = isNaN(parsedDate);
	        
	        if (!invalidDate)
	        {
	            var year = (new Date(parsedDate)).getFullYear();
	            if (year < 1900 || year > 10000) 
	            {
	                invalidDate = true;
	            }
	        }
	        
            if (invalidDate)
            {
                alert(_messages['EventSelectorDateInvalid']);
                return false;
            }
            isValid = true;
        }
    }
	if (isValid == false)
	{
	    alert(_messages['SelectAnEvent']);
	}
    return isValid;
}

function highlightCurrentDeliveryMethod(normalClass, selectedClass)
{
	$('.deliveryOptions :radio').each(function()
	{
		var removeClass = (this.checked) ? normalClass : selectedClass;
		var addClass = (this.checked) ? selectedClass : normalClass;
		$(this).parent().parent().removeClass(removeClass).addClass(addClass);
	});
}

function setTextareaLineLimit(id, maxLines)
{
	$('#' + id)
		.keypress(function(e) 
			{
				if (this.value.split('\n').length >= maxLines &&
					(e.which == 10 || e.which == 13))
					return false; 
			})
		.bind('input', function() { trimTextAreaLines(this, maxLines); })
		.change(       function() { trimTextAreaLines(this, maxLines); })
		.focus(        function() { trimTextAreaLines(this, maxLines); })
		.mouseover(    function() { trimTextAreaLines(this, maxLines); })
		.mouseout(     function() { trimTextAreaLines(this, maxLines); })
		.bind('paste', function() 
			{
				var textarea = this;
				// This doesn't seem to work without a delay (crazy!)
				setTimeout(function() { trimTextAreaLines(textarea, maxLines);  }, 50);
			})
		.each(function() { trimTextAreaLines(this, maxLines); });
}

function trimTextAreaLines(textarea, maxLines)
{	
	var lines = textarea.value.split('\n');
	if (lines.length > maxLines)
	{
		lines.length = maxLines;
		textarea.value = lines.join('\n').replace(/\s+$/, '');
	}
}

