function DefaValidator() {
    this.loadConfig();

    if (browserInfo && (typeof(browserInfo) != 'undefined') && (browserInfo.whoami == 'defabrowserchecker')) {
        this.browser = browserInfo.browser;
        this.majorVersion = browserInfo.majorVersion;
        this.minorVersion = browserInfo.minorVersion;
    } else {
        this.checkBrowser();
    }

    this.reBlank = new RegExp('^[\\s ]*$', 'i');
    this.reMail = new RegExp('^[a-z][a-z0-9_\\-\\.]+@[a-z0-9_\\-\\.]+\\.[a-z]{2,}$', 'i');
    this.reUrl = new RegExp('^http:\\/\\/[a-z0-9_\\-\\.]+\\.[a-z]{2,}(\/.*)?$', 'i');
    this.reAlnum = new RegExp('^[a-z0-9_]*$', 'i');
    this.reDate = new RegExp('^(\\d{4}-\\d{2}-\\d{2}|\\d{2}\\.\\d{2}\\.\\d{4})$', 'i');
    this.reInteger = new RegExp('^-*\\d+$', 'i');
}

DefaValidator.prototype.loadConfig = function() {
    this.emsgs = new Array();
    this.fakeLabels = new Array();

    /* Форма авторизации */
    this.emsgs['live_auth_form'] = new Array();
    this.emsgs['live_auth_form']['u_login'] = 'Укажите логин.';
    this.emsgs['live_auth_form']['u_pwd'] = 'Укажите пароль.';

    /* Форма регистрации/профайла */
    this.emsgs['reg_form'] = new Array();
    this.emsgs['reg_form']['u_login'] = 'Логин может содержать только латинские буквы, цифры и знак "_".';
    this.emsgs['reg_form']['u_pwd'] = 'Пароль может содержать только латинские буквы, цифры и знак "_". Длина пароля -- от 6 символов.';
    this.emsgs['reg_form']['u_ppwd'] = 'Пароли не совпадают.';    
    this.emsgs['reg_form']['u_name'] = 'Укажите имя.';
    this.emsgs['reg_form']['u_surname'] = 'Укажите фамилию.';
    this.emsgs['reg_form']['u_mail'] = 'Введите корректный e-mail.';

}

DefaValidator.prototype.checkBrowser = function() {
    var browserStr = navigator.userAgent;

    if (browserStr.indexOf('Firefox') != -1) {
        this.browser = 'FF';
        var arr = /Firefox\/(\d+)\.(\d+)/.exec(browserStr);
        this.majorVersion = arr[1];
        this.minorVersion = arr[2];
    } else if (browserStr.indexOf('Opera') != -1) {
        this.browser = 'O';
        var arr = /Opera (\d+)\.(\d+)/.exec(browserStr);
        if (!arr) {
            var arr = /Opera\/(\d+)\.(\d+)/.exec(browserStr);
        }
        if (arr) {
            this.majorVersion = arr[1];
            this.minorVersion = arr[2];
        } else {
            this.majorVersion = 1;
            this.minorVersion = 0;
        }
    } else if (browserStr.indexOf('MSIE') != -1) {
        this.browser = 'IE';
        var arr = /MSIE (\d+)\.(\d+)/.exec(browserStr);
        this.majorVersion = arr[1];
        this.minorVersion = arr[2];
    } else {
        this.browser = 'smth';
        this.majorVersion = 0;
        this.minorVersion = 0;
    }

    //alert(this.browser+' '+this.majorVersion+'.'+this.minorVersion);
}

DefaValidator.prototype.catchEvent = function(input, event_type, alertType) {
    if (!alertType || (typeof(alertType) == 'undefined')) {
        var alertType = 0;
    }

    switch (event_type.type) {
        case 'change':
            this.catchOnChange(input);
            break;
        default:
            alert('Undefined event');
    }
}

DefaValidator.prototype.catchOnChange = function(input, fake_field, alertType) {
    if (!alertType || (typeof(alertType) == 'undefined')) {
        var alertType = 0;
    }

    if (fake_field && (typeof(fake_field) != 'undefined')) {
        var fake_input = document.getElementById(fake_field);
    }

    if (input.type && (typeof(input.type) != 'undefined') && ((input.type == 'radio') || (input.type == 'checkbox'))) {
        var group = input.form[input.name];
        if (group.length && (typeof(group.length) != 'undefined')) {
            for (var i = 0; i < group.length; i++) {
                if (group[i] && (typeof(group[i]) != 'undefined') && (typeof(group[i].id) != 'undefined') && (group[i].id != '')) {
                    input = group[i];
                }
            }
        }
    }

    if (fake_input && (typeof(fake_input) != 'undefined')) {
        input = fake_input;
    }

    var validationType = this.getValidationType(input.id);
    if (validationType !== false) {
        if (this.checkField(input, validationType)) {
            this.makeCorrect(input, alertType);
        } else {
            this.makeIncorrect(input, alertType);
        }
    }
}

DefaValidator.prototype.getValidationType = function(id) {
    if (id.indexOf('validation_') != -1) {
        var params = new Array();
        var re = new RegExp('validation_(.+)$');
        var arr = re.exec(id);

        var tmp = this.explode(arr[1], '_');

        this.params = tmp;

        return tmp[0];
    } else {
        return false;
    }
}

DefaValidator.prototype.checkField = function(input, type) {
    if ((this.params[this.params.length - 1] == 'empty') && (input.value == '')) {
        return true;
    }

    switch (type) {
        case 'file':
        case 'blank':
            return (!this.reBlank.test(input.value));
            break;
        case 'mail':
            return (this.reMail.test(input.value));
            break;
        case 'url':
            return (this.reUrl.test(input.value));
            break;
        case 'length':
            if (this.params[2] > 0) {
                return ((input.value.length >= this.params[1]) && (input.value.length <= this.params[2]));
            } else {
                return (input.value.length >= this.params[1]);
            }
            break;
        case 'alnum':
            if ((this.params[1] > 0) && (this.params[2] > 0)) {
                return ((input.value.length >= this.params[1]) && (input.value.length <= this.params[2]) && this.reAlnum.test(input.value));
            } else if (this.params[1] > 0) {
                return ((input.value.length >= this.params[1]) && this.reAlnum.test(input.value));
            } else {
                return (this.reAlnum.test(input.value));
            }
            break;
        case 'equal2':
            /* Equal2 requires only one param */
            for (var i = 2; i < this.params.length; i++) {
                this.params[1] += '_'+this.params[i];
            }
            if (this.params[1] && (typeof(input.form[this.params[1]]) != 'undefined')) {
                return (input.value == input.form[this.params[1]].value);
            } else {
                return false;
            }
            break;
        case 'ext':
            var exts = this.explode(this.params[1], '-');
            var re = new RegExp('\\.([a-z0-9]+)$', 'i');
            if (re.test(input.value)) {
                var arr = re.exec(input.value);
                return this.inArray(arr[1], exts);
            } else {
                return false;
            }
            break;
        case 'radio':
            var group = input.form[input.name];
            if (group.length && (typeof(group.length) != 'undefined')) {
                for (var i = 0; i < group.length; i++) {
                    if (group[i] && (typeof(group[i]) != 'undefined') && group[i].checked) {
                        return true;
                    }
                }
            } else {
                return input.checked;
            }
            return false;
            break;
        case 'fakeradio':
            return (input.value != '');
            break;
        case 'checkbox':
            var group = input.form[input.name];
            if (group.length && (typeof(group.length) != 'undefined')) {
                for (var i = 0; i < group.length; i++) {
                    if (group[i] && (typeof(group[i]) != 'undefined') && group[i].checked) {
                        return true;
                    }
                }
            } else {
                return input.checked;
            }
            return false;
            break;
        case 'fakecheckbox':
            var group = input.form[input.name];
            if (group.length && (typeof(group.length) != 'undefined')) {
                for (var i = 0; i < group.length; i++) {
                    if (group[i] && (typeof(group[i]) != 'undefined') && (group[i].value != '')) {
                        return true;
                    }
                }
            } else {
                return (input.value != '');
            }
            break;
        case 'date':
            return (this.reDate.test(input.value));
            break;
        case 'integer':
            /* Making int */
            this.params[1]++; this.params[1]--;
            this.params[2]++; this.params[2]--;
            var x = input.value - 1;
            x++;

            if (this.reInteger.test(input.value)) {
                if (this.params[2] > 0) {
                    return ((x >= this.params[1]) && (x <= this.params[2]) && this.reInteger.test(input.value));
                } else if (this.params[1] > 0) {
                    return ((x >= this.params[1]) && this.reInteger.test(input.value));
                } else {
                    return true;
                }
            }
            return false;
            break;
        default:
            return false;
    }
}

DefaValidator.prototype.makeCorrect = function(input, alertType) {
    if (!alertType || (typeof(alertType) == 'undefined')) {
        var alertType = 0;
    }

    switch (alertType) {
        case 0:
            if (input.type == 'file') {
                if ((typeof(input.parentNode.parentNode) != 'undefined') && input.parentNode.parentNode) {
                    if (input.parentNode.parentNode.className.indexOf('formitem') != -1) {
                        input.parentNode.parentNode.className = 'formitem';
                    } else {
                        input.parentNode.parentNode.className = 'field_holder_ok';
                    }
                }
            } else {
                if ((typeof(input.parentNode) != 'undefined') && input.parentNode) {
                    if (input.parentNode.className.indexOf('formitem') != -1) {
                        input.parentNode.className = 'formitem';
                    } else {
                        input.parentNode.className = 'field_holder_ok';
                    }
                }
            }
            break;
        case 1:
            //Alert only type. Do nothing.
            break;
        case 2:
            var label = document.getElementById(input.name+'_label');
            var errorDiv = document.getElementById('error_holder');
            var errSpan = document.getElementById(input.name+'_err_msg');

            /* Deleteing error messages */
            if (errorDiv && (typeof(errorDiv) != 'undefined')) {
                /* Delete message for current field */
                if (errSpan && (typeof(errSpan) != 'undefined')) {
                    errorDiv.removeChild(errSpan);
                }

                /* Delete common message, if it is last */
                var spanList = errorDiv.getElementsByTagName('span');
                if (spanList && (typeof(spanList) != 'undefined') && (spanList.length == 1) && (spanList[0].id == (input.form.name+'_err_msg'))) {
                    errorDiv.removeChild(spanList[0]);
                }
            }

            /* Unhighliting label */
            if (label && (typeof(label) != 'undefined')) {
                label.className = '';
            }

            break;
        default:
            if (input.type == 'file') {
                if ((typeof(input.parentNode.parentNode) != 'undefined') && input.parentNode.parentNode) {
                    if (input.parentNode.parentNode.className.indexOf('formitem') != -1) {
                        input.parentNode.parentNode.className = 'formitem';
                    } else {
                        input.parentNode.parentNode.className = 'field_holder_ok';
                    }
                }
            } else {
                if ((typeof(input.parentNode) != 'undefined') && input.parentNode) {
                    if (input.parentNode.className.indexOf('formitem') != -1) {
                        input.parentNode.className = 'formitem';
                    } else {
                        input.parentNode.className = 'field_holder_ok';
                    }
                }
            }
    }
}

DefaValidator.prototype.makeIncorrect = function(input, alertType) {
    if (!alertType || (typeof(alertType) == 'undefined')) {
        var alertType = 0;
    }
    switch (alertType) {
        case 0:
            if (input.type == 'file') {
                if ((typeof(input.parentNode.parentNode) != 'undefined') && input.parentNode.parentNode) {
                    if (input.parentNode.parentNode.className.indexOf('formitem') != -1) {
                        input.parentNode.parentNode.className = 'formitem_err';
                    } else {
                        input.parentNode.parentNode.className = 'field_holder_err';
                    }
                }
            } else {
                if ((typeof(input.parentNode) != 'undefined') && input.parentNode) {
                    if (input.parentNode.className.indexOf('formitem') != -1) {
                        input.parentNode.className = 'formitem_err';
                    } else {
                        input.parentNode.className = 'field_holder_err';
                    }
                }
            }
            break;
        case 1:
            if (this.emsgs[input.form.name] && (typeof(this.emsgs[input.form.name]) != 'undefoned') && this.emsgs[input.form.name][input.name] && (typeof(this.emsgs[input.form.name][input.name]) != 'undefined')) {
                alert(this.emsgs[input.form.name][input.name]);
            } else {
                alert('Не все обязательные поля заполнены.');
            }
            break;
        case 2:
            var label = document.getElementById(input.name+'_label');
            var errorDiv = document.getElementById('error_holder');
            var commonError = document.getElementById(input.form.name+'_err_msg');
            var insertedSpan = document.getElementById(input.name+'_err_msg');
            var spanExists = false;

            /* Printing or alerting error message */
            if (errorDiv && (typeof(errorDiv) != 'undefined')) {
                var span = document.createElement('span');
                span.id = input.name+'_err_msg';
                if (this.emsgs[input.form.name] && (typeof(this.emsgs[input.form.name]) != 'undefoned') && this.emsgs[input.form.name][input.name] && (typeof(this.emsgs[input.form.name][input.name]) != 'undefined')) {
                    span.innerHTML = this.emsgs[input.form.name][input.name];
                    /* Checking if error message exists */
                    if (insertedSpan && (typeof(insertedSpan) != 'undefined')) {
                        spanExists = true;
                    }
                } else {
                    span.id = input.form.name+'_err_msg';
                    span.innerHTML = 'Не все обязательные поля заполнены.';
                    /* Checking if common error message exists */
                    if (commonError && (typeof(commonError) != 'undefined')) {
                        spanExists = true;
                    }
                }
                if (!spanExists) {
                    errorDiv.appendChild(span);
                }
            } else {
                if (this.emsgs[input.form.name] && (typeof(this.emsgs[input.form.name]) != 'undefoned') && this.emsgs[input.form.name][input.name] && (typeof(this.emsgs[input.form.name][input.name]) != 'undefined')) {
                    alert(this.emsgs[input.form.name][input.name]);
                } else {
                    alert('Не все обязательные поля заполнены.');
                }
            }

            /* Highliting label */
            if (label && (typeof(label) != 'undefined')) {
                label.className = 'eggog';
            }

            break;
        default:
            if ((typeof(input.parentNode) != 'undefined') && input.parentNode) {
                if (input.parentNode.className.indexOf('formitem') != -1) {
                    input.parentNode.className = 'formitem_err';
                } else {
                    input.parentNode.className = 'field_holder_err';
                }
            }
    }
}

DefaValidator.prototype.explode = function(str, sep) {
    var arr = new Array();

    if (str.indexOf(sep) != -1) {
        var pos;

        while ((pos = str.indexOf(sep)) != -1) {
            arr[arr.length] = str.slice(0, pos);
            str = str.slice(pos + 1, str.length);
        }

        arr[arr.length] = str;
    } else {
        arr[0] = str;
    }

    return arr;
}

DefaValidator.prototype.inArray = function(needle, haystack) {
    for (i in haystack) {
        if (needle == haystack[i]) {
            return true;
        }
    }
    return false;
}

DefaValidator.prototype.validateForm = function(form, alertType) {
    if (!alertType || (typeof(alertType) == 'undefined')) {
        var alertType = 0;
    }

    var ok = true;
    var focused = false;
    for (var i = 0; i < form.elements.length; i++) {
        if (form.elements[i] && (typeof(form.elements[i]) != 'undefined') && (typeof(form.elements[i].id) != 'undefined') && (/validation_/.test(form.elements[i].id))) {
            var validationType = this.getValidationType(form.elements[i].id);
            if (this.checkField(form.elements[i], validationType)) {
                this.makeCorrect(form.elements[i], alertType);
            } else {
                this.makeIncorrect(form.elements[i], alertType);
                if (!focused && (form.elements[i].type != 'hidden')) {
                    form.elements[i].focus();
                    focused = true;
                }
                ok = false;
                if (alertType == 1) {
                    return ok;
                }
            }
        }
    }

    return ok;
}


/* Alisa. Опросы. */
DefaValidator.prototype.cutomValidation1 = function(form, type, id) {
    var ok = false;
    var reRadio = new RegExp('^\\d+$');
    var reCheckbox = new RegExp('^(_\\d+)+_$');
    var inp = document.getElementById('poll_'+id);
    var err = document.getElementById('err_'+id);

    if (inp && (typeof(inp) != 'undefined')) {
        switch (type) {
            case 'radio':
                ok = reRadio.test(inp.value);
                break;
            case 'checkbox':
                ok = reCheckbox.test(inp.value);
                break;
            default:
                ok = false;
        }
    } else {
        ok = false;
    }

    if (!ok) {
        if (err && (typeof(err) != 'undefined')) {
            err.style.display = 'block';
        } else {
            alert('Выберите вариант ответа.');
        }
    } else {
        if (err && (typeof(err) != 'undefined')) {
            err.style.display = 'none';
        }
    }

    return ok;
}

DefaValidator.prototype.proto = function() {
}

var defaValidator = new DefaValidator();