//place the following line in the header of the page that you want to include this file in
//<script src="/jscript/validation.js" type="text/javascript"></script>

function standardValidation_CSS(frm, fieldNames)
{
    var fields = fieldNames.split(",");
    var validationReturn = true;
    var fieldValue = "";
    var rExp = / /gi;

    for (x = 0; x < fields.length; x++)
    {
        fieldValue = frm[fields[x]].value;
        fieldValue = fieldValue.replace(rExp, '');
        
        if (fieldValue.length == 0)
        {
            validation_changeErrorDisplay(fields[x]);
            validationReturn = false;
        }
    }
    return validationReturn;
}
function validation_changeErrorDisplay(fieldName, displayType, newMessage)
{
    var errorDiv = document.getElementById(fieldName + "_Error");

    if (displayType == null || displayType == '') displayType = 'inline';
    
    if (errorDiv != null)
    {
        errorDiv.style.display = displayType;
        
        if (newMessage != null)
        {
            errorDiv.innerHTML = newMessage;
        }
    }
}
function validation_hideAllErrors(fieldNames)
{
    var fields = fieldNames.split(",");
    
    for (x = 0; x < fields.length; x++)
    {
        validation_changeErrorDisplay(fields[x], 'none');
    }
}

function changeDeferral(section)
{
    //changes the terms of deferral dates
    //used on pages that modify deferral dates (eg: modifyAccount, userresults [admin])
    //****************************************************
    //REQUIRES dateFormat.js TO BE INCLUDED ON PARENT PAGE
    //****************************************************

    var strNewDeferralDate;
    if (section == "modDeferral")
    {
        strNewDeferralDate = document.formDeferralChange.txtDeferralDate.value;
    }
    else
    {
        strNewDeferralDate = document.formDeferAccount.txtDeferralDate.value;
    }

    if (strNewDeferralDate == '') return;

    var dtNewDeferralDate = new Date(strNewDeferralDate);
    diff.setTime(dtNewDeferralDate.getTime() - dtOriginalDeferralDate.getTime());
    timediff = diff.getTime();
    var days = Math.floor(timediff / (1000 * 60 * 60 * 24));
    //alert('dtNewDeferralDate:' + dtNewDeferralDate +'dtOriginalDeferralDate:' + dtOriginalDeferralDate + 'days:' + days);

    def1 = document.getElementById(section + "1");
    def2 = document.getElementById(section + "2");
    def3 = document.getElementById(section + "3");
    //add a day to the date
    dtNewExpiration = new Date(dtOriginalExpiration);
    dtNewExpiration.setDate(dtNewExpiration.getDate() + days);
    if (def1 != null) def1.innerHTML = strNewDeferralDate;
    if (def2 != null) def2.innerHTML = strNewDeferralDate;
    if (def3 != null) def3.innerHTML = dtNewExpiration.format("mm/dd/yyyy hh:MM TT");
}

function checkIntField(theForm, fieldName, fieldDescription, isRequired)
{
    //used to check that a field is numeric (will rip out $ and ,)
    //Input :
    //  frm (object) (the form object)
    //  fieldName (string) (name of the input field)
    //  fieldDescription (string) (description of field to be used in alert
    //  isRequired (bool) (if false then i will return true if the field is empty)
    //Output :
    //  returns true if value is numeric (or if field is blank and isRequired is false)
    //  returns false if value is not numeric (or if field is blank and isRequired is true)

    var fieldValue = theForm[fieldName].value;

    rExp = '\$';
    fieldValue = fieldValue.replace(rExp, '');
    rExp = /,/gi;
    fieldValue = fieldValue.replace(rExp, '');

    theForm[fieldName].value = fieldValue;

    if (fieldValue == '' && isRequired)
    {
        alert('Please fill out the ' + fieldDescription + ' field.');
        theForm[fieldName].focus();

        return false;
    } else if (fieldValue == '')
    {
        return true;
    }
    if (isNaN(fieldValue))
    {
        alert('The ' + fieldDescription + ' must be a numeric value.');
        theForm[fieldName].focus();
        return false;
    }
    return true;
}

function checkRadio(theForm, fieldName, numberOfRadioButtons, errorMessage)
{
    //used to validate a set of radio buttons (make sure one is selected
    //Input:
    //  frm (object) (the form object)
    //  fieldName (string) (name of the radio buttons)
    //  numberOfRadioButtons (int) (the number of possible radio buttons: usually 2)
    //  errorMessage (string) (message to be displayed if a radio is not selected
    //Output:
    //  Returns true if a radio is selected
    //  Returns false if not and alerts user and places focus on the field in question
    var optionChecked = false;
    
    for (x = 0; x < numberOfRadioButtons; x++)
    {
        if (theForm[fieldName][x].checked)
        {
            optionChecked = true;
            break;
        }
    }

    if (!optionChecked)
    {
        alert(errorMessage);
        theForm[fieldName][0].focus();
        return false;
    }
    return true;
}

function checkPhoneNumber(frm, areaCodeFieldName, prefixFieldName, suffixFieldName, extFieldName, optionalField, fieldDescription, cssId)
{
    //used to validate a phone number 
    //Input:
    //  frm (object) (the form object)
    //  areaCodeFieldName (string) (name of the area code field)
    //  prefixFieldName (string) (name of the prefix field)
    //  suffixFieldName (string) (name of the suffix field)
    //	extFieldName (string) name of the extension field
    //	optionalField (boolean) if true function will not error out if the entire phone field is blank
    // 	fieldDescription (string) describes the field other than "phone" (eg: fax)
    //	cssId (string) id for the CSS class to be shown instead of the alert
    //Output:
    //  Returns true if the phone number is valid
    //  Returns false if not and places focus on the field in question
    var rExp = / /gi;

    //if the field is optional, then return true if all the field are empty
    var fieldValue = frm[areaCodeFieldName].value + frm[prefixFieldName].value + frm[suffixFieldName].value + frm[extFieldName].value;

    fieldValue = fieldValue.replace(rExp, '');

    if (optionalField == true && fieldValue == '') return true;

    //check area code
    areaCodeValue = frm[areaCodeFieldName].value;
    areaCodeValue = areaCodeValue.replace(rExp, '');
    frm[areaCodeFieldName].value = areaCodeValue;

    if (fieldDescription == null || fieldDescription == '') fieldDescription = 'Phone';
    fieldDescription += ' ';
    useCSS = false;
    if (cssId != null) useCSS = true;
    if (isNaN(areaCodeValue) || areaCodeValue.length != 3)
    {
        if (useCSS)
        {
            if (isNaN(areaCodeValue))
            {
                validation_changeErrorDisplay(cssId, '', 'Please enter a valid ' + fieldDescription + 'Number');
            } else
            {
                validation_changeErrorDisplay(cssId);
            }
        } else
        {
            alert('Your ' + fieldDescription + 'area code does not appear to be valid.');
            frm[areaCodeFieldName].focus();
        }
        return false;
    }
    //check prefix
    prefixValue = frm[prefixFieldName].value;
    prefixValue = prefixValue.replace(rExp, '');
    frm[prefixFieldName].value = prefixValue;

    if (isNaN(prefixValue) || prefixValue.length != 3)
    {
        if (useCSS)
        {
            if (isNaN(prefixValue))
            {
                validation_changeErrorDisplay(cssId, '', 'Please enter a valid ' + fieldDescription + 'Number');
            } else
            {
                validation_changeErrorDisplay(cssId);
            }
        } else
        {
            alert('Your ' + fieldDescription + 'prefix does not appear to be valid.');
            frm[prefixFieldName].focus();
        }
        return false;
    }
    //check suffix
    suffixValue = frm[suffixFieldName].value;

    suffixValue = suffixValue.replace(rExp, '');
    frm[suffixFieldName].value = suffixValue;
    if (isNaN(suffixValue) || suffixValue.length != 4)
    {
        if (useCSS)
        {
            if (isNaN(suffixValue))
            {
                validation_changeErrorDisplay(cssId, '', 'Please enter a valid ' + fieldDescription + 'Number');
            } else
            {
                validation_changeErrorDisplay(cssId);
            }
        } else
        {
            alert('Your ' + fieldDescription + 'suffix does not appear to be valid.');
            frm[suffixFieldName].focus();
        }
        return false;
    }
    //check extnsension
    extValue = frm[extFieldName].value;
    extValue = extValue.replace(rExp, '');
    frm[extFieldName].value = extValue;

    if (isNaN(extValue))
    {
        if (useCSS)
        {
            validation_changeErrorDisplay(cssId, '', 'Please enter a valid ' + fieldDescription + 'Number');
        } else
        {
            alert('Your ' + fieldDescription + 'extension does not appear to be valid.');
            frm[extFieldName].focus();
        }
        return false;
    }
    return true;
}

function checkZipCode(frm, fieldName)
{
    //used to validate a zip code
    //Input:
    //  frm (object) (the form object)
    //  fieldName (string) (name of the zip code field)
    //Output:
    //  Returns true if the zip code is valid
    //  Returns false if not and places focus on the field in question
    var zipCode = frm[fieldName].value;

    var rExp = / /gi;
    zipCode = zipCode.replace(rExp, '');

    frm[fieldName].value = zipCode;

    if (isNaN(zipCode) || zipCode.length != 5)
    {
        alert('You must enter a 5 digit numeric zip code');
        frm[fieldName].focus();
        return false;
    }
    return true;
}

function g_fnCheckEmail(poForm, psFieldName)
{

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // New Email validation
    // Returns true if the email address is valid else Returns false
    // and places focus on the field
    // Email is not allow any invalid Email characters
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    var lsEmail = poForm[psFieldName].value;

    var rExp = /^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z]*[-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/gi;

    if (lsEmail == '')
    {	// not empty
        poForm[psFieldName].focus();
        return false;
    }

    if (!rExp.test(lsEmail))
    {		//not allow any invalid Email characters
        poForm[psFieldName].focus();
        return false;
    }

    return true;

}

function g_fnCheckCreditCard(psValue)
{
    psValue = psValue.replace(/ /gi, '').replace(/-/gi, '');

    if (isNaN(psValue) || psValue.length > 16 || psValue.length < 13)
    {
        return false;
    }
    if (psValue.indexOf(".") >= 0)
    {
        return false;
    }
    return true;
}


function checkEmail(frm, fieldName, useCSS)
{
    //used to validate an email address.
    //Input:
    //  frm (object) (the form object)
    //  fieldName (string) (name of the email field)
    //Output:
    //  Returns true if the email address is valid
    //  Returns false if not and places focus on the field in question
    var email;
    var emailErrorMsg = "";
    var validationReturn = true;

    var email = frm[fieldName].value;

    if (useCSS == null) useCSS = false;
    var rExp = / /gi;
    email = email.replace(rExp, '');
    rExp = /\.\./gi;
    email = email.replace(rExp, '.');
    rExp = /,/gi;
    email = email.replace(rExp, '.');

    frm[fieldName].value = email;

    if (email == '')
    {
        emailErrorMsg = 'You must enter an e-mail address.';
        validationReturn = false;
    } else
    {
        atLoc = email.indexOf('@');
        dotLoc = email.indexOf('.');
        forwardSlashLoc = email.indexOf('/');
        backSlashLoc = email.indexOf('\\');
        secondAtLoc = email.indexOf('@', atLoc + 1);
        wwwLoc = email.indexOf('www');
        semiColonLoc = email.indexOf(';');
        quoteLoc = email.indexOf("'");
        doubleQuoteLoc = email.indexOf('"');
        emailLen = email.length - 1;
        if (atLoc < 1 || dotLoc < 0 || emailLen < 5 || email.charAt(emailLen) == '.' || (atLoc + 1) == dotLoc)
        {
            emailErrorMsg = 'It appears that you did not enter a valid email address.';
            validationReturn = false;
        } else if (secondAtLoc != -1)
        {
            emailErrorMsg = 'This is not a valid email address. There are two @ symbols in your entry. Please enter only one email address.';
            validationReturn = false;
        } else if (forwardSlashLoc != -1 || backSlashLoc != -1)
        {
            emailErrorMsg = 'This is not a valid email address. Please do not use any slashes (eg: /) in your email address.';
            validationReturn = false;
        } else if (wwwLoc != -1 && confirm('Most email addresses do not have a www in them. Would you like to change your entry?'))
        {
            validationReturn = false;
        } else if (semiColonLoc != -1)
        {
            emailErrorMsg = 'This is not a valid email address. Please do not use any semi-colons in your email address.';
            validationReturn = false;
        } else if (quoteLoc != -1 || doubleQuoteLoc != -1)
        {
            emailErrorMsg = 'This is not a valid email address. Please do not use any quotes or double quotes in your email address.';
            validationReturn = false;
        }

    }
    if (!validationReturn)
    {
        if (useCSS)
        {
            validation_changeErrorDisplay(fieldName, "", emailErrorMsg);
        } else
        {
            alert(emailErrorMsg);
            frm[fieldName].focus();
        }
    }
    return validationReturn;
}

function checkCCNumber(frm, fieldName, useCSS)
{
    //used to validate a credit card number
    //Input:
    //  frm (object) (the form object)
    //  fieldName (string) (name of the credit card number field)
    //Output:
    //  Returns true if the cc number is valid
    //  Returns false if not and places focus on the field in question
    var ccNumber = frm[fieldName].value;
    rExp = / /gi;
    ccNumber = ccNumber.replace(rExp, '');
    rExp = /-/gi;
    ccNumber = ccNumber.replace(rExp, '');
    if (useCSS != null) useCSS = true;
    if (isNaN(ccNumber) || ccNumber.length > 16 || ccNumber.length < 13)
    {
        if (useCSS)
        {
            validation_changeErrorDisplay(fieldName, "", "Your credit card number does not appear to be valid.");
        } else
        {
            alert('Your credit card number does not appear to be valid.');
            frm[fieldName].focus();
        }
        return false;
    }
    if (ccNumber.indexOf(".") >= 0)
    {
        if (useCSS)
        {
            validation_changeErrorDisplay(fieldName, "", "Your credit card number contains invalid characters. Please do not use punctuation like periods and dashes.");
        } else
        {
            alert('Your credit card number contains invalid characters. Please do not use punctuation like periods and dashes.');
            frm[fieldName].focus();
        }
        return false;
    }
    return true;
}

function checkABARoutingNumber(frm, fieldName, useCSS)
{
    //used to validate Routing Number for ACH Transaction
    //Input:
    //  frm (object) (the form object)
    //  fieldName (string) (name of the Routing number field)
    //Output:
    //  Returns true if the Routing Number is valid
    //  Returns false if not and places focus on the field in question

    var strFieldValue = frm[fieldName].value;
    if (useCSS != null) useCSS = true;

    // First, remove any non-numeric characters.
    strABARoutingNumber = "";
    for (i = 0; i < strFieldValue.length; i++)
    {
        c = parseInt(strFieldValue.charAt(i), 10);
        if (c >= 0 && c <= 9)
            strABARoutingNumber = strABARoutingNumber + c;
    }

    // Check the length, it should be nine digits.
    if (strABARoutingNumber.length != 9)
    {
        if (useCSS)
        {
            if (strABARoutingNumber.length == 0)
            {
                validation_changeErrorDisplay(fieldName);
            } else
            {
                validation_changeErrorDisplay(fieldName, '', 'Your Routing Number does not appear to be valid');
            }
        } else
        {
            alert('Your Routing number does not appear to be valid.');
            frm[fieldName].focus();
        }
        return false;
    }

    // Now run through each digit and calculate the total.

    n = 0;
    for (i = 0; i < strABARoutingNumber.length; i += 3)
    {
        n += parseInt(strABARoutingNumber.charAt(i), 10) * 3
	 + parseInt(strABARoutingNumber.charAt(i + 1), 10) * 7
	 + parseInt(strABARoutingNumber.charAt(i + 2), 10);
    }

    // If the resulting sum is an even multiple of ten (but not zero),
    // the aba routing number is good.

    if (n != 0 && n % 10 == 0)
    {
        return true;
    } else
    {
        if (useCSS)
        {
            validation_changeErrorDisplay(fieldName, '', 'Your Routing Number does not appear to be valid');
        } else
        {
            alert('Your Routing number does not appear to be valid.');
            frm[fieldName].focus();
        }
        return false;
    }


}

function standardValidation(frm, fieldNames, fieldDesc)
{
    //used to validate that fields are not blank
    //Input:
    //  frm (the form object)
    //  fieldNames (a csv string of the html names of the fields that are too be tested)
    //  fieldDesc (a description of the above fieldNames, MUST contain a description for each field passed)
    //Output:
    //  Returns true if all fields are valid
    //  Returns false if not and places focus on the field in question

    var fields = fieldNames.split(",");
    var desc = fieldDesc.split(",");

    var fieldValue = "";

    for (x = 0; x < fields.length; x++)
    {
        fieldValue = frm[fields[x]].value;

        rExp = / /gi;
        fieldValue = fieldValue.replace(rExp, '');

        if (fieldValue.length == 0)
        {
            alert('The ' + desc[x] + ' field is required.');

            frm[fields[x]].focus();
            return false;
        }
    }
    return true;
}


// currently used by BHD to validate password.
function checkPassword(frm, fieldName)
{
    //used to validate a password
    //Input:
    //  frm (object) (the form object)
    //  fieldName (string) (name of the credit card number field)
    //Output:
    //  Return true if password contains letters, numbers and underscore and
    //  the length is between 4 and 10.
    //  Returns false otherwise

    var pswd = frm[fieldName].value;

    if (pswd.length < 4 || pswd.length > 10)
    {
        alert('Your password should be between 4 and 10 characters long.');
        frm[fieldName].focus();
        return false;
    }

    tomatch = /^[a-zA-Z0-9_]+$/;  //regular expression shortcut would be /^\w+$/
    if (!tomatch.test(pswd))
    {
        alert("Password can only contain letters, numbers, and underscores");
        frm[fieldName].focus();
        return false;
    }

    return true;
}


// Validation symbol groups
var RE_NUMBERS_GROUP = "0-9";
var RE_ACCENTED_GROUP = "\\x8A\\x8E\\x9A\\x9E\\x9F\\xC0\\xC1\\xC2\\xC3\\xC4\\xC5\\xC7\\xC8\\xC9\\xCA\\xCB\\xCC\\xCD\\xCE\\xCF\\xD1\\xD2\\xD3\\xD4\\xD5\\xD6\\xD9\\xDA\\xDB\\xDC\\xDD\\xDE\\xDF\\xE0\\xE1\\xE2\\xE3\\xE4\\xE5\\xE8\\xE9\\xEA\\xEB\\xEC\\xED\\xEE\\xEF\\xF1\\xF2\\xF3\\xF4\\xF5\\xF6\\xF9\\xFA\\xFB\\xFC\\xFD\\xFE\\xFF";
var RE_BASIC_GROUP = "a-zA-Z";
var RE_COMMONSPECIAL_GROUP = "\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2A\\x2C\\x2D\\x2E\\x2F\\x5B\\x5C\\x5D\\x5E\\x5F\\x7B\\x7C\\x7D\\x7E\\x81";
var RE_SPECIAL_GROUP = "\\x2B\\x3A\\x3B\\x3C\\x3D\\x3E\\x3F\\x40\\x60\\x80\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8B\\x8C\\x8D\\x8F\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9B\\x9C\\x9D\\xA0\\xA1\\xA2\\xA3\\xA4\\xA5\\xA6\\xA7\\xA8\\xA9\\xAA\\xAB\\xAC\\xAD\\xAE\\xAF\\xB0\\xB1\\xB2\\xB3\\xB4\\xB5\\xB7\\xB8\\xB9\\xBA\\xBB\\xBC\\xBD\\xBE\\xBF\\xC6\\xD0\\xD7\\xD8\\xE6\\xE7\\xF0\\xF7\\xF8";
var RE_APOSTROPHE = "'";
var RE_SPACE = "\\s";
var RE_DASH = "\\-";
var RE_COMMA = ",";
var RE_DOT = "\\.";
var RE_NUMBERSIGN = "#";
var RE_SLASH = "/";
var RE_ASTERISK = "\\*";
var RE_AMPERSAND = "\\&";
var RE_DOUBLEQUOTE = "\\\"";
var RE_EMAIL = "^[a-zA-Z0-9]+([_.-]?[a-zA-Z0-9]*)*@[a-zA-Z0-9]+([_-]?[a-zA-Z0-9]+)*([.]{1})[a-zA-Z0-9]+([.]?[a-zA-Z0-9]+)*$";



// validation common methods

function _getRegexExp()
{
    var reg = "/^[";
    var postfix = "+";
    var minCharCount;
    var maxCharCount;


    for (var i = 0; i < arguments.length; i++)
    {

        if (i == 0 && !isNaN(arguments[i]))
        {
            minCharCount = arguments[i];
        }


        if (i == 1 && !isNaN(arguments[i]))
        {
            maxCharCount = arguments[i];
        }

        if (isNaN(arguments[i]))
        {
            reg += arguments[i];
        }
    }
    if (minCharCount != undefined && maxCharCount != undefined)
    {
        postfix = "{" + minCharCount + "," + maxCharCount + "}";
    }
    else if (minCharCount != undefined)
    {
        postfix = "{" + minCharCount + "}";
    }

    return eval(reg + "]" + postfix + "$/i");
}

function _validateFieldRegEx(value, expression, errorList, invError, reqError)
{

    var result = true;

    if (value)
    {
        if (!value.match(expression))
        {
            _addErrorToList(errorList, invError);
            result = false;
        }
    }
    else if (typeof (reqError) != 'undefined' && reqError !== null && reqError !== '')
    {
        _addErrorToList(errorList, reqError);
        result = false;
    }

    return result;
}

function _addErrorToList(errorList, error)
{
    errorList.push(error);
}

function _initErrorsObj(errorsObject, fields)
{
    if (typeof (errorsObject) != 'undefined' && errorsObject != null)
    {
        for (i in fields)
        {
            errorsObject[fields[i]] = []; // create new array
        }
    }
}

function _processLastErrors(field, lastErrors, errorList, errorsObject)
{
    if (typeof (lastErrors) != 'undefined' && lastErrors != null)
    {
        if (typeof (errorList) != 'undefined' && errorList != null)
        {
            _pushErrorList(errorList, lastErrors);
        }

        if (typeof (errorsObject) != 'undefined' && errorsObject != null && typeof (field) != 'undefined' && field != null)
        {
            errorsObject[field] = lastErrors;
        }

    }

}

function _pushErrorList(errorList, lastErrors)
{
    for (i = 0; i < lastErrors.length; i++)
    {
        errorList.push(lastErrors[i]);
    }
}

// rot13
var _rot13map;

function _rot13init()
{
    var map = new Array();
    var s = "abcdefghijklmnopqrstuvwxyz";
    for (i = 0; i < s.length; i++)
        map[s.charAt(i)] = s.charAt((i + 13) % 26);
    for (i = 0; i < s.length; i++)
        map[s.charAt(i).toUpperCase()] = s.charAt((i + 13) % 26).toUpperCase();
    return map;
}

function _rot13(a)
{
    if (!_rot13map)
        _rot13map = _rot13init();
    s = "";
    for (i = 0; i < a.length; i++)
    {
        var b = a.charAt(i);
        s += (b >= 'A' && b <= 'Z' || b >= 'a' && b <= 'z' ? _rot13map[b] : b);
    }
    return s;
}



function _fnParseInt(strVal)
{
    return parseInt(strVal, 10);
}

// billing address validation common methods and initialization

var _billingAddressIsInited = false;
var _billingAddressDomesticAddressRegEx = null;
var _billingAddressInternationalAddressRegEx = null;
var _billingAddressDomesticCityTowsRegEx = null;
var _billingAddressInternationalCityTowsRegEx = null;
var _billingAddressProvinceRegEx = null;
var _billingAddressPostalCodeRegEx = null;
var _billingAddressStateRegEx = null;
var _billingAddressZipCodeRegEx = null;
var _billingAddressCountryRegEx = null;

function _initBillingAddress()
{
    if (!_billingAddressIsInited)
    {
        _addressConstInit();

        _billingAddressDomesticAddressRegEx = _getRegexExp(1, 50, RE_BASIC_GROUP,
			RE_ACCENTED_GROUP,
			RE_NUMBERS_GROUP,
			RE_NUMBERSIGN,
			RE_DASH,
			RE_COMMA,
			RE_DOT,
			RE_SLASH,
			RE_APOSTROPHE,
			RE_SPACE);

        _billingAddressInternationalAddressRegEx = _getRegexExp(1, 50, RE_BASIC_GROUP,
			RE_ACCENTED_GROUP,
			RE_NUMBERS_GROUP,
			RE_NUMBERSIGN,
			RE_DASH,
			RE_COMMA,
			RE_DOT,
			RE_SLASH,
			RE_APOSTROPHE,
			RE_SPACE);

        _billingAddressDomesticCityTowsRegEx = _getRegexExp(1, 30, RE_BASIC_GROUP,
			RE_ACCENTED_GROUP,
			 RE_NUMBERS_GROUP,
			 RE_DASH,
			 RE_APOSTROPHE,
			 RE_COMMA,
			 RE_SPACE);

        _billingAddressInternationalCityTowsRegEx = _getRegexExp(1, 30, RE_BASIC_GROUP,
			 RE_ACCENTED_GROUP,
			 RE_NUMBERS_GROUP,
			 RE_DASH,
			 RE_APOSTROPHE,
			 RE_COMMA,
			 RE_SPACE);

        _billingAddressProvinceRegEx = _getRegexExp(1, 30, RE_BASIC_GROUP,
			 RE_ACCENTED_GROUP,
			 RE_NUMBERS_GROUP,
			 RE_DASH,
			 RE_APOSTROPHE,
			 RE_COMMA,
			 RE_SPACE
			);

        _billingAddressPostalCodeRegEx = _getRegexExp(1, 10, RE_BASIC_GROUP,
			   RE_NUMBERS_GROUP,
			   RE_DASH,
			   RE_SPACE);

        _billingAddressStateRegEx = _getRegexExp(2, RE_BASIC_GROUP);

        _billingAddressZipCodeRegEx = _getRegexExp(5, RE_NUMBERS_GROUP);

        _billingAddressCountryRegEx = _getRegexExp(4, RE_BASIC_GROUP);

        _billingAddressIsInited = true;
    }

}


function addressConst()
{
}

var _addressConstIsInited = false;

function _addressConstInit()
{
    if (!_addressConstIsInited)
    {
        addressConst.fields = {
            country: "country",
            address: "address",
            address2: "address2",
            cityTown: "cityTown",
            stateProvince: "stateProvince",
            zipPostalCode: "zipPostalCode"

        };

        _addressConstIsInited = true;
    }
}

// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_BillingDomesticAddress( "Maint* $%^@$^% est123g st. 12", "Main st. 12", "test", "Ca", "1234567", errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[addressConst.fields.address].join('\n')) }
function Validator_BillingDomesticAddress(address, address2, city, state, zipCode, errorList, errorsObject)
{

    var result = true;
    var lastErrors = [];

    _initBillingAddress();
    _initErrorsObj(errorsObject, addressConst.fields);

    if (!_validateFieldRegEx(address, _billingAddressDomesticAddressRegEx, lastErrors, 'Address is not valid', 'Address is required'))
    { result = false; _processLastErrors(addressConst.fields.address, lastErrors, errorList, errorsObject); lastErrors = []; }


    if (!_validateFieldRegEx(address2, _billingAddressDomesticAddressRegEx, lastErrors, 'Address2 is not valid'))
    { result = false; _processLastErrors(addressConst.fields.address2, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(city, _billingAddressDomesticCityTowsRegEx, lastErrors, 'City/Town is not valid', 'City/Town is required'))
    { result = false; _processLastErrors(addressConst.fields.cityTown, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(state, _billingAddressStateRegEx, lastErrors, 'State is not valid', 'State is required'))
    { result = false; _processLastErrors(addressConst.fields.stateProvince, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(zipCode, _billingAddressZipCodeRegEx, lastErrors, 'ZIP Code is not valid', 'ZIP Code is required'))
    { result = false; _processLastErrors(addressConst.fields.zipPostalCode, lastErrors, errorList, errorsObject); lastErrors = []; }

    return result;
}

// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_BillingInternationalAddress("UNIT", "Maint* $%^@$^% est123g st. 12", "Main st. 12", "test", "Ca", "1234567", errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[addressConst.fields.address].join('\n')) }
function Validator_BillingInternationalAddress(country, address, address2, city, province, postalcode, errorList, errorsObject)
{


    var result = true;
    var lastErrors = [];

    _initBillingAddress();
    _initErrorsObj(errorsObject, addressConst.fields);




    if (!_validateFieldRegEx(country, _billingAddressCountryRegEx, lastErrors, 'Country is not valid', 'Country is required'))
    { result = false; _processLastErrors(addressConst.fields.country, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(address, _billingAddressInternationalAddressRegEx, lastErrors, 'Address is not valid', 'Address is required'))
    { result = false; _processLastErrors(addressConst.fields.address, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(address2, _billingAddressInternationalAddressRegEx, lastErrors, 'Address2 is not valid'))
    { result = false; _processLastErrors(addressConst.fields.address2, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(city, _billingAddressInternationalCityTowsRegEx, lastErrors, 'City/Town is not valid', 'City/Town is required'))
    { result = false; _processLastErrors(addressConst.fields.cityTown, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(province, _billingAddressProvinceRegEx, lastErrors, 'Province is not valid'))
    { result = false; _processLastErrors(addressConst.fields.stateProvince, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(postalcode, _billingAddressPostalCodeRegEx, lastErrors, 'Postal Code is not valid', 'Postal Code is required'))
    { result = false; _processLastErrors(addressConst.fields.zipPostalCode, lastErrors, errorList, errorsObject); lastErrors = []; }

    return result;
}

// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_ContactDomesticAddress( "Maint* $%^@$^% est123g st. 12", "Main st. 12", "test", "Ca", "1234567", errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[addressConst.fields.address].join('\n')) }
function Validator_ContactDomesticAddress(address, address2, city, state, zipCode, errorList, errorsObject)
{

    var result = true;
    var lastErrors = [];

    _initBillingAddress();
    _initErrorsObj(errorsObject, addressConst.fields);

    if (!_validateFieldRegEx(address, _billingAddressDomesticAddressRegEx, lastErrors, 'Address is not valid'))
    { result = false; _processLastErrors(addressConst.fields.address, lastErrors, errorList, errorsObject); lastErrors = []; }


    if (!_validateFieldRegEx(address2, _billingAddressDomesticAddressRegEx, lastErrors, 'Address2 is not valid'))
    { result = false; _processLastErrors(addressConst.fields.address2, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(city, _billingAddressDomesticCityTowsRegEx, lastErrors, 'City/Town is not valid'))
    { result = false; _processLastErrors(addressConst.fields.cityTown, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(state, _billingAddressStateRegEx, lastErrors, 'State is not valid'))
    { result = false; _processLastErrors(addressConst.fields.stateProvince, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(zipCode, _billingAddressZipCodeRegEx, lastErrors, 'ZIP Code is not valid', 'ZIP Code is required'))
    { result = false; _processLastErrors(addressConst.fields.zipPostalCode, lastErrors, errorList, errorsObject); lastErrors = []; }

    return result;
}

// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_ContactInternationalAddress("UNIT", "Maint* $%^@$^% est123g st. 12", "Main st. 12", "test", "Ca", "1234567", errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[addressConst.fields.address].join('\n')) }
function Validator_ContactnternationalAddress(country, address, address2, city, province, postalcode, errorList, errorsObject)
{


    var result = true;
    var lastErrors = [];

    _initBillingAddress();
    _initErrorsObj(errorsObject, addressConst.fields);




    if (!_validateFieldRegEx(country, _billingAddressCountryRegEx, lastErrors, 'Country is not valid'))
    { result = false; _processLastErrors(addressConst.fields.country, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(address, _billingAddressInternationalAddressRegEx, lastErrors, 'Address is not valid'))
    { result = false; _processLastErrors(addressConst.fields.address, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(address2, _billingAddressInternationalAddressRegEx, lastErrors, 'Address2 is not valid'))
    { result = false; _processLastErrors(addressConst.fields.address2, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(city, _billingAddressInternationalCityTowsRegEx, lastErrors, 'City/Town is not valid'))
    { result = false; _processLastErrors(addressConst.fields.cityTown, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(province, _billingAddressProvinceRegEx, lastErrors, 'Province is not valid'))
    { result = false; _processLastErrors(addressConst.fields.stateProvince, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (!_validateFieldRegEx(postalcode, _billingAddressPostalCodeRegEx, lastErrors, 'Postal Code is not valid', 'Postal Code is required'))
    { result = false; _processLastErrors(addressConst.fields.zipPostalCode, lastErrors, errorList, errorsObject); lastErrors = []; }

    return result;
}



//Frofanity Filter
var _profanityWords = new Array("\\onahf\\o",
	"\\onff\\o",
	"nffubyr",
	"onfgneq",
	"ovtnff",
	"ovgpu",
	"oybbq",
	"oybjwbo",
	"pvnyvk",
	"\\opbpx\\o",
	"pbpxfhpx",
	"\\ophag\\o",
	"\\ophagf\\o",
	"\\oqvyqb\\o",
	"qebcqrnq",
	"rwnphyng",
	"\\osnt\\o",
	"snttbg",
	"\\osneg\\o",
	"\\oshpx\\o",
	"shpxvat",
	"\\oubeal\\o",
	"\\ownpxbss\\o",
	"\\owrexbss\\o",
	"zbgureshpx",
	"\\oavttre\\o",
	"betnfz",
	"cubarfrk",
	"\\ocbea\\o",
	"chffl",
	"\\ofrk\\o",
	"\\ofuvg\\o",
	"fuvgurnq",
	"\\ofuvggre\\o",
	"\\ofyhg\\o",
	"\\ofhpxre\\o",
	"ivnten",
	"kkk");

var _profanityRegex = null;

function _initProfanityRegex()
{
    var profanityRegexStr = "";
    for (var i = 0; i < _profanityWords.length; i++)
    {
        if (profanityRegexStr.length > 0)
        {
            profanityRegexStr += "|";
        }
        profanityRegexStr += "(" + _rot13(_profanityWords[i]) + ")";
    }

    _profanityRegex = eval("/" + profanityRegexStr + "/i");
}


function _profanityFilterMeetCheck(input, errorList, invError)
{
    if (!_profanityRegex)
    {
        _initProfanityRegex();
    }

    if (input.match(_profanityRegex))
    {
        _addErrorToList(errorList, invError);
        return false;
    }
    else
    {
        return true;
    }
}

// Contact information validation

var _contactInformationIsInited = false;
var _contactInformationFirstNameRegEx = null;
var _contactInformationLastNameRegEx = null;


function contactConst()
{
}


var _contactConstIsInited = false;

function _contactConstInit()
{
    if (!_contactConstIsInited)
    {
        contactConst.fields = {
            firstName: "firstName",
            lastName: "lastName"

        };

        _contactConstIsInited = true;
    }
}


function _initContactInformation()
{
    if (!_contactInformationIsInited)
    {
        _contactConstInit();

        _contactInformationFirstNameRegEx = _getRegexExp(RE_BASIC_GROUP,
			RE_NUMBERS_GROUP,
			RE_DOT,
			RE_COMMA,
			RE_AMPERSAND,
			RE_DOUBLEQUOTE,
			RE_ACCENTED_GROUP,
			RE_DASH,
			RE_APOSTROPHE,
			RE_SPACE);

        _contactInformationLastNameRegEx = _getRegexExp(RE_BASIC_GROUP,
			RE_NUMBERS_GROUP,
			RE_DOT,
			RE_COMMA,
			RE_AMPERSAND,
			RE_DOUBLEQUOTE,
			RE_ACCENTED_GROUP,
			RE_DASH,
			RE_APOSTROPHE,
			RE_SPACE);

        _contactInformationIsInited = true;
    }

}

function Validator_ContactInformation(firstName, lastName, errorList, errorsObject)
{
    var result = true;
    var lastErrors = [];

    _initContactInformation();
    _initErrorsObj(errorsObject, contactConst.fields);
    if (!_validateFieldRegEx(firstName, _contactInformationFirstNameRegEx, lastErrors, 'First Name is not valid', 'First Name is required'))
    { result = false; _processLastErrors(contactConst.fields.firstName, lastErrors, errorList, errorsObject); lastErrors = []; }
    else if (!_profanityFilterMeetCheck(firstName, lastErrors, 'First Name is not valid'))
    { result = false; _processLastErrors(contactConst.fields.firstName, lastErrors, errorList, errorsObject); lastErrors = []; }
    if (!_validateFieldRegEx(lastName, _contactInformationLastNameRegEx, lastErrors, 'Last Name is not valid', 'Last Name is required'))
    { result = false; _processLastErrors(contactConst.fields.lastName, lastErrors, errorList, errorsObject); lastErrors = []; }
    else if (!_profanityFilterMeetCheck(lastName, lastErrors, 'Last Name is not valid'))
    { result = false; _processLastErrors(contactConst.fields.lastName, lastErrors, errorList, errorsObject); lastErrors = []; }
    return result;
}

var _emailAddressIsInited = false;

function emailAddressConst()
{
}

var _emailAddressConstIsInited = false;

function _initEmailAddressConst()
{
    if (!_emailAddressConstIsInited)
    {
        emailAddressConst.fields = {
            email: "email",
            confirmEmail: "confirmEmail"
        };
    }

    _emailAddressConstIsInited = true;
}

var _emailAddressEmailRegEx = null;


function _initEmailAddress()
{

    if (!_emailAddressIsInited)
    {

        _initEmailAddressConst();

        _emailAddressEmailRegEx = eval("/" + RE_EMAIL + "/i");

    }

    _emailAddressIsInited = true;

}

// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_EmailAddress( "test@email.com", "test@email.com", errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[emailAddressConst.fields.email].join('\n')) }
function Validator_EmailAddress(email, confirmEmail, errorList, errorsObject)
{

    var result = true;
    var lastErrors = [];

    _initEmailAddress();

    _initErrorsObj(errorsObject, emailAddressConst.fields);

    if (!_validateFieldRegEx(email, _emailAddressEmailRegEx, lastErrors, 'E-mail Address is invalid', 'E-mail Address is required'))
    { result = false; _processLastErrors(emailAddressConst.fields.email, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (result && null != confirmEmail)
    {
        if (confirmEmail.toString().length == 0) { result = false; _addErrorToList(lastErrors, "Confirm E-mail is required"); }
        if (result && confirmEmail.toString().toLowerCase() != email.toString().toLowerCase()) { result = false; _addErrorToList(lastErrors, "Confirm E-mail Address does not match E-mail Address field"); }
        if (!result) { _processLastErrors(emailAddressConst.fields.confirmEmail, lastErrors, errorList, errorsObject); lastErrors = []; }
    }

    return result;
}

var _passwordIsInit = false;

function passwordConst() { }

var _passwordConstIsInit = false;

function _initPasswordConst()
{
    if (!_passwordConstIsInit)
    {
        passwordConst.fields = {
            password: "password",
            confirmPassword: "confirmPassword"
        };
    }
    _passwordConstIsInit = true;
}

var _passwordPasswordRegEx = null;


function _initPassword()
{
    if (!_passwordIsInit)
    {

        _initPasswordConst();

        _passwordPasswordRegEx = _getRegexExp(1, 50,
            RE_BASIC_GROUP,
            RE_NUMBERS_GROUP,
            RE_COMMONSPECIAL_GROUP);
    }

    _passwordIsInit = true;
}

function Validator_UserType(type, errorList, errorsObject) 
{
    var lastErrors = [];
    var isChecked = false;

    for (var i = 0; i < type.length; i++) 
    {
        isChecked = type[i].checked || isChecked;
    }

    if (!isChecked) 
    {
        _addErrorToList(lastErrors, "User Type is required");
        _processLastErrors("user type", lastErrors, errorList, errorsObject);
    }

    return isChecked;
}

// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_Password( "password1", "password1", errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[passwordConst.fields.password].join('\n')) }
function Validator_Password(password, confirmPassword, errorList, errorsObject)
{
    var result = true;
    var lastErrors = [];

    _initPassword();

    var innerPass = password; //.toString().replace(/^\s+|\s+$/g, '');

    _initErrorsObj(errorsObject, passwordConst.fields);

    if (!_validateFieldRegEx(innerPass, _passwordPasswordRegEx, lastErrors, 'Your password field does not match the verify password field. Spaces are not allowed in the password', 'Your password can not be blank'))
    { result = false; _processLastErrors(passwordConst.fields.password, lastErrors, errorList, errorsObject); lastErrors = []; }

    if (result && (null == confirmPassword || innerPass != confirmPassword.toString()))
    {
        _addErrorToList(lastErrors, "Your password field does not match the verify password field. Spaces are not allowed in the password");
        _processLastErrors(passwordConst.fields.confirmPassword, lastErrors, errorList, errorsObject); lastErrors = [];
        result = false;
    }

    return result;
}

var _phoneNumberConstIsInit = false;

function phoneNumberConst() { }

function _initPhoneNumberConst()
{
    if (!_phoneNumberConstIsInit)
    {
        phoneNumberConst.fields = {
            areaCode: "areaCode",
            prefix: "prefix",
            suffix: "suffix",
            ext: "ext",
            number: "number"
        };
    }
    _phoneNumberConstIsInit = true;
}

var _phoneNumberAreaCodeRegEx = null;
var _phoneNumberPrefixRegEx = null;
var _phoneNumberSuffixRegEx = null;
var _phoneNumberExtRegEx = null;

var _phoneNumberInternationalNumberRegEx = null;

var _phoneNumberIsInit = false;


function _initPhoneNumber()
{
    if (!_phoneNumberIsInit)
    {

        _initPhoneNumberConst();

        _phoneNumberAreaCodeRegEx = _getRegexExp(3, RE_NUMBERS_GROUP);

        _phoneNumberPrefixRegEx = _getRegexExp(3, RE_NUMBERS_GROUP);

        _phoneNumberSuffixRegEx = _getRegexExp(4, RE_NUMBERS_GROUP);

        _phoneNumberExtRegEx = _getRegexExp(RE_NUMBERS_GROUP,
            RE_BASIC_GROUP,
            RE_SPACE,
            RE_DASH,
            RE_NUMBERSIGN,
            RE_ASTERISK,
            RE_COMMA,
            RE_DOT);

        _phoneNumberInternationalNumberRegEx = _getRegexExp(6, 16,
            RE_NUMBERS_GROUP,
            RE_DASH,
            RE_SPACE);

    }
    _phoneNumberIsInit = true;
}

// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_DomesticPhone( "123","123","123", null,  errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[phoneNumberConst.fields.areaCode].join('\n')) }
function Validator_DomesticPhone(areaCode, prefix, suffix, ext, errorList, errorsObject)
{
    var result = true;
    var lastErrors = [];

    _initPhoneNumber();

    _initErrorsObj(errorsObject, phoneNumberConst.fields);

    if (areaCode === '' && prefix === '' && suffix === '' && (ext === null || ext === ''))
    {
        lastErrors = ['Phone Number is required'];
        result = false; _processLastErrors(phoneNumberConst.fields.number, lastErrors, errorList, errorsObject); lastErrors = [];

        return result;
    }


    if (!_validateFieldRegEx(areaCode, _phoneNumberAreaCodeRegEx, lastErrors, 'Phone Number is not valid', 'Phone Number is not valid'))
    {
        result = false; _processLastErrors(phoneNumberConst.fields.areaCode, lastErrors, errorList, errorsObject); lastErrors = [];
        return result;
    }

    if (!_validateFieldRegEx(prefix, _phoneNumberPrefixRegEx, lastErrors, 'Phone Number is not valid', 'Phone Number is not valid'))
    {
        result = false; _processLastErrors(phoneNumberConst.fields.prefix, lastErrors, errorList, errorsObject); lastErrors = [];
        return result;
    }

    if (!_validateFieldRegEx(suffix, _phoneNumberSuffixRegEx, lastErrors, 'Phone Number is not valid', 'Phone Number is not valid'))
    {
        result = false; _processLastErrors(phoneNumberConst.fields.suffix, lastErrors, errorList, errorsObject); lastErrors = [];
        return result;
    }

    if (!_validateFieldRegEx(ext, _phoneNumberExtRegEx, lastErrors, 'Phone Number is not valid'))
    {
        result = false; _processLastErrors(phoneNumberConst.fields.ext, lastErrors, errorList, errorsObject); lastErrors = [];
        return result;
    }

    return result;
}

// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_InternationalPhone( "123456", errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[phoneNumberConst.fields.number].join('\n')) }
function Validator_InternationalPhone(number, errorList, errorsObject)
{
    var result = true;
    var lastErrors = [];

    _initPhoneNumber();

    _initErrorsObj(errorsObject, phoneNumberConst.fields);

    if (!_validateFieldRegEx(number, _phoneNumberInternationalNumberRegEx, lastErrors, 'Phone Number is not valid', 'Phone Number is required'))
    {
        result = false; _processLastErrors(phoneNumberConst.fields.number, lastErrors, errorList, errorsObject); lastErrors = [];
    }

    return result;
}

var _creditCardIsInit = false;
var _creditCardConstIsInit = false;

function creditCardConst() { }

function _initCreditCardConst()
{
    if (!_creditCardConstIsInit)
    {

        creditCardConst.fields = {
            number: "number",
            type: "type",
            expDate: "expDate",
            name: "name",
            cvv: "cvv"
        };
    }

    _creditCardConstIsInit = true;
}
var _creditCardTypeRegEx = null;
var _creditCardNumberRegEx = null;
var _creditCardNameRegEx = null;
var _creditCardCVV = null;

function _initCreditCard()
{

    if (!_creditCardIsInit)
    {

        _initCreditCardConst();

        _creditCardTypeRegEx = _getRegexExp(2, 5, RE_BASIC_GROUP);

        _creditCardNumberRegEx = _getRegexExp(13, 16, RE_NUMBERS_GROUP);

        _creditCardNameRegEx = _getRegexExp(
            RE_BASIC_GROUP,
	    RE_NUMBERS_GROUP,
	    RE_DOT,
            RE_COMMA,
	    RE_SLASH,
            RE_DOUBLEQUOTE,
            RE_NUMBERSIGN,
            RE_ACCENTED_GROUP,
            RE_DASH,
            RE_APOSTROPHE,
            RE_SPACE);

        _creditCardCVV = _getRegexExp(3, 4, RE_NUMBERS_GROUP);

    }
    _creditCardIsInit = true;
}


function Validator_CreditCard(type, ccNumber, expMonth, expYear, name, cvv, errorList, errorsObject, ccNumberOriginal, typeOriginal)
{
    var result = true;
    var ccUpdated = true;
    var ccTypeUpdated = false;
    var lastErrors = [];

    //ccNumberOriginal is only passed on edit forms (eg: edit my profile).
    //If it is equal to ccNumber then the user is not updating their credit card and cannot validate existing values because they are obfuscated
    if (typeof(ccNumberOriginal) != "undefined" && ccNumberOriginal != null && ccNumberOriginal != "" && ccNumber == ccNumberOriginal) 
		ccUpdated = false;

    //if typeOriginal != type then the user has updated their payment type and validation needs to happen 
    if (typeof(typeOriginal) != "undefined" && typeOriginal != null && typeOriginal != "" && typeOriginal != type) 
		ccTypeUpdated = true;

    _initCreditCard();

    _initErrorsObj(errorsObject, creditCardConst.fields);

    if (!_validateFieldRegEx(type, _creditCardTypeRegEx, lastErrors, 'Payment Type is not valid', 'Payment Type is required'))
    {
        result = false; _processLastErrors(creditCardConst.fields.type, lastErrors, errorList, errorsObject); lastErrors = [];
    }

    if (ccNumber == '' || ccUpdated || ccTypeUpdated)
    {
        if (!_validateFieldRegEx(ccNumber, _creditCardNumberRegEx, lastErrors, 'Credit card number is not valid', 'Credit card number is required'))
        {
            result = false; _processLastErrors(creditCardConst.fields.number, lastErrors, errorList, errorsObject); lastErrors = [];
        }

        if (result && !_checkCreditCardNumber(ccNumber, type))
        {
            _addErrorToList(lastErrors, 'Credit card number is not valid');
            _processLastErrors(creditCardConst.fields.number, lastErrors, errorList, errorsObject); lastErrors = [];
            result = false;
        }
    }

    if (!_validateExpirationDate(expMonth, expYear))
    {
        if (!expMonth || !expYear)
        {
            _addErrorToList(lastErrors, 'Credit Card Expiration Date is required');
        }
        else
        {
            _addErrorToList(lastErrors, 'Credit Card Expiration Date is not valid');
        }
        _processLastErrors(creditCardConst.fields.expDate, lastErrors, errorList, errorsObject); lastErrors = [];
        result = false;
    }

    if (!_validateFieldRegEx(__trimString(name), _creditCardNameRegEx, lastErrors, 'Card Holder Name is not valid', 'Card Holder Name is required'))
    {
        result = false; _processLastErrors(creditCardConst.fields.name, lastErrors, errorList, errorsObject); lastErrors = [];
    }


    if (cvv !== null && !_validateFieldRegEx(cvv, _creditCardCVV, lastErrors, 'CVV2 number is not valid', 'CVV2 number is required'))
    {
        result = false; _processLastErrors(creditCardConst.fields.cvv, lastErrors, errorList, errorsObject); lastErrors = [];
    }


    return result;
}

function __trimString(value)
{
    if (!value || undefined == value) { return ''; }
    return value.toString().replace(/^\s+|\s+$/g, '');
}


function _validateExpirationDate(expMonth, expYear)
{
    try
    {
        var testDate = new Date();

        var innerMonth = _fnParseInt(expMonth) - 1;

        testDate.setFullYear(expYear, innerMonth, 1);

        if (testDate.getMonth() != innerMonth)
        {
            return false;
        }

        if (testDate.getFullYear() != expYear)
        {
            return false;
        }
        
        testDate.setFullYear(expYear, innerMonth+1, 1);

        if (testDate > new Date())
        {
            return true;
        }

        return false;
    }
    catch (err)
    {
        alert(err);
        return false;
    }
}

function _checkCreditCardNumber(number, type)
{
    try
    {
        number = number.toString();
        var firstChar = number.charAt(0);
        if (firstChar != '3' && firstChar != '4' && firstChar != '5') { return false; }

        if (type)
        {
            var typeStr = type.toString().toLowerCase();

            if (typeStr == 'visa' && firstChar != '4') { return false; }
            if (typeStr == 'mc' && firstChar != '5') { return false; }
            if (typeStr == 'amex' && firstChar != '3') { return false; }
        }



        var total = 0;
        var j = 1;

        for (var i = number.length - 1; i >= 0; i--)
        {
            var v = parseInt(number.charAt(i)) * j;

            if (v > 9)
            {
                v -= 9;
            }

            total += v;

            if (j == 2)
            {
                j = 1;
            }
            else
            {
                j = 2;
            }
        }


        return total % 10 == 0;

    }
    catch (err)
    {
        return false;
    }
}

var _paymentInfoCommonInfoIsInit = false;
var _paymentInfoConstIsInit = false;

function paymentInfoConst() { }

function _initPaymentInfoConst()
{
    if (!_paymentInfoConstIsInit)
    {
        paymentInfoConst.fields = {
            firstName: "firstName",
            lastName: "lastName",
            routingNumber: "routingNumber",
            confirmRoutingNumber: "confirmRoutingNumber",
            accountNumber: "accountNumber",
            confirmAccountNumber: "confirmAccountNumber",
            driversLicense: "driversLicense",
            state: "state",
            dateOfBirth: "dateOfBirth",
            companyName: "companyName",
            phoneNumber: "phoneNumber"//,
            //termsOfUse: "termsOfUse"
        };
    }

    _paymentInfoConstIsInit = true;
}

var _paymentInfoFirstNameRegEx = null;
var _paymentInfoLastNameRegEx = null;
var _paymentInfoRoutingNumberRegEx = null;
var _paymentInfoAccountNumberRegEx = null;

function _initPaymentInfoCommonInfo()
{
    if (!_paymentInfoCommonInfoIsInit)
    {

        _initPaymentInfoConst();
        _paymentInfoFirstNameRegEx = _getRegexExp(RE_BASIC_GROUP,
			RE_NUMBERS_GROUP,
			RE_DOT,
			RE_COMMA,
			RE_AMPERSAND,
			RE_DOUBLEQUOTE,
			RE_ACCENTED_GROUP,
			RE_DASH,
			RE_APOSTROPHE,
			RE_SPACE);

        _paymentInfoLastNameRegEx = _getRegexExp(RE_BASIC_GROUP,
			RE_NUMBERS_GROUP,
			RE_DOT,
			RE_COMMA,
			RE_AMPERSAND,
			RE_DOUBLEQUOTE,
			RE_ACCENTED_GROUP,
			RE_DASH,
			RE_APOSTROPHE,
			RE_SPACE);

        _paymentInfoRoutingNumberRegEx = _getRegexExp(RE_NUMBERS_GROUP);


        _paymentInfoAccountNumberRegEx = _getRegexExp(RE_NUMBERS_GROUP);

    }

    _paymentInfoCommonInfoIsInit = true;
}

function _validateRoutingNumber(number)
{
    if (__trimString(number) == '') { return false; }

    var numbersOnly = number.toString().replace(/[^\d]/g, '');



    if (9 == numbersOnly.length)
    {
        var total = 0;
        try
        {
            for (var i = 0; i < numbersOnly.length; i += 3)
            {
                total += parseInt(numbersOnly.charAt(i)) * 3 + parseInt(numbersOnly.charAt(i + 1)) * 7 + parseInt(numbersOnly.charAt(i + 2));
            }

            return total % 10 == 0;
        }
        catch (err)
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}

// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_PaymentInfoCommonInfo( "Vasia", "Pupkin", "102000199", "102000199", "203", "203", errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[paymentInfoConst.fields.firstName].join('\n')) }
function Validator_PaymentInfoCommonInfo(first, last, routing, confRouting, account, confAccount, errorList, errorsObject, routingOriginal, accountOriginal)
{

    var result = true;
    var lastErrors = [];
    var isRNValid = true;
    var isANValid = true;

    _initPaymentInfoCommonInfo();

    _initErrorsObj(errorsObject, paymentInfoConst.fields);

    if (!_validateFieldRegEx(first, _paymentInfoFirstNameRegEx, lastErrors, 'First Name on Checking Account is not valid', 'First Name on Checking Account is required'))
    {
        result = false; _processLastErrors(paymentInfoConst.fields.firstName, lastErrors, errorList, errorsObject); lastErrors = [];
    }

    if (!_validateFieldRegEx(last, _paymentInfoLastNameRegEx, lastErrors, 'Last Name on Checking Account is not valid', 'Last Name on Checking Account is required'))
    {
        result = false; _processLastErrors(paymentInfoConst.fields.lastName, lastErrors, errorList, errorsObject); lastErrors = [];
    }

    if (routingOriginal == null || routing != routingOriginal || routing == '')
    {
        //routingOriginal is only used on pages where the user is modifying their billing info (eg: edit my profile)
        //if routing == routingOriginal then the user is not updating their info and we are unable to validate because it's obfuscated (eg: xxxxxxxx1234)
        if (!_validateFieldRegEx(routing, _paymentInfoRoutingNumberRegEx, lastErrors, 'Routing number is not valid', 'Routing number is required'))
        {
            result = false; _processLastErrors(paymentInfoConst.fields.routingNumber, lastErrors, errorList, errorsObject); lastErrors = [];
            isRNValid = false;
        }
        else if (!_validateRoutingNumber(routing))
        {
            _addErrorToList(lastErrors, 'Routing number is not valid');
            _processLastErrors(paymentInfoConst.fields.routingNumber, lastErrors, errorList, errorsObject); lastErrors = [];
            result = false;
            isRNValid = false;
        }
        if (null != confRouting)
        {
            if (isRNValid && !_validateFieldRegEx(confRouting, _paymentInfoRoutingNumberRegEx, lastErrors, 'Confirm Routing number is not valid', 'Confirm Routing number is required'))
            {
                result = false; _processLastErrors(paymentInfoConst.fields.confirmRoutingNumber, lastErrors, errorList, errorsObject); lastErrors = [];
                isRNValid = false;
            }

            if (isRNValid && routing != confRouting)
            {
                _addErrorToList(lastErrors, 'Confirm Routing number is not valid');
                _processLastErrors(paymentInfoConst.fields.confirmRoutingNumber, lastErrors, errorList, errorsObject); lastErrors = [];
                result = false;
            }
        }
    }


    if (accountOriginal == null || account != accountOriginal || account == '')
    {
        //accountOriginal is only used on pages where the user is modifying their billing info (eg: edit my profile)
        //if account == accountOriginal then the user is not updating their info and we are unable to validate because it's obfuscated (eg: xxxxxxxx1234)
        if (!_validateFieldRegEx(account, _paymentInfoAccountNumberRegEx, lastErrors, 'Account number is not valid', 'Account number is required'))
        {
            result = false; _processLastErrors(paymentInfoConst.fields.accountNumber, lastErrors, errorList, errorsObject); lastErrors = [];
            isANValid = false;
        }

        if (null != confAccount)
        {
            if (isANValid && !_validateFieldRegEx(confAccount, _paymentInfoAccountNumberRegEx, lastErrors, 'Confirm account number is not valid', 'Confirm account number is required'))
            {
                result = false; _processLastErrors(paymentInfoConst.fields.confirmAccountNumber, lastErrors, errorList, errorsObject); lastErrors = [];
                isANValid = false;
            }

            if (isANValid && confAccount != account)
            {
                _addErrorToList(lastErrors, 'Confirm account number is not valid');
                _processLastErrors(paymentInfoConst.fields.confirmAccountNumber, lastErrors, errorList, errorsObject); lastErrors = [];
                result = false;
            }
        }
    }
    return result;
}

var _paymentInfoCompanyInfoIsInit = false;

var _paymentInfoCompanyNameRegEx = null;
var _paymentInfoPhoneAreaCodeRegEx = null;
var _paymentInfoPhonePrefixRegEx = null;
var _paymentInfoPhoneSuffixRegEx = null;
var _paymentInfoPhoneExtRegEx = null;


function _initPaymentInfoCompanyInfo()
{
    if (!_paymentInfoCompanyInfoIsInit)
    {

        _initPaymentInfoConst();

        _paymentInfoCompanyNameRegEx = _getRegexExp(RE_BASIC_GROUP,
            RE_ACCENTED_GROUP,
            RE_NUMBERS_GROUP,
            RE_NUMBERSIGN,
            RE_DASH,
            RE_COMMA,
            RE_DOT,
            RE_SLASH,
            RE_APOSTROPHE,
            RE_SPACE);

        _paymentInfoPhoneAreaCodeRegEx = _getRegexExp(3, RE_NUMBERS_GROUP);

        _paymentInfoPhonePrefixRegEx = _getRegexExp(3, RE_NUMBERS_GROUP);

        _paymentInfoPhoneSuffixRegEx = _getRegexExp(4, RE_NUMBERS_GROUP);

        _paymentInfoPhoneExtRegEx = _getRegexExp(RE_NUMBERS_GROUP,
            RE_BASIC_GROUP,
            RE_SPACE,
            RE_DASH,
            RE_NUMBERSIGN,
            RE_ASTERISK,
            RE_COMMA,
            RE_DOT);

    }

    _paymentInfoCompanyInfoIsInit = true;
}

// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_PaymentInfoCompanyInfo( "Vasia", "Pupkin", "102", "102", "203", "203", "mycompany", "123456789", errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[paymentInfoConst.fields.firstName].join('\n')) }
function Validator_PaymentInfoCompanyInfo(first, last, routing, confRouting, account, confAccount, company, areaCode, prefix, suffix, ext, errorList, errorsObject, routingOriginal, accountOriginal)
{
    var result = true;
    var lastErrors = [];

    _initPaymentInfoCompanyInfo();

    _initErrorsObj(errorsObject, paymentInfoConst.fields);

    if (!Validator_PaymentInfoCommonInfo(first, last, routing, confRouting, account, confAccount, errorList, errorsObject, routingOriginal, accountOriginal))
    {
        result = false;
    }

    if (!_validateFieldRegEx(company, _paymentInfoCompanyNameRegEx, lastErrors, 'Company Name is not valid', 'Company Name is required'))
    {
        result = false; _processLastErrors(paymentInfoConst.fields.companyName, lastErrors, errorList, errorsObject); lastErrors = [];
    }

    var phonePartValid = true;

    if (areaCode === "" && prefix === "" && suffix === "" && (ext === null || ext === ""))
    {
        lastErrors = ['Business Phone Number is required'];
        result = false; _processLastErrors(paymentInfoConst.fields.phoneNumber, lastErrors, errorList, errorsObject); lastErrors = [];
        phonePartValid = false;
    }

    if (phonePartValid && !_validateFieldRegEx(areaCode, _paymentInfoPhoneAreaCodeRegEx, lastErrors, 'Business Phone Number is not valid', 'Business Phone Number is not valid'))
    {
        result = false; _processLastErrors(paymentInfoConst.fields.phoneNumber, lastErrors, errorList, errorsObject); lastErrors = [];
        phonePartValid = false;
    }

    if (phonePartValid && !_validateFieldRegEx(prefix, _paymentInfoPhonePrefixRegEx, lastErrors, 'Business Phone Number is not valid', 'Business Phone Number is not valid'))
    {
        result = false; _processLastErrors(paymentInfoConst.fields.phoneNumber, lastErrors, errorList, errorsObject); lastErrors = [];
        phonePartValid = false;
    }

    if (phonePartValid && !_validateFieldRegEx(suffix, _paymentInfoPhoneSuffixRegEx, lastErrors, 'Business Phone Number is not valid', 'Business Phone Number is not valid'))
    {
        result = false; _processLastErrors(paymentInfoConst.fields.phoneNumber, lastErrors, errorList, errorsObject); lastErrors = [];
        phonePartValid = false;
    }

    if (ext && phonePartValid && !_validateFieldRegEx(ext, _paymentInfoPhoneExtRegEx, lastErrors, 'Business Phone Number is not valid'))
    {
        result = false; _processLastErrors(paymentInfoConst.fields.phoneNumber, lastErrors, errorList, errorsObject); lastErrors = [];
        phonePartValid = false;
    }


    return result;

}


var _paymentInfoPersonInfoIsInit = false;

var _paymentInfoDriverLicenseRegEx = null;
var _paymentInfoStateRegEx = null;
//var _paymentInfoDateOfBirthRegEx = null;

function _initPaymentInfoPersonInfo()
{
    if (!_paymentInfoPersonInfoIsInit)
    {

        _initPaymentInfoConst();

        _paymentInfoDriverLicenseRegEx = _getRegexExp(RE_NUMBERS_GROUP,
            RE_BASIC_GROUP,
            RE_SPACE,
            RE_DASH);

        _paymentInfoStateRegEx = _getRegexExp(2, RE_BASIC_GROUP);

    }
    _paymentInfoPersonInfoIsInit = true;
}


// Usage example:
//var errors = [];
//var test_obj = {};
//var result = Validator_PaymenInfoPersonInfo( "Vasia", "Pupkin", "102", "102", "203", "203", "1234567890", "LV", "12", "21", "2008", errors, test_obj);
//if (!result) { alert(errors.join('\n')); alert(test_obj[paymentInfoConst.fields.firstName].join('\n')) }
function Validator_PaymenInfoPersonInfo(first, last, routing, confRouting, account, confAccount, driverLic, state, month, day, year, errorList, errorsObject, routingOriginal, accountOriginal)
{
    var result = true;
    var lastErrors = [];

    _initPaymentInfoPersonInfo();

    _initErrorsObj(errorsObject, paymentInfoConst.fields);

    if (!Validator_PaymentInfoCommonInfo(first, last, routing, confRouting, account, confAccount, errorList, errorsObject, routingOriginal, accountOriginal))
    {
        result = false;
    }

    if (!_validateFieldRegEx(driverLic, _paymentInfoDriverLicenseRegEx, lastErrors, 'Driver License number is not valid', 'Driver License number is required'))
    {
        result = false; _processLastErrors(paymentInfoConst.fields.driversLicense, lastErrors, errorList, errorsObject); lastErrors = [];
    }

    if (!_validateFieldRegEx(state, _paymentInfoStateRegEx, lastErrors, 'Driver License State is not valid', 'Driver License State is required'))
    {
        result = false; _processLastErrors(paymentInfoConst.fields.state, lastErrors, errorList, errorsObject); lastErrors = [];
    }

    if (__trimString(month) == '' || __trimString(day) == '' || __trimString(year) == '')
    {
        _addErrorToList(lastErrors, 'Date of Birth is required');
        _processLastErrors(paymentInfoConst.fields.dateOfBirth, lastErrors, errorList, errorsObject); lastErrors = [];
        result = false;
    }
    else
    {
        try
        {
            var iMonth = _fnParseInt(month) - 1;
            var iDay = _fnParseInt(day);
            var iYear = _fnParseInt(year);

            var today = new Date();
            var birth = new Date();



            birth.setFullYear(iYear, iMonth, iDay);




            if (birth > today || birth.getDate() != iDay || birth.getMonth() != iMonth || birth.getFullYear() != iYear)
            {
                _addErrorToList(lastErrors, 'Date of Birth is not valid');
                _processLastErrors(paymentInfoConst.fields.dateOfBirth, lastErrors, errorList, errorsObject); lastErrors = [];
                result = false;
            }

        }
        catch (err)
        {
            _addErrorToList(lastErrors, 'Date of Birth is not valid');
            _processLastErrors(paymentInfoConst.fields.dateOfBirth, lastErrors, errorList, errorsObject); lastErrors = [];
            result = false;
        }
    }


    return result;
}

function g_fnPaymentInformationBoxGet(pbVisible)
{
    try
    {
        var loPaymentInfoBox = document.getElementById('divPaymentInformationBox');

        if (pbVisible)
        {
            loPaymentInfoBox.style.display = "block";
        }
        else
        {
            loPaymentInfoBox.style.display = "none";
        }
    }
    catch (e)
    {
    }
}