function cancelEvent(event) {
    if (window.event) //IE only
    {
        event.cancelBubble = true;
        event.returnValue = false;
    }
    else {
        event.stopPropagation();
        event.preventDefault();
    }
    return false;
}

function Modifiers(alt, ctrl, shift) {
    this.alt = alt;
    this.ctrl = ctrl;
    this.shift = shift;
}

function KeyCodes() {
    this.BACKSPACE = 8;
    this.TAB = 9;
    this.END = 35;
    this.HOME = 36;

    this.LEFT = 37;
    this.UP = 38;
    this.RIGHT = 39;
    this.DOWN = 40;

    this.DELETE = 46;

    this.C = 67;
    this.V = 86;
    this.X = 88;
}

function KeyCode2Char(code, modifiers) {
    var ascii = code;
    var key = new KeyCodes();
    if (code >= 96 && code <= 105)
        ascii = code - 48;

    if (code == 111 || code == 193) {
        if (modifiers.shift && code == 193)
            ascii = 63;
        else
            ascii = 47;
    }

    if (code == 188 || code == 110) //virgula ,
    {
        /*if (event.shiftKey && code == 188) //Shift + ,(teclado numerico) = delete
        ascii = 60;
        else*/
        ascii = 44;
    }

    if (code == 189 || code == 109) //hifen -
    {
        if (modifiers.shift && code == 189)
            ascii = 95;
        else
            ascii = 45;
    }


    if (code == 190 || code == 194) //ponto .
    {
        if (modifiers.shift && code == 190)
            ascii = 62;
        else
            ascii = 46;
    }

    if (code >= 37 && code <= 40) //setas
    {
        return null
    }

    return String.fromCharCode(ascii);
}

function IsNumber(code) {
    return ((code >= 48 && code <= 57) || (code >= 96 && code <= 105));
}

function IsNumberAscii(code) {
    return (code >= 48 && code <= 57);
}

function IsEditKeys(code, modifiers) {
    var key = new KeyCodes();
    with (key) {
        return (code == BACKSPACE || code == TAB || code == END || code == HOME || code == LEFT || code == RIGHT || code == DELETE || (modifiers.ctrl && (code == C || code == V || code == X)));
    }
}

function RemovePunctuation(chr) {
    var chrNumbers = "";
    for (i = 0; i < chr.length; i++) {
        if (IsNumberAscii(chr.charCodeAt(i)))
            chrNumbers += chr.charAt(i);
    }
    return chrNumbers;
}

function GetSelection() {
    var selectedText;
    if (document.selection)
        selectedText = "document.selection.createRange().text";
    else if (document.getSelection)
        selectedText = "document.getSelection()";
    else if (window.getSelection)
        selectedText = "window.getSelection()";
    else return;
    return selectedText;
}

function validaNumeric(event, field) {
    var code = event.which || event.keyCode;
    
    if ((code > 47 && code < 58) || (code > 95 && code < 106))
        return true;

    var character = String.fromCharCode(code);

    if (IsNumberAscii(character))
        return true;

    if (code == 9 || code == 16 || code == 17 || code == 110 || code == 188) return true;
    if ((code > 34 && code < 41) || code == 8 || code == 46) return true;

    if (code == 67 || code == 86 || code == 88) //copy, past, cut
        if (event.ctrlKey)
        return true;

    return cancelEvent(event);
}

function FormatValor(event, control) {
    var code = event.which || event.keyCode;
    var mod = new Modifiers(event.altKey, event.ctrlKey, event.shiftKey);
    var key = new KeyCodes();

    if (IsEditKeys(code, mod) || (GetSelection().length > 0 && IsNumber(code))) {
        if (code != key.HOME && code != key.END && code != key.LEFT && code != key.UP && code != key.RIGHT && code != key.DOWN) {
            control.onkeyup = function() {
                this.value = FormatValorStr(control.value);
                this.onkeyup = null;
            }
        }
        return; //Propaga teclas de edição
    }
    else {
        if (IsNumber(code) || event == null) {
            control.value += KeyCode2Char(code, mod);
            control.value = FormatValorStr(control.value);
        }
        return cancelEvent(event);
    }
}

function FormatValorStr(valor) {
    var chrFomated = "";
    var chrNumbers = RemovePunctuation(valor);

    for (i = chrNumbers.length - 1; i >= 0; i--) {
        var chrTyped = chrNumbers.charAt(i);

        switch (chrFomated.length) {
            case 0:
                chrFomated = chrTyped + chrFomated;
                break;
            case 1: // virgula
                chrFomated = "," + chrTyped + chrFomated;
                break;
            case 2:
            case 3:
            case 4:
            case 5:
                chrFomated = chrTyped + chrFomated;
                break;
            default: // pontos
                if (((chrFomated.length - 2) % 4) == 0)
                    chrFomated = chrTyped + "." + chrFomated;
                else
                    chrFomated = chrTyped + chrFomated;
                break;
        }
    }
    return chrFomated;
}

function FormatCEP(event, control) {
    var code = event.which || event.keyCode;
    var mod = new Modifiers(event.altKey, event.ctrlKey, event.shiftKey);

    if (IsEditKeys(code, mod))
        return; //Propaga teclas de edição
    else {
        if (IsNumber(code) && control.value.length < 9) {
            control.value += KeyCode2Char(code, mod);

            switch (control.value.length) {
                case 5: // Traço
                    control.value += "-";
                    break;
            }

        }
        return cancelEvent(event);
    }
}

function FormatCPF(event, control) {
    var code = event.which || event.keyCode;
    var mod = new Modifiers(event.altKey, event.ctrlKey, event.shiftKey);

    if (IsEditKeys(code, mod))
        return; //Propaga teclas de edição
    else {
        if (IsNumber(code) && control.value.length < 14) {
            control.value += KeyCode2Char(code, mod);

            switch (control.value.length) {
                case 3: // Primeiro ponto
                    control.value += ".";
                    break;
                case 7: // Segundo ponto
                    control.value += ".";
                    break;
                case 11: // Traço
                    control.value += "-";
                    break;
            }

        }
        return cancelEvent(event);
    }
}

function FormatCNPJ(event, control) {
    var code = event.which || event.keyCode;
    var mod = new Modifiers(event.altKey, event.ctrlKey, event.shiftKey);

    if (IsEditKeys(code, mod))
        return; //Propaga teclas de edição
    else {
        if (IsNumber(code) && control.value.length < 18) {
            control.value += KeyCode2Char(code, mod);

            switch (control.value.length) {
                case 2: // Primeiro ponto
                    control.value += ".";
                    break;
                case 6: // Segundo ponto
                    control.value += ".";
                    break;
                case 10: // Barra
                    control.value += "/";
                    break;
                case 15: // Traço
                    control.value += "-";
                    break;
            }

        }
        return cancelEvent(event);
    }
}

function FormatData(event, control) {
    var code = event.which || event.keyCode;
    var mod = new Modifiers(event.altKey, event.ctrlKey, event.shiftKey);

    if (IsEditKeys(code, mod))
        return; //Propaga teclas de edição
    else {
        if (IsNumber(code) && control.value.length < 10) {
            var chr = KeyCode2Char(code, mod);
            var dataStr = control.value;
            switch (dataStr.length) {
                case 0: //Dia
                    if (chr >= 0 && chr <= 3) control.value += chr;  //de 0 a 3
                    break;
                case 1:
                    if (dataStr.charAt(0) == '3') {
                        if (chr >= 0 && chr <= 1) control.value += chr + "/";  //de 0 a 1
                    }
                    else {
                        if (dataStr.charAt(0) == '0') {
                            if (chr > 0) control.value += chr + "/";  //de 1 a 9
                        }
                        else
                            control.value += chr + "/"; //de 0 a 9
                    }
                    break;
                //case 2:// Slash "/" 
                case 3: //Mês
                    if (chr >= 0 && chr <= 1) control.value += chr;  //de 0 a 1
                    break;
                case 4:
                    if (dataStr.charAt(3) == '1') {
                        if (chr >= 0 && chr <= 2) control.value += chr + "/";  //de 0 a 2
                    }
                    else {
                        if (chr > 0) control.value += chr + "/";  //de 1 a 9
                    }
                    break;
                //case 5: // Slash "/" 
                case 6: //Ano
                    if (chr >= 0 && chr <= 2) control.value += chr;  //de 1 a 2
                    break;
                case 7:
                    if (dataStr.charAt(6) == '1') {
                        if (chr == 9) control.value += chr;  //igual a 9
                    }
                    else
                        if (chr == 0) control.value += chr;  //igual a 0
                    break;
                case 8: //idem case 9
                case 9:
                    control.value += chr;  //de 0 a 9
                    break;
            }

        }
        return cancelEvent(event);
    }
}

function FormatHora(event, control, acceptSeconds) {
    var code = event.which || event.keyCode;
    var mod = new Modifiers(event.altKey, event.ctrlKey, event.shiftKey);

    if (IsEditKeys(code, mod))
        return; //Propaga teclas de edição
    else {
        var limitChars = (acceptSeconds) ? 8 : 5;
        if (IsNumber(code) && control.value.length < limitChars) {
            var chr = KeyCode2Char(code, mod);
            var dataStr = control.value;
            switch (dataStr.length) {
                case 0: //Horas
                    if (chr >= 0 && chr <= 2) control.value += chr;  //de 0 a 2
                    break;
                case 1:
                    if (dataStr.charAt(0) == '2') {
                        if (chr >= 0 && chr <= 3) control.value += chr + ":";  //de 0 a 4
                    }
                    else {
                        control.value += chr + ":"; //de 0 a 9
                    }
                    break;
                case 2: control.value += ":";  // Colon ":"
                case 3: //Minutos
                    if (chr >= 0 && chr <= 5) control.value += chr;  //de 0 a 5
                    break;
                case 4:
                    control.value += chr + (acceptSeconds ? ":" : "");  //de 0 a 9
                    break;
                case 5: control.value += ":";  // Colon ":"
                case 6: //Segundos
                    if (chr >= 0 && chr <= 5) control.value += chr;  //de 0 a 5
                    break;
                case 7:
                    control.value += chr;  //de 0 a 9
                    break;
            }

        }
        return cancelEvent(event);
    }
}
