/** * Biblioteca de máscaras. * * aqui temos algumas máscaras para nos auxiliar no tratamento de eventos, bem * como métodos de validação que podem ser disparados em outro contexto. * * creditos originais da idpeia do timeout e do replace: * * http://elcio.com.br/ajax/mascara/ * * referências do subsistema de conserto do posicionamento do cursor: * * http://parentnode.org/javascript/working-with-the-cursor-position/ * http://msdn.microsoft.com/en-us/library/ms536623(VS.85).aspx * * @licence BSD-style, * @author sombriks at usix technology *///////////////////////////////////////////////////** * Motor abstrato e comum às mascaras. Criado apenas para prover comodidades de * herança. * * @param fild * campo que iremos atrelar a essa máscara * @param regra * função contendo a grega que modifica o value do campo * @param tamanho * (opcional) tamanho fixo do campo */function _AbstractMask(fild, regra, tamanho) { // validações em tempo de codificação if (!fild) throw new Error("infore o campo"); if (!regra) throw new Error("informe a regra"); // devido ao controle da posição do caractere temos que cuidar do foco // do campo também, pra não cair em laços eternos de roubo de foco... var fused; function fusin() { fused = true; } function fusout() { fused = false; } // wrapper que nos permite salvar a posição do cursor. function regrawrapper() { if (fild.createTextRange) {// TODO fazer pros IE's da vida, rsrs // 2 ranges no IE pra achar a posição, :] var r1 = document.selection.createRange(); var r2 = fild.createTextRange(); var pos = 0; if (fused) { while (r1.compareEndPoints("StartToStart", r2)) { r2.moveStart("character", 1); pos++; } } var tamIni = fild.value.length; regra.call(this); var tamFim = fild.value.length; var dif = tamFim - tamIni; if(fused){ r2 = fild.createTextRange(); r2.moveStart("character", pos + dif); r2.collapse(); r2.select(); } // console.debug("position: "+pos+" dif: "+dif); } else if (fild.selectionStart >= 0) { var pos = fild.selectionStart; var tamIni = fild.value.length; regra.call(this); var tamFim = fild.value.length; var dif = tamFim - tamIni; if (fused) { fild.selectionStart = pos + dif; fild.selectionEnd = pos + dif; } // console.debug("pos: "+pos+"\ttamIni: // "+tamIni+"\ttamFim:"+tamFim); } else { // die... } } function executar() { setTimeout(regrawrapper, 1); } if (fild.addEventListener) { fild.addEventListener("focus", fusin, true); fild.addEventListener("keypress", executar, true); fild.addEventListener("blur", fusout, true);// tomara q baste fild.addEventListener("blur", executar, true); } else if (fild.attachEvent) { fild.attachEvent("onfocus", fusin); fild.attachEvent("onkeypress", executar); fild.attachEvent("onblur", fusout); fild.attachEvent("onblur", executar); } var maxlength; if (tamanho) { maxlength = document.createAttribute("maxlength"); maxlength.nodeValue = tamanho; fild.setAttributeNode(maxlength); } // meio de encontrar essa máscara depois fild.mascara = this; // utilitário para removermos a máscara this.desinstalar = function() { if (fild.removeEventListener) { fild.removeEventListener("focus", fusin, true); fild.removeEventListener("keypress", executar, true); fild.removeEventListener("blur", fusout, true); fild.removeEventListener("blur", executar, true); } else if (fild.detachEvent) { fild.detachEvent("onfocus", fusin); fild.detachEvent("onkeypress", executar); fild.detachEvent("onblur", fusout); fild.detachEvent("onblur", executar); } fild.mascara = undefined; if (tamanho) { fild.removeAttributeNode(maxlength); } delete this;// XXX não sei se basta };}/** * máscara de cep */function CepMask(fild) { // regra function cep() { var v = fild.value; v = v.replace(/\D/g, ""); v = v.replace(/^(\d{5})(\d)/, "$1-$2"); fild.value = v; } _AbstractMask.call(this, fild, cep, 9); return fild;}/** * máscara para campo de telefone */function TelefoneMask(fild) { // regra function telefone() { var v = fild.value; v = v.replace(/\D/g, ""); v = v.replace(/^(\d\d)(\d)/g, "($1) $2"); v = v.replace(/(\d{4})(\d)/, "$1-$2"); fild.value = v; } _AbstractMask.call(this, fild, telefone, 14); return fild;}/** * Esta classe irá controlar o input de cpf's */function CpfMask(fild) { // regra function cpf() { var v = fild.value; v = v.replace(/\D/g, ""); v = v.replace(/(\d{3})(\d)/, "$1.$2"); v = v.replace(/(\d{3})(\d)/, "$1.$2"); v = v.replace(/(\d{3})(\d{1,2})$/, "$1-$2"); fild.value = v; } _AbstractMask.call(this, fild, cpf, 14); // matemática de validação de cpf's... this.validarCpf = function() { var s_aux = fild.value.replace(/\D/g, ""); var d1 = 0, d2 = 0, digito1 = 0, digito2 = 0, resto = 0, digitoCPF, nDigResult; for ( var n_Count = 1; n_Count < s_aux.length - 1; n_Count++) { digitoCPF = parseInt(s_aux.substring(n_Count - 1, n_Count)); d1 = d1 + (11 - n_Count) * digitoCPF; d2 = d2 + (12 - n_Count) * digitoCPF; } resto = (d1 % 11); if (resto < 2) digito1 = 0; else digito1 = 11 - resto; d2 += 2 * digito1; resto = (d2 % 11); if (resto < 2) digito2 = 0; else digito2 = 11 - resto; var nDigVerific = s_aux.substring(s_aux.length - 2, s_aux.length); nDigResult = digito1 + "" + digito2; if (nDigVerific != nDigResult) throw new Error("CPF invalido"); }; return fild;}/** * esta classe valida o input de cnpj's */function CnpjMask(fild) { // regra function cnpj() { var v = fild.value; v = v.replace(/\D/g, ""); v = v.replace(/^(\d{2})(\d)/, "$1.$2"); v = v.replace(/^(\d{2})\.(\d{3})(\d)/, "$1.$2.$3"); v = v.replace(/\.(\d{3})(\d)/, ".$1/$2"); v = v.replace(/(\d{4})(\d)/, "$1-$2"); fild.value = v; } _AbstractMask.call(this, fild, cnpj, 18); return fild;}/** * Esta classe faz com que o campo receba apenas números */function NumberMask(fild) { // regra function soNumeros() { fild.value = fild.value.replace(/\D/g, ""); } _AbstractMask.call(this, fild, soNumeros); return fild;}/* * cl4553 p4r4 35cr3v3r 4551m */function LeetMask(fild) { // regra function leet() { var v = fild.value; v = v.replace(/o/gi, "0"); v = v.replace(/i/gi, "1"); v = v.replace(/z/gi, "2"); v = v.replace(/e/gi, "3"); v = v.replace(/a/gi, "4"); v = v.replace(/s/gi, "5"); v = v.replace(/t/gi, "7"); fild.value = v; } _AbstractMask.call(this, fild, leet); return fild;}/** * classe de máscara para dinheiro */function ValorMask(fild) { // regra function valor() { var v = fild.value; v = v.replace(/\D/g, ""); v = v.replace(/(\d+)(\d{2})/, "$1,$2"); v = v.replace(/(\d+)(\d{3},\d{2})$/g, "$1.$2"); var qtdLoop = (v.length - 3) / 3; var count = -1; while (qtdLoop > count++) v = v.replace(/(\d+)(\d{3}.*)/, "$1.$2"); v = v.replace(/^(0+)(\d)/g, "$2"); fild.value = v; } _AbstractMask.call(this, fild, valor); return fild;}/** * Máscara para datas dd/mm/yyyy */function DataMask(fild) { // regra function data() { var v = fild.value; v = v.replace(/\D/g, ""); if (v.length < 5) v = v.replace(/(\d{2})(\d)/, "$1/$2"); else v = v.replace(/(\d{2})(\d{2})(\d)/, "$1/$2/$3"); // XXX removemos a correção em tempo de digitação porque // ficava demasiadamente invasiva. vamos adicionar um lançador de // exceção ou booleando inocente (NOT!!!) pra avisarmos que a data está // errada. // // if (v.length == 10) {// ajustador de limites // var dma = v.split("/"); // var d = new Date(); // d.setFullYear(dma[2], dma[1] - 1, dma[0]); // dma = [ d.getDate(), d.getMonth() + 1, d.getFullYear() ]; // if (10 > dma[0]) // dma[0] = "0" + dma[0]; // if (10 > dma[1]) // dma[1] = "0" + dma[1]; // v = dma[0] + "/" + dma[1] + "/" + dma[2]; // } fild.value = v; } /** * helper de validação de datas verificando os anos bissextos e os meses de * 30 e 31 dias. * * o retorno dessa função é void, pois a validação real se dá pelos throws * com suas mensagens de erro. */ this.validar = function() { var v = fild.value; // splittando a data var dma = v.match(/[0-9]+/g); var i; if (dma) i = dma.length; else throw new Error("data invalida"); while (i--) // tratar o 08 e 09 no mês/ano e datas idiotas como 0666. dma[i] = dma[i].replace(/^0+/, ""); if (dma[0] < 0) throw new Error("dia invalido"); if (dma[1]) {// mês foi informado? switch (parseInt(dma[1])) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: if (dma[0] > 31) throw new Error("dia invalido"); break; case 4: case 6: case 9: case 11: if (dma[0] > 30) throw new Error("dia invalido"); break; case 2:// bissexto? if (dma[2]) {// ano foi informado? // 1 - divisível por 400 if (dma[2] % 400 == 0) { if (dma[0] > 29) throw new Error("dia invalido"); // 2 - divisível por 4 mas não por 100 } else if (dma[2] % 4 == 0 && dma[2] % 100 != 0) { if (dma[0] > 29) throw new Error("dia invalido"); // 3 - fevereiro normal... } else if (dma[0] > 28) { throw new Error("dia invalido"); } } else if (dma[0] > 28) {// fallback para teste do 28 throw new Error("dia invalido"); } break; default: throw new Error("mês inválido"); } } }; _AbstractMask.call(this, fild, data, 10); return fild;}/** * máscara para placas de carro (HUX-1234) * */function PlacaMask(fild) { // regra function placa() { var v = fild.value; v = v.replace(/-/g, ""); var pr = v.match(/-/);// XXX revendo isso var v1 = v.substring(0, 3); var v2 = v.substring(3, 7); v1 = v1.replace(/\d|\W/g, ""); v1 = v1.toUpperCase(); v2 = v2.replace(/\D/g, ""); v = v1; if (v2 != "") v += "-" + v2; fild.value = v; } _AbstractMask.call(this, fild, placa, 8); return fild;}/** * * FUNÇÃO PRA ESCREVER ASSIM */function CaixaAltaMask(fild) { // regra function caixa() { var v = fild.value; v = v.toUpperCase(); fild.value = v; } _AbstractMask.call(this, fild, caixa); return fild;}/** * Esta classe faz com que o campo receba apenas endereços ip * * FIXME quebrada. */function IpMask(fild) { function tresOctetos() { var v = fild.value; v = v.replace(/[^\d|^\.]+/, ""); v = v.replace(/(\.)(\.)/, "$1"); v = v.replace(/(\d{3})(\d+)/, "$1.$2"); v = v.replace(/(\d{1,3}\.\d{3})(\d+)/, "$1.$2"); v = v.replace(/(\d{1,3}\.\d{1,3}\.\d{3})(\d+)/, "$1.$2"); v = v.replace(/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\.+)/, "$1"); v = v.replace(/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{3})([\.|\d]+)/, "$1"); fild.value = v; } _AbstractMask.call(this, fild, tresOctetos, 15); return fild;}/** * função para restringir o tamanho de um campo */function TamanhoCampo(fild, size) { var maxlength = document.createAttribute("maxlength"); maxlength.nodeValue = size; fild.setAttributeNode(maxlength); return fild;}