function DefaValidator() {
    this.loadConfig();
    window.onload = function() {
        defaValidator.prepareAlertDiv();
        defaValidator.resetFader();
    }

    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.beautyAlertHolder = 'main_body';

    this.emsgs = new Array();
    this.fakeLabels = new Array();

    /* Форма добавления сообщения */
    this.emsgs['add_msg'] = new Array();
    this.emsgs['add_msg']['msg_title'] = 'Укажите заголовок сообщения.';
    this.emsgs['add_msg']['msg_txt'] = 'Укажите текст сообщения.';
    this.emsgs['add_msg']['msg_work'] = 'Работа должна быть картинкой в формате gif или jpg.';
    this.emsgs['add_msg']['msg_prev_img'] = 'Изображение для превью должно быть картинкой в формате gif или jpg.';
    this.emsgs['add_msg']['msg_full_img'] = 'Изображение для полного текста должно быть картинкой в формате gif или jpg.';

    /* Форма редактирования сообщения */
    this.emsgs['edit_msg'] = new Array();
    this.emsgs['edit_msg']['msg_title'] = 'Укажите заголовок сообщения.';
    this.emsgs['edit_msg']['msg_txt'] = 'Укажите текст сообщения.';

    /* Форма добавления комментария */
    this.emsgs['add_comm'] = new Array();
    this.emsgs['add_comm']['comm_title'] = 'Укажите заголовок комментария.';
    this.emsgs['add_comm']['comm_txt'] = 'Укажите текст комментария.';

    /* Форма редактирования комментария */
    this.emsgs['edit_comment'] = new Array();
    this.emsgs['edit_comment']['msg_title'] = 'Укажите заголовок комментария.';
    this.emsgs['edit_comment']['msg_title'] = 'Укажите текст комментария.';

    /* Флрма авторизации */
    this.emsgs['auth_form'] = new Array();
    this.emsgs['auth_form']['u_login'] = 'Укажите логин.';
    this.emsgs['auth_form']['u_pwd'] = 'Укажите пароль.';

    /* Флрма восстановления пароля */
    this.emsgs['reminder'] = new Array();
    this.emsgs['reminder']['u_login'] = 'Укажите логин.';
}

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 = $(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 ((typeof(input.parentNode) != 'undefined') && input.parentNode) {
                input.parentNode.className = '';
            }
            break;
        case 1:
            //Alert only type. Do nothing.
            break;
        case 2:
            var label = $(input.name+'_label');
            var errorDiv = $('error_holder');
            var errSpan = $(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 ((typeof(input.parentNode) != 'undefined') && input.parentNode) {
                input.parentNode.className = '';
            }
    }
}

DefaValidator.prototype.makeIncorrect = function(input, alertType) {
    if (!alertType || (typeof(alertType) == 'undefined')) {
        var alertType = 0;
    }
    switch (alertType) {
        case 0:
            if ((typeof(input.parentNode) != 'undefined') && input.parentNode) {
                input.parentNode.className = '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')) {
                this.beautyAlert(this.emsgs[input.form.name][input.name]);
            } else {
                this.beautyAlert('Не все обязательные поля заполнены.');
            }
            break;
        case 2:
            var label = $(input.name+'_label');
            var errorDiv = $('error_holder');
            var commonError = $(input.form.name+'_err_msg');
            var insertedSpan = $(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) {
                input.parentNode.className = '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;
}


DefaValidator.prototype.prepareAlertDiv = function() {
    var div = document.createElement('div');
    var holder = $(this.beautyAlertHolder);

    if (!holder || (typeof(holder) == 'undefined')) {
        var divs = document.getElementsByTagName('div');
        holder = divs[0];
    }

    div.id = 'beauty_alert_div';
    div.innerHTML = '<b>ОШИБКА!</b>';

    var span = document.createElement('span');
    span.id = 'err_txt';
    span.innerHTML = 'Some error text';
    div.appendChild(span);

    var btnHolder = document.createElement('div');
    btnHolder.id = 'btn_holder';
    btnHolder.innerHTML = '<a href="#" onclick="this.parentNode.parentNode.style.display = \'none\'; if ($(\'fader\')) {$(\'fader\').style.display = \'none\';} return false;"><img src="/defa/i/ok_btn.gif" width="50" height="16" alt="OK" /></a>';
    div.appendChild(btnHolder);

    holder.appendChild(div);
}

DefaValidator.prototype.beautyAlert = function(txt, yesNo) {
    if (yesNo && (typeof(yesNo) != 'undefined')) {
        return confirm(txt);
    } else {
        var errTxt = $('err_txt');
        var beautyAlertDiv = $('beauty_alert_div');

        if (beautyAlertDiv && (typeof(beautyAlertDiv) != 'undefined') && errTxt && (typeof(errTxt) != 'undefined')) {
            if ($('fader')) {
                this.resetFader();
                $('fader').style.display = 'block';
            }
            errTxt.innerHTML = txt;
            beautyAlertDiv.style.display = 'block';
        } else {
            alert(txt);
        }
    }
}

DefaValidator.prototype.resetFader = function() {
    if ($('global') && $('fader')) {
        $('fader').style.width = $('global').offsetWidth + 'px';
        $('fader').style.height = $('global').offsetHeight + 'px';
    } else {
        alert('! WARNING !\n\nCouldn`t init fader! Use Internet Explorer 6.0+ or FireFox 1.5+ or Opera 9.0+');
    }
}

DefaValidator.prototype.proto = function() {
}

var defaValidator = new DefaValidator();
