﻿        /*
        tValidator v1.0, by tony,080910
        部分思路及内容借鉴于Validator及Clean Form Validation
        */
        var tValidator = {
            ErrorItem: [document.forms[0]],
            ErrorMessage: ["Error Occured，Please check the following："],
            ClearState: function(elem) {
                with (elem) {
                    if (style.color == "red")
                        style.color = "";
                    var lastNode = parentNode.childNodes[parentNode.childNodes.length - 1];
                    if (lastNode.id == "_errPanel")
                        parentNode.removeChild(lastNode);
                }
            },
            AddError: function(obj, str) {
                this.ErrorItem[this.ErrorItem.length] = obj;
                this.ErrorMessage[this.ErrorMessage.length] = this.ErrorMessage.length + ":" + str;
            },
            init: function(settings) {
                this.settings = settings;
                this.form = this.$(this.settings["id"]);
                this.mode = this.settings["mode"];
                this.count = this.form.elements.length;
                this.ErrorItem[0] = this.form;
                this.form.onsubmit = function() {
                    return tValidator.validate();
                };
            },
            validate: function() {
                this.ErrorMessage.length = 1;
                this.ErrorItem.length = 1;
                var tV = this.settings["validator"];
                for (var i = 0; i < tV.length; i++) {
                    var _dataType = tV[i][1].split(",");
                    this.ClearState(this.$(tV[i][0]));
                    var iError = false;
                    for (var j = 0; j < _dataType.length; j++) {
                        if (j == 0) {
                            if (_dataType[j] != "required" && this.$(tV[i][0]).value == "") break;
                        }
                        if (iError || _dataType[j].length < 1) break;
                        var isPass = false;
                        var _tempType = _dataType[j].split("|");
                        for (var k = 0; k < _tempType.length; k++) {
                            if (_tempType[k].length > 0 && !isPass) {
                                switch (_tempType[k]) {
                                    case "regex":
                                    case "issafe":
                                    case "range":
                                    case "compare":
                                    case "group":
                                    case "groupin":
                                    case "limit":
                                    case "limitb":
                                    case "filter":
                                        with (this.$(tV[i][0])) {
                                            if (eval(this[_tempType[k]])) {
                                                isPass = true;
                                            }
                                        }
                                        break;
                                    default:
                                        if (this[_tempType[k]].test(this.$(tV[i][0]).value)) {
                                            isPass = true;
                                        }
                                        break;
                                }
                            }
                        }
                        if (!isPass) {
                            this.AddError(this.$(tV[i][0]), tV[i][2]);
                            iError = true;
                        }
                    }
                }
                if (this.ErrorMessage.length > 1) {
                    mode = this.mode || 1;
                    var errCount = this.ErrorItem.length;
                    switch (mode) {
                        case 2:
                            for (var i = 1; i < errCount; i++)
                                this.ErrorItem[i].style.color = "red";
                        case 1:
                            alert(this.ErrorMessage.join("\n"));
                            this.ErrorItem[1].focus();
                            break;
                        case 3:
                            alert(this.ErrorMessage.join("\n"));
                            for (var i = 1; i < errCount; i++) {
                                try {
                                    var span = document.createElement("SPAN");
                                    span.id = "_errPanel";
                                    span.style.color = "red";
                                    this.ErrorItem[i].parentNode.appendChild(span);
                                    span.innerHTML = this.ErrorMessage[i].replace(/\d+:/, "*");
                                }
                                catch (e) { alert(e.description); }
                            }
                            this.ErrorItem[1].focus();
                            break;
                        default:
                            alert(this.ErrorMessage.join("\n"));
                            break;
                    }
                    return false;
                }
                return true;
            },
            /* regex */
            required: /.+/,
            email: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
            cardid: /^[1-9]([0-9]{16}|[0-9]{13})[xX0-9]$/,
            phone: /^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/,
            mobile: /^((\(\d{2,3}\))|(\d{3}\-))?((13\d{9})|(15\d{9}))$/,
            url: /^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"])*$/,
            ip: /^(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5]).(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5]).(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5]).(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5])$/,
            currency: /^\d+(\.\d+)?$/,
            number: /^\d+$/,
            zip: /^[1-9]\d{5}$/,
            qq: /^[1-9]\d{4,8}$/,
            english: /^[A-Za-z]+$/,
            chinese: /^[\u0391-\uFFE5]+$/,
            username: /^[a-z]\w{3,19}$/i,
            integer: /^[-\+]?\d+$/,
            floatnum: /^[-\+]?\d+\.\d+$/,
            unsafe: /['"<>]+/,
            date: /((^((1[8-9]\d{2})|([2-9]\d{3}))([-\/\._])(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])$)|(^([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])([-\/\._])(0?2)([-\/\._])(29)$))/,
            /* fun */
            regex: "new RegExp(tV[i][3],'g').test(value)",
            issafe: "!this.unsafe.test(value)",
            compare: "this.CompareTo(value,tV[i][3],this.$(tV[i][4]).value)",
            range: "tV[i][3] < (value|0) && (value|0) < tV[i][4]",
            group: "this.Group(tV[i][3], tV[i][4], tV[i][5])",
            groupin: "this.GroupIn(tV[i][3], tV[i][4], tV[i][5])",
            filter: "this.Filter(value, tV[i][3])",
            limit: "this.Limit(value.length,tV[i][3], tV[i][4])",
            limitb: "this.Limit(this.LenB(value), tV[i][3], tV[i][4])",
            /* test fun */
            CompareTo: function(op1, operator, op2) {
                switch (operator) {
                    case "<>":
                        return (op1 != op2);
                    case ">":
                        return (op1 > op2);
                    case ">=":
                        return (op1 >= op2);
                    case "<":
                        return (op1 < op2);
                    case "<=":
                        return (op1 <= op2);
                    default:
                        return (op1 == op2);
                }
            },
            Filter: function(input, filter) {
                return new RegExp("^.+\.(?=EXT)(EXT)$".replace(/EXT/g, filter.split(/\s*,\s*/).join("|")), "gi").test(input);
            },
            Group: function(name, min, max) {
                var groups = document.getElementsByName(name);
                var hasChecked = 0;
                min = min || 1;
                max = max || groups.length;
                if (groups[0].options != undefined) {
                    for (var i = groups[0].options.length - 1; i >= 0; i--)
                        if (groups[0].options[i].selected) hasChecked++;
                }
                else {
                    for (var i = groups.length - 1; i >= 0; i--)
                        if (groups[i].checked) hasChecked++;
                }
                return min <= hasChecked && hasChecked <= max;
            },
            GroupIn: function(name, min, max) {
                var names = name.split(",");
                var hasChecked = 0;
                min = min || 1;
                max = max || names.length;
                for (var i = 0; i < names.length; i++) {
                    if (this.$(names[i]).value != "") hasChecked++;
                }
                return min <= hasChecked && hasChecked <= max;
            },
            Limit: function(len, min, max) {
                min = min || 0;
                max = max || Number.MAX_VALUE;
                return min <= len && len <= max;
            },
            LenB: function(str) {
                return str.replace(/[^\x00-\xff]/g, "**").length;
            },
            $: function(id) { return document.getElementById(id) == null ? document.getElementsByName(id)[0] : document.getElementById(id); }
        };

