function FieldClass(elField, options) {
    var self = this;
    this.elField = elField;
    this.input = this.elField;//Old
    this.options = options || {};
    this.onPaste = false;
    this.label = $('label[for=' + this.elField.id + '][class*="defaultValue"]')[0];

    $(this.elField).focus(function() { self.elField.select() });
    $(this.input).bind("keydown change", function() { self.removeError(); });

    if (options instanceof Object) {
        if (this.options.latin == true) {
            this.options.reTyping = new RegExp("^[A-Z ]+$");
            this.options.textCase = "upper";
        }
        if (this.options.email == true) {
            this.options.reTyping = new RegExp("^[\\w\\-\.@]+$","i");
            this.options.textCase = null;
        }
        if (this.options.numbers == true) {
            this.options.reTyping = new RegExp("^[\\d]+$");
            this.options.textCase = null;
        }
        if (this.options.latinAndNumbers == true) {
            this.options.reTyping = new RegExp("^[\\dA-Z]+$");
            this.options.textCase = "upper";
        }

        if (this.options.reTyping != null) {
            this.filterString();
            $(this.elField).bind("keydown", function(event) { self.getCode(event); });
            $(this.elField).bind("keypress", function(event) { self.testTyping(event); });
            $(this.elField).bind("blur", function(event) { self.filterString(); });
        }
    }
    
    if (this.label != null) {
        setTimeout(function() { self.Update() }, 0);
        $(this.input).bind("keypress change", function() { self.Update() });
        $(this.input).bind("keypress keyup change", function() { setTimeout(function() { self.Update() }, 10) });
    }
}
FieldClass.prototype.removeError = function() {
    $(this.elField).removeClass('error');
}
FieldClass.prototype.Update = function() {
    if (this.elField.value != "" && this.label != null && this.label.className.indexOf("invisible") == -1) {
        $(this.label).addClass('invisible');
    } else if (this.elField.value == "" && this.label != null && this.label.className.indexOf("invisible") >= 0) {
        $(this.label).removeClass('invisible');
    }
}
FieldClass.prototype.testTyping = function(event) {
    var self = this;
    var charCode = (event.charCode) ? event.charCode : event.keyCode;
    var charCodeStr = String.fromCharCode(charCode);
    var keyCodeStr = String.fromCharCode(this.keyCode).toLowerCase();
    if (event.shiftKey)
        keyCodeStr = String.fromCharCode(this.keyCode).toUpperCase();
    keyCodeStr = this.toTextCase(keyCodeStr);

    if (event.ctrlKey && this.keyCode == 86) { //Ctrl + v (FF & Opera)
        setTimeout(function() { self.filterString() }, 1);
    }
    
    if (event.ctrlKey || event.altKey || (this.keyCode < 47 && this.keyCode != 32)) {
        return true;
    } else if (this.options.reTyping.test(charCodeStr)) {
        return true;
    } else {
        var strInCase = this.toTextCase(charCodeStr);
        if (this.options.reTyping.test(strInCase)) {
            this.pasteString(strInCase);
        } else if (65 <= this.keyCode && this.keyCode <= 90 && this.options.reTyping.test(keyCodeStr)) {
            this.pasteString(keyCodeStr);
        }
        if (this.options.email == true) {
            if (event.shiftKey && this.keyCode == 50)
                this.pasteString("@");
            if (event.shiftKey == false && this.keyCode == 190)
                this.pasteString(".");
        }
        event.preventDefault ? event.preventDefault() : event.returnValue = false;
    }
}
FieldClass.prototype.filterString = function() {
    var str = this.toTextCase(this.elField.value);
    var newStr = "";
    for (var i = 0, textLength = str.length; i < textLength; i++) {
        var iChar = str.charAt(i);
        if (this.options.reTyping.test(iChar)) {
            newStr += iChar;
        } else if (arTranslit[iChar]) {
            if (this.options.reTyping.test(arTranslit[iChar]))
                newStr += arTranslit[iChar];
        }
    }
    this.elField.value = newStr;
}
FieldClass.prototype.toTextCase = function(str) {
    var strNew = str;
    switch (this.options.textCase) {
        case "upper":
            strNew = strNew.toUpperCase();
            break;
        case "lower":
            strNew = strNew.toLowerCase();
            break;
    }
    return strNew
}
FieldClass.prototype.pasteString = function(strNew) {
    this.getSelection();
    var strStart = this.elField.value.substring(0, this.selectionStart);
    var strEnd = this.elField.value.substr(this.selectionEnd, this.elField.value.length);
    this.elField.value = strStart + strNew + strEnd;

    if (this.elField.setSelectionRange) {
        this.elField.setSelectionRange(this.selectionStart + 1, this.selectionStart + 1);
    } else {
        var SelectionRange = this.elField.createTextRange();
        SelectionRange.move("character", this.selectionStart + 1);
        SelectionRange.select();
    }
}
FieldClass.prototype.getCode = function(event) {
    this.keyCode = event.keyCode;
}
FieldClass.prototype.getSelection = function() {
    this.selectionStart = this.getSelectionStart() || 0;
    this.selectionEnd = this.getSelectionEnd();
}
FieldClass.prototype.getSelectionStart = function() {
    if (!this.elField.createTextRange) {
        return this.elField.selectionStart;
    } else {
        var SelectionRange = document.selection.createRange().duplicate()
        SelectionRange.moveEnd('character', this.elField.value.length)
        return this.elField.value.lastIndexOf(SelectionRange.text)
    }
}
FieldClass.prototype.getSelectionEnd = function() {
    if (!this.elField.createTextRange) {
        return this.elField.selectionEnd
    } else {
        var SelectionRange = document.selection.createRange().duplicate()
        SelectionRange.moveStart('character', -this.elField.value.length)
        return SelectionRange.text.length
    }
}
