﻿// Validation RegEx patters are at the bottom of this file.

if (!this.Validation)
{
    Validation = { };
    Validation.Groups = { };
    Validation.ISREQUIRED = " is required";
    Validation.ISINVALID = " is invalid";
    Validation.ISOUTOFRANGE = " is out of range of acceptable values";
    Validation.INVALIDBGCOLOR = "#FFFFDD";
}

Validation.Group = function ()
{
    this.Id = "";
    this.Elements = new Object();
    this.Summary = {};
    this.IsValid = true;
};

Validation.Element = function() {
    this.Id = "";
    this.Type = "";
    this.Required = false;
    this.IsValid = true;
    this.Message = "";
    this.FieldName = "";
    this.MinValue = null;
    this.MaxValue = null;
    this.Initial = null;
    this.Control = null;
    this.Label = null;
};

Validation.RegisterPanel = function(panelId) {
    var panel = $('#' + panelId)[0];

    var group = new Validation.Group();
    group.Id = panelId;

    group.Summary = Validation.GetValidationSummary(panelId);

    var inputs = panel.getElementsByTagName('input');
    var selects = panel.getElementsByTagName('select');

    var combined = new Array();
    for (var i = 0; i < inputs.length; i++) {
        combined = combined.concat(inputs[i]);
    }
    for (var i = 0; i < selects.length; i++) {
        combined = combined.concat(selects[i]);
    }

    var elements = combined;

    for (var i = 0; i < elements.length; i++) {

        var validate = elements[i].attributes['validate'];
        var fieldName = elements[i].attributes['fieldname'];
        var required = elements[i].attributes['required'];

        if (validate != null) {

            if (fieldName == undefined) {
                throw "Validation: Control '" + elements[i].id + "' is missing FieldName attribute";
            }

            var rules = validate.value.split(':');
            var type = rules[0];
            var attrs = [];

            if (rules.length > 1) {
                attrs = rules[1].trim().split(',');
            }

            var element = new Validation.Element();

            element.Control = $('#' + elements[i].id)[0];
            if ($('#' + elements[i].id + "Label").length != 0) {
                element.Label = $('#' + elements[i].id + "Label")[0];
            }
            element.Id = elements[i].id;
            element.Type = type;
            element.FieldName = fieldName.value;

            if (required != null) {
                element.Required = (required.value == "true" || required.value == "True"
                    || required.value == "yes" || required.value == "Yes"
                    || required.value == true);
            }

            for (var j = 0; j < attrs.length; j++) {
                var attr = attrs[j].trim();
                if (attr == 'required') {
                    element.Required = true;
                    if (element.Label) {
                        element.Label.innerHTML = element.Label.innerHTML + "*";
                        element.Label.style.fontWeight = "bold";
                    }
                }
                if (attr.startsWith('minvalue')) {
                    element.MinValue = attr.split('=')[1];
                }
                if (attr.startsWith('maxvalue')) {
                    element.MaxValue = attr.split('=')[1];
                }
                if (attr.startsWith('initial')) {
                    element.Initial = attr.split('=')[1];
                }

            }

            group.Elements[element.Id] = element;
        }
    }

    this.Groups[panelId] = group;
};

Validation.SetRequired = function (panelId, control, required)
{
    control.setAttribute("Required", required);
    this.Groups[panelId].Elements[control.id].Required = required;
};

Validation.ResetGroup = function (panelId)
{
    var group = this.Groups[panelId];
    group.Summary = Validation.GetValidationSummary(panelId);
    
    for (var element in group.Elements) {
        group.Elements[element].IsValid = true;
        group.Elements[element].Control.style.backgroundColor = "";
        if (group.Elements[element].Label) {
            group.Elements[element].Label.style.color = "";
        }
    }
    
    group.IsValid = true;
    
    Validation.UpdateValidationSummary(panelId);
};

Validation.Validate = function (panelId)
{
    Validation.ResetGroup(panelId);

    var group = this.Groups[panelId];
    
    for (var element in group.Elements) {
    	if (group.Elements[element].Control.style.display != 'none') {
	        if (Validation.ValidateElement(group, element) == false) {
	            group.IsValid = false;
	        }
    	}
    }
    
    Validation.UpdateValidationSummary(panelId);
    
    return group.IsValid;
};

Validation.DoesValidate = function (panelId)
{
    Validation.ResetGroup(panelId);

    var group = this.Groups[panelId];
    
    for (var element in group.Elements) {
        if (Validation.ValidateElement(group, element) == false) {
            group.IsValid = false;
            return false;
        }
    }
    return true;
};

Validation.ValidateControl = function (panelId, control)
{
    var group = this.Groups[panelId];    

    if (Validation.ValidateElement(group, control.id) == false) {
        control.style.backgroundColor = Validation.INVALIDBGCOLOR;
        return false;
    } else {
        control.style.backgroundColor = "";
        return true;
    }
};

Validation.ValidateElement = function(group, eleId) {

    var ele = group.Elements[eleId];

    if (ele.Control.nodeName != "SELECT") {
        Validation.CleanseElement(ele);
    }

    // Check for required first
    if (ele.Control.value.length == 0) {
        // If the element is required AND is not disabled, set to invalid.
        if (ele.Required == true && ele.Control.disabled == false) {
            ele.IsValid = false;
            ele.Message = ele.FieldName + Validation.ISREQUIRED;
            return false;
        }
        else {
            return true;
        }
    }

    var regExType = null;

    if (ele.Type == 'text') {
        return;
    }
    if (ele.Type == 'number') {
        regExType = Validation.Types.number;
    }
    if (ele.Type == 'decimal') {
        regExType = Validation.Types.decimal;
    }
    if (ele.Type == 'date') {
        regExType = Validation.Types.date;
    }
    if (ele.Type == 'time') {
        regExType = Validation.Types.time;
    }
    if (ele.Type == 'mysqlTime') {
        regExType = Validation.Types.mysqlTime;
    }
    if (ele.Type == 'currency') {
        regExType = Validation.Types.currency;
    }
    if (ele.Type == 'ssn') {
        regExType = Validation.Types.ssn;
    }
    if (ele.Type == 'yesNo') {
        regExType = Validation.Types.yesNo;
    }
    if (ele.Type == 'uscanzip') {
        regExType = Validation.Types.uscanzip;
    }
    if (ele.Type == 'usstate') {
        regExType = Validation.Types.usstate;
    }
    if (ele.Type == 'usphone') {
        regExType = Validation.Types.usphone;
    }
    if (ele.Type == 'email') {
        regExType = Validation.Types.email;
    }

    if (regExType == null) {
        alert("Validator: Regex type " + ele.Type + " unknown");
        return false;
    }

    var regex = new RegExp(regExType.regExp);
    var eleValue = ele.Control.value;

    if (regex.exec(eleValue) == null) {
        ele.IsValid = false;
        ele.Message = ele.FieldName + Validation.ISINVALID;
        return false;
    }

    if (ele.Type == 'number' || ele.Type == 'currency' || ele.Type == 'decimal' || ele.Type == 'time') {
        if (ele.Initial != null && ele.Required == true &&
                parseFloat(eleValue) == parseFloat(ele.Initial)) {
            ele.IsValid = false;
            ele.Message = ele.FieldName + Validation.ISREQUIRED;
            return false;
        }
        if (ele.MinValue != null && parseFloat(eleValue) < parseFloat(ele.MinValue)) {
            ele.IsValid = false;
            ele.Message = ele.FieldName + Validation.ISOUTOFRANGE;
            return false;
        }
        if (ele.MaxValue != null && parseFloat(eleValue) > parseFloat(ele.MaxValue)) {
            ele.IsValid = false;
            ele.Message = ele.FieldName + Validation.ISOUTOFRANGE;
            return false;
        }
    }

    return true;
};

Validation.CleanseElement = function (element)
{
    element.Control.value = element.Control.value.trim();
};

Validation.GetValidationSummary = function (panelId)
{
    var elements = $('#'+panelId)[0].getElementsByTagName('div');
    var validationSummaries = new Array();
    for (var i = 0; i < elements.length; i++) {
        if (elements[i].className == "ValidationSummary") {
            validationSummaries.push(elements[i]);
        }
    }
    
    return validationSummaries;
};

Validation.UpdateValidationSummary = function(panelId) {
    var group = this.Groups[panelId];
    var summaryText = "";

    if (group.IsValid == false) {
        summaryText = "<p>Some required entires are missing.<p>";
        summaryText += "<ul>";

        for (var element in group.Elements) {

            var ele = group.Elements[element];

            if (ele.IsValid == false) {
                summaryText += "<li>" + ele.Message + "</li>";
                //group.Elements[element].Control.style.backgroundColor = Validation.INVALIDBGCOLOR;
                if (group.Elements[element].Label) {
                    group.Elements[element].Label.style.color = "#ff0000";
                }
            }
        }
        summaryText += "</ul>";

        //window.scrollTo(0, 0);

    }

    for (var i = 0; i < group.Summary.length; i++) {
        group.Summary[i].style.display = (summaryText.length) ? "inline" : "none";
        group.Summary[i].innerHTML = summaryText;
    }
};

// ASP Validation Helpers

Validation.ValidateGroup = function (validationGroup)
{
    return Page_ClientValidate(validationGroup);
};

Validation.ResetValidationGroup = function(validationGroup)
{
    // Reset all validation controls for this validation group
    for (var i = 0; i < Page_Validators.length; i++) {
        if (Page_Validators[i].validationGroup == validationGroup) {
            Page_Validators[i].isvalid = true;
            ValidatorUpdateDisplay(Page_Validators[i]);
        }
    }
    
    // Reset the validation summary
    for (var i = 0; i < Page_ValidationSummaries.length; i++) {
        if (Page_ValidationSummaries[i].validationGroup == validationGroup) {
            Page_ValidationSummaries[i].style.display = "none";
        }
    }
};

Validation.Types = {
    date: {
        // Four-digit years only.  Supports Leap Years.
        regExp: /((^(10|12|0?[13578])([\/])(3[01]|[12][0-9]|0?[1-9])([\/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(11|0?[469])([\/])(30|[12][0-9]|0?[1-9])([\/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([\/])(2[0-8]|1[0-9]|0?[1-9])([\/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([\/])(29)([\/])([2468][048]00)$)|(^(0?2)([\/])(29)([\/])([3579][26]00)$)|(^(0?2)([\/])(29)([\/])([1][89][0][48])$)|(^(0?2)([\/])(29)([\/])([2-9][0-9][0][48])$)|(^(0?2)([\/])(29)([\/])([1][89][2468][048])$)|(^(0?2)([\/])(29)([\/])([2-9][0-9][2468][048])$)|(^(0?2)([\/])(29)([\/])([1][89][13579][26])$)|(^(0?2)([\/])(29)([\/])([2-9][0-9][13579][26])$))/
        //regExp: /^([0]?[1-9]|[1|2][0-9]|[3][0|1])[.\/-]([0]?[1-9]|[1][0-2])[.\/-]([0-9]{4}|[0-9]{2})$/
		//regExp: /^([0]?[1-9]|[1][0-2])[\.\/\-]([0]?[1-9]|[1|2][0-9]|[3][0|1])[\.\/\-]([0-9]{4}|[0-9]{2})$/
    },
    time: {
        // HOUR:MINUTE AM/PM
    	regExp: /(^([0-9]|[0-1][0-9]|[2][0-3]):([0-5][0-9])(\s{0,1})(AM|PM|am|pm|aM|Am|pM|Pm{2,2})$)|(^([0-9]|[1][0-9]|[2][0-3])(\s{0,1})(AM|PM|am|pm|aM|Am|pM|Pm{2,2})$)/
    },
    mysqlTime: {
        // mysql's default time format yyyy-mm-dd
        regExp: /^([0-1][0-9]|2[0-4]):([0-5][0-9]):([0-5][0-9])$/
    },
    currency: {
    	regExp: /^\$?(\d{1,3},?(\d{3},?)*\d{3}(\.\d{0,2})?|\d{1,3}(\.\d{0,2})?|\.\d{1,2}?)$/
    },
    currencyPositiveOnly: {
        regExp: /^\d*\.?\d*$/
    },
    number: {
        regExp: /^[-+]?[0-9]*$/
    },
	decimal: {
		regExp: /^[-+]?\d*\.?\d*$/
	},
	digits: {
		regExp: /^[-]?\d+(\.\d+)?$/
	},
	yesNo: {
	    regExp: /^[YN]?$/
	},
	email: {
		regExp: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/
	},
	uscanzip: {
		regExp: /^((\d{5}([- ])\d{4})|(\d{5})|([AaBbCcEeGgHhJjKkLlMmNnPpRrSsTtVvXxYy]\d[A-Za-z]\s?\d[A-Za-z]\d))$/
	},
	usstate: {
		regExp: /^(A[LKSZRAEP]|C[AOT]|D[EC]|F[LM]|G[ANU]|HI|I[ADLN]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$/
	},
	usphone: {
		regExp: /^([0-9]( |-|.)?)?(\(?[0-9]{3}\)?|[0-9]{3})( |-|.)?([0-9]{3}( |-|.)?[0-9]{4}|[a-zA-Z0-9]{7})$/
	},
	creditcard: {
		regExp: /^((4\d{3})|(5[1-5]\d{2})|(6011))([- ])?\d{4}([- ])?\d{4}([- ])?\d{4}|3[4,7]\d{13}$/
	},
	ssn: {
		regExp: /(^|\s)(00[1-9]|0[1-9]0|0[1-9][1-9]|[1-6]\d{2}|7[0-6]\d|77[0-2])(-?|[\. ])([1-9]0|0[1-9]|[1-9][1-9])\3(\d{3}[1-9]|[1-9]\d{3}|\d[1-9]\d{2}|\d{2}[1-9]\d)($|\s|[;:,!\.\?])/
	},
	alpha: {
		regExp: /^[a-zA-z\s]+$/
	},
	alphanum: {
		regExp: /^[a-zA-Z0-9]+$/
	}
};
