/*
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 ValidateAccountPremiumSms(controlID, phoneControlID, internationalCode, numberPattern) {

    var control = document.getElementById(controlID);
    var phoneControl = document.getElementById(phoneControlID);

    if (control == null) {
        return true;
    }

    var phoneNumber = (phoneControl == null) ? '' : jQuery.trim(phoneControl.value);

    if (phoneNumber.length == 0) {
        if ($(control).find('input:checkbox:checked').length > 0) {
            alert(_messages['AccountPremiumSmsPhoneNumberRequired']);
            if (phoneControl != null) phoneControl.focus();
            return false;
        }
    }
    else if (!phoneControl.disabled) {
        phoneNumber = phoneNumber.replace(/\D/g, '');

        if (phoneNumber.charAt(0) == '0') {
            phoneNumber = phoneNumber.substring(1);
        }

        phoneNumber = internationalCode + phoneNumber;

        if (!numberPattern.test(phoneNumber)) {
            alert(_messages['AccountPremiumSmsPhoneNumberInvalid']);
            phoneControl.focus();
            return false;
        }
    }

    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;
            var objPassword = $("input[id*='uiEntitlementPassword']", div).get(0);
            var password = (objPassword == null ? null : objPassword.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, null) || !ticketContainers[priceType].Add(priceType, number, password)) {
                    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, password) {
    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 if (password != null) {
            alert(
				_messages["MaxEntitlementTicketsMultiPassword"]
					.replace(/\{0\}/g, this.MaxTickets)
					.replace(/\{1\}/g, "\"" + this.PriceTypes.join("\", \"") + "\"")
					.replace(/\{2\}/g, password));
        }
        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;
// TODO: remove line below if implementing overloay style purchase popup
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;

    // TODO: change if implementing overloay style purchase popup
    gobjBasketPurchasingWindow = OpenWindow("PurchasePopup.aspx", 400, 260);
    /*ShowContentPopupOverlayFrameNoClose("BasketOffers.PurchaseProcessing.Title", "BasketOffers.PurchaseProcessing", 600, 600);*/

    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;
}

// TODO: remove method below if implementing overloay style purchase popup
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 (typeof (objState) != 'undefined' && 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 (typeof (objState) != 'undefined' && 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);
    // 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+$/, '');
    }
}

function ValidateNewWaitlistSubscription(eventListId, ticketsRequestedListId) 
{
	var eventList = document.getElementById(eventListId);
	var ticketsRequestedList = document.getElementById(ticketsRequestedListId);
	
	if (eventList == null)
		return true;

	if (eventList.selectedIndex < 1)
	{
		alert(_messages["WaitlistEventNotSelected"]);
		return false;
	}

	if (ticketsRequestedList != null && ticketsRequestedList.selectedIndex < 1) 
	{
		alert(_messages["WaitlistTicketsRequiredNotSelected"]);
		return false;
	}

	return true;
}
