/**
 * Validates form elements.
 */
function validateForm(form) {
    var result = true;
    var elements = form.elements;
    for (var i = 0; (i < elements.length) && result; ++i) {
        var element = elements[i];
        var nextSibling = element.nextSibling;
        if ((nextSibling != null) && (nextSibling.nodeType == 1) && (nextSibling.tagName == "A")) {
            // validate the field is not null
            if ((nextSibling.className == "nonempty") && (Trim(element.value) == "")) {
                alert(alert_not_empty.replace('<field name>', nextSibling.firstChild.nodeValue));
                element.focus();
                result = false;
            }

            // validate the field is not null nor too long
            if (nextSibling.className == "description") {
                if (Trim(element.value) == "") {
                    alert(alert_not_empty.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
                else if (element.value.length > 255) {
                    alert(alert_less_char.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
            }

            // no trainling blank character
            if ((nextSibling.className == "generalname") && !isGeneralName(element.value)) {
                alert(alert_no_blank.replace('<field name>', nextSibling.firstChild.nodeValue));
                element.focus();
                result = false;
            }

            // validate the field is not null or http://
            if ((nextSibling.className == "http") && ((Trim(element.value) == "") || (Trim(element.value) == "http://"))) {
                alert(alert_not_empty.replace('<field name>', nextSibling.firstChild.nodeValue));
                element.focus();
                result = false;
            }

            // validate the field is mail format
            if ((nextSibling.className == "mailformat")) {
                var regstr = /^[\w-]+(\.[\w-]*)*@([\w-]+\.)+[\w-]{2,4}$/;
                if (!regstr.test(element.value)) {
                    alert(alert_email_format_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
            }

            // validate the field is URL format
            if ((nextSibling.className == "urlformat")) {
                var regstr = /^(http|https):\/\/([\w-]+\.)+[\w-]{1,4}(:\d+)?(\/[\w %=@&~,:+!{}`_\-\.\/\?\[\]]*)?$/;
                if (!regstr.test(element.value)) {
                    alert(alert_url_format_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
            }

            // validate the field is date format
            if ((nextSibling.className == "dateformat")) {
                var reg  =  /^(\d{4})-(\d{2})-(\d{2})$/;
                result = (reg.test(element.value));
                if (!reg.test(element.value)) {
                    alert(alert_date_format_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
                else if (!checkDateValid(element.value)) {
                    alert(alert_date_invalid.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
            }

            // validate the field is date format
            if ((nextSibling.className == "letter")) {
                var reg  =  /^[a-zA-Z0-9_]+?$/;
                result = (reg.test(element.value));
                if (!reg.test(element.value)) {
                    alert(alert_letter_format_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
                else if(element.value.length < 3) {
                    alert(alert_more_char.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
                else if(!isNaN(element.value.charAt(0)) || element.value.charAt(0) == "_") {
                    alert(alert_field_format_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
            }

            // validate the field is user account format
            if ((nextSibling.className == "useraccount")) {
                var reg  =  /^[a-zA-Z0-9]+?$/;
                result = (reg.test(element.value));
                if (!reg.test(element.value)) {
                    alert(alert_user_account_format_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
            }

            // validate the field is zip format
            if ((nextSibling.className == "zipcode")) {
                var reg  =  /^\d{5}(-\d{4})?$/;
                if (!reg.test(element.value)) {
                    alert(alert_zip_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
            }

            // validate the field is Code format
            if ((nextSibling.className == "code")) {
                var reg  =  /^[0-9]+(\-[0-9]+)?$/;
                result = (reg.test(element.value));
                if (!reg.test(element.value)) {
                    alert(alert_code_format_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
            }

            // validate the field which is "SSN/Tax ID"
            if ((nextSibling.className == "ssn")) {
                if (Trim(element.value) == "") {
                    alert(alert_not_empty.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
                else {
                    var reg = /[0-9]|[a-z]|[A-Z]|-/;
                    var regNegative = /[\.]|[_]/;
                    if (!reg.test(element.value) || regNegative.test(element.value)) {
                        alert(alert_dynamic_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                        element.focus();
                        result = false;
                    }
                }
            }

            // validate the field is Credit Card Number format
            if ((nextSibling.className == "creditcard")) {
                if (Trim(element.value) == "") {
                    alert(alert_not_empty.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
                else {
                    if (form.maskedCardNumber.value != element.value) {
                        var reg = /^[0-9]+?$/;
                        result = reg.test(element.value);
                        if (!result) {
                            alert(alert_credit_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                            element.focus();
                            result = false;
                        }
                    }
                }
            }

            // validate the field is float format
            if ((nextSibling.className == "floatformat")) {
                var regfloat  = /^[0-9]+(\.[0-9]+)?$/;
                if (!regfloat.test(element.value)) {
                    alert(alert_require_float.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    return false;
                }
                else if (element.canBeZero) {
                    if (element.value < 0) {
                        alert(alert_require_none_negative.replace('<field name>', nextSibling.firstChild.nodeValue));
                        element.focus();
                        return false;
                    }
                }
                else if (element.value <= 0) {
                    alert(alert_require_positive.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    return false;
                }
                var decimals = Math.round(nextSibling.title);
                if (decimals > 0) {
                    var value = element.value;
                    for (var l = 0; l < decimals; l++) {
                        value *= 10;
                    }
                    if (Math.abs(value - Math.round(value)) > 1e-12) {
                        if (!confirm(alert_require_decimals.replace('<field name>', nextSibling.firstChild.nodeValue))) {
                            element.focus();
                            return false;
                        }
                    }
                }
            }

            // validate the field is money format
            if ((nextSibling.className == "moneyformat")) {
                var regfloat  = /^[0-9]+(\.[0-9]+)?$/;
                var letter = element.value;
                if (letter.substr(0,1) == "$") {
                    letter = letter.substr(1,letter.length-1);
                }
                else{
                    alert(alert_money_format_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                    return false;
                }

                if (!regfloat.test(letter)) {
                    alert(alert_money_format_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    return false;
                }
                else if (letter <= 0) {
                    alert(alert_require_positive.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    return false;
                }
            }

            // validate the field is int format
            if ((nextSibling.className == "phone")) {
                var reg  =  /^[0-9*() \-]+(\-[0-9]+)?$/;
                result = (reg.test(element.value));
                if (!reg.test(element.value)) {
                    alert(alert_input_phone);
                    element.focus();
                    return false;
                }
            }

            // validate the field is int format
            if ((nextSibling.className == "intformat")) {
                var regint  = /^[1-9][0-9]*$/;
                if (!regint.test(element.value)) {
                    alert(alert_require_interger.replace('<field name>', nextSibling.firstChild.nodeValue));
                    element.focus();
                    result = false;
                }
                else {
                    if (element.intlength) {
                        var intlength = parseInt(element.intlength);
                        var max  = Math.pow(2,intlength);
                        if (parseFloat(element.value) > max-1) {
                            alert(alert_big.replace('<field name>', nextSibling.firstChild.nodeValue));
                            element.focus();
                            result = false;
                        }
                    }
                }
            }

            if ((nextSibling.className == "colorformat")) {
                if (Trim(element.value) == "") {
                    alert(alert_not_empty.replace('<field name>', nextSibling.firstChild.nodeValue));
                    try {
                        element.focus();
                    }
                    catch (e) {
                        //do nothing
                    }
                    result = false;
                }
                else {
                    var reg = /^#[0-9a-fA-F]{6}$/;
                    if (!reg.test(element.value) && ("TRANSPARENT" != element.value.toUpperCase())) {
                        alert(alert_color_incorrect.replace('<field name>', nextSibling.firstChild.nodeValue));
                        try {
                            element.focus();
                        }
                        catch (e) {
                            //do nothing
                        }
                        result = false;
                    }
                }
            }
        }
    }
    return result;
}

/**
 * Check whether the date is a valid date.
 */
function checkDateValid(date) {
    var valid = true;
    var dateArray = date.split('-');
    var year = dateArray[0];
    var month = dateArray[1];
    var day = dateArray[2];
    var feb = ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 29 : 28;
    var array = new Array(31, feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    var maxday = array[month - 1];

    if (12 < month || maxday < day || 1 > month || 1 > day) {
        valid = false;
    }

    return valid;
}

function checkStartEndDate(theFrom) {
    var result = true;
    var regExp = /[-]/g;
    var startDate = theFrom.start.value.replace(regExp, '/');
    var endDate = theFrom.end.value.replace(regExp, '/');
    var dateStart = new Date(startDate);
    var dateEnd = new Date(endDate);

    if (dateStart > dateEnd) {
        alert(alert_start_later_end);
        result =  false;
    }

    return result;
}

/**
 * Check whether a character is blank (space, tab, or return).
 */
function isBlankCharacter(ch) {
    return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n');
}

/**
 * Check whether a string is nonempty and has blank trailing (space, tab, or return).
 */
function isGeneralName(name) {
    return (name.length > 0) && !isBlankCharacter(name.charAt(0)) && !isBlankCharacter(name.charAt(name.length - 1));
}

/**
 * Deletes left space.
 */
function LTrim(str) {
    var whitespace = new String(" \t\n\r");
    var s = new String(str);
    if (whitespace.indexOf(s.charAt(0)) != -1) {
        var j=0, i = s.length;
        while (j < i && whitespace.indexOf(s.charAt(j)) != -1) {
            j++;
        }
        s = s.substring(j, i);
    }
    return s;
}

/**
 * Deletes right space.
 */
function RTrim(str) {
    var whitespace = new String(" \t\n\r");
    var s = new String(str);
    if (whitespace.indexOf(s.charAt(s.length-1)) != -1) {
        var i = s.length - 1;
        while (i >= 0 && whitespace.indexOf(s.charAt(i)) != -1) {
            i--;
        }
        s = s.substring(0, i+1);
    }
    return s;
}

/**
 * Deletes left and right space.
 */
function Trim(str) {
    return RTrim(LTrim(str));
}

/**
 * Credit cart validater in client.
 */
function isVisa(cc){ // 4111 1111 1111 1111
    if (((cc.length >= 13) && (cc.length <= 19)) && (cc.substring(0,1) == 4))
        return isCreditCard(cc);
    return false;
}

function isMasterCard(cc){ // 5500 0000 0000 0004
    firstdig = cc.substring(0,1);
    seconddig = cc.substring(1,2);
    if (((cc.length >= 13) && (cc.length <= 19)) && (firstdig == 5) && ((seconddig >= 1) && (seconddig <= 5)))
        return isCreditCard(cc);
    return false;
}

function isAmex(cc){ // 340000000000009
    firstdig = cc.substring(0,1);
    seconddig = cc.substring(1,2);
    if ((cc.length == 15) && (firstdig == 3) && ((seconddig == 4) && (seconddig == 7)))
        return isCreditCard(cc);
    return false;
}

function isDiscover(cc){ // 6011000000000004
    prefix = cc.substring(0,4);
    if ((cc.length == 16) && (prefix == 6011))
        return isCreditCard(cc);
    return false;
}

function isCreditCard(st){
    // Encoding only works on cards with less than 19 digits
    if (st.length > 19)
        return (false);
    return (true);
}

function creditCardValidator (creditCardNo) {
    var result = false;
    if (isVisa(creditCardNo)) {
        result = true;
    }
    else if (isMasterCard(creditCardNo)) {
        result = true;
    }
    else if (isAmex(creditCardNo)) {
        result = true;
    }
    else if (isDiscover(creditCardNo)) {
        result = true;
    }
    else {
        result = true;
    }
    return result;
}

/**
 * Get year, month, day array by parsing date string.
 */
function getYMDDate(date, separator, sequence) {
    var dateArray = date.split(separator);
    var yearIndex = sequence.indexOf("y");
    var monthIndex = sequence.indexOf("m");
    var dayIndex = sequence.indexOf("d");
    var ymdArray = new Array(3);

    ymdArray[0] = dateArray[yearIndex];
    ymdArray[1] = dateArray[monthIndex];
    ymdArray[2] = dateArray[dayIndex];

    return ymdArray;
}

/**
 * Check the expiratin date which in array form.
 */
function checkExpirationDate(dates) {
    dateCurrent = new Date();
    dateCurrent = new Date(dateCurrent.getFullYear() + '/' + (dateCurrent.getMonth() + 1) + '/01');
    dateExp = new Date(dates[0] + '/' + dates[1] + '/01');
    if (dateCurrent > dateExp) {
        alert(alert_expiration_date_incorrect);
        return false;
    }

    return true;
}