Recently I had to perform a mask for dates with autocompletion, I searched and did not find answers to solve my doubts.
When you type '4' in the first field, you should already enter '0', and so on.
Well, I was able to come up with a code that would meet my needs, however, I think it might have been a bit confusing.
Would you guys have any tips, idea, to optimize this code?
I hope the code can help anyone who needs it. Thank you for your attention!
var before = " / / ";
var cont = true;
var copied = false;
//A máscara realiza comparações de "antes" e "depois" no keydown e //keyup
function beforeDate(field, e) {
var start = field.selectionStart;
var end = field.selectionEnd;
var key = e || window.event;
key = key.keyCode;
//Ações de ctrl+V, C ou X
var ctrl = e.ctrlKey ? e.ctrlKey : ((key === 17) ? true : false); // ctrl detection
if (((key == 86) || (key == 65) || (key == 67) || (key == 88)) && ctrl) {
if (key == 86 || key == 88) {
copied = true;
}
createSelection(field, 0, 10);
return;
}
//Caso o usuário tenha selecionado parte da data
//Preserva as barras e espaços
if (start != end) {
if ((key >= 48 && key <= 57) || (key >= 96 && key <= 105) || key == 8 || key == 46 || key == 32 || (key == 86 && ctrl) || (key == 67 && ctrl)) {
for (var i = start; i < end; i++) {
if (field.value.charAt(i) != "/") {
field.value = field.value.substring(0, i) + " " + field.value.substring(i + 1, 10);
}
}
before = field.value;
createSelection(field, field.value.indexOf(" "), field.value.indexOf(" "));
return false;
} else if (key >= 37 && key <= 40) {
return true;
} else {
return false;
}
}
//Setas
if (key >= 37 && key <= 40) {
return true;
} else if (key == 33) {
createSelection(field, 0, 0);
return;
} else if (key == 34) {
createSelection(field, field.value.length, field.value.length);
return;
} else if ((key >= 48 && key <= 57) || (key >= 96 && key <= 105) || key == 46) {
//Executar a ação uma vez por tecla
if (cont) {
cont = false;
if (field.value.charAt(2) != "/") {
field.value = setCharAt(field.value, 2, "/");
}
if (field.value.charAt(5) != "/") {
field.value = setCharAt(field.value, 5, "/");
}
createSelection(field, start, start);
before = field.value;
return;
}
return false;
} else if (key == 8) {
//Backspace pressionado
if (start != 0) {
if ((field.value.charAt(start - 1)) != "/") {
before = field.value;
field.value = setCharAt(field.value, start - 1, " ");
createSelection(field, start - 1, start - 1);
return false;
} else {
before = field.value;
createSelection(field, start - 1, start - 1);
return false;
}
}
}
};
//Evento Keyup
function afterDate(field, e) {
var key = e || window.event;
key = key.keyCode;
var after = field.value;
var cursor = field.selectionStart;
cont = true;
//Caso o usuário tenha colado uma data
if (copied) {
putMaskAgain(field);
copied = false;
}
if (!((key >= 48 && key <= 57) || (key >= 96 && key <= 105) || key == 46)) {
return false;
} else {
if ((key >= 48 && key <= 57) || (key >= 96 && key <= 105)) {
if (key >= 96) {
key -= 48;
}
var char = String.fromCharCode(key);
var aux = field.value.charAt(cursor);
if (aux != " " && aux != "/" && (field.value.charAt(cursor + 1)) == " ") {
field.value = setCharAt(field.value, cursor, char);
field.value = setCharAt(field.value, cursor + 1, aux);
return;
}
console.log(cursor);
//Valida a entrada dos dias nas posições 0, 1 e 2
switch (cursor) {
case 0:
if (char > 3) {
field.value = setCharAt(field.value, 0, 0);
field.value = setCharAt(field.value, 1, char);
cursor += 3;
} else {
field.value = setCharAt(field.value, 0, char);
cursor += 1;
}
break;
case 1:
if (field.value.charAt(0) == " ") {
if (char > 3) {
field.value = setCharAt(field.value, 0, 0);
field.value = setCharAt(field.value, 1, char);
cursor += 2;
} else {
field.value = setCharAt(field.value, 0, char);
}
} else {
field.value = setCharAt(field.value, 1, char);
cursor += 2;
}
break;
case 2:
if (field.value.charAt(0) == " " && field.value.charAt(1) == " ") {
if (char > 3) {
field.value = setCharAt(field.value, 0, 0);
field.value = setCharAt(field.value, 1, char);
cursor += 1;
} else {
field.value = setCharAt(field.value, 0, char);
}
} else if (field.value.charAt(0) != " " && field.value.charAt(1) == " ") {
field.value = setCharAt(field.value, 1, char);
cursor += 1;
} else if (field.value.charAt(0) == " " && field.value.charAt(1) != " ") {
if (char > 3) {
field.value = setCharAt(field.value, 0, 0);
cursor += 1;
} else {
field.value = setCharAt(field.value, 0, char);
}
} else {
if (char > 1) {
field.value = setCharAt(field.value, 3, 0);
field.value = setCharAt(field.value, 4, char);
cursor += 3;
} else {
field.value = setCharAt(field.value, 3, char);
cursor += 2;
}
}
break;
//Valida entrada dos meses nas posições 3,4 e 5
case 3:
if (char > 1) {
field.value = setCharAt(field.value, 3, 0);
field.value = setCharAt(field.value, 4, char);
cursor += 3;
} else {
field.value = setCharAt(field.value, 3, char);
cursor += 1;
}
break;
case 4:
if (field.value.charAt(3) == " ") {
if (char > 1) {
field.value = setCharAt(field.value, 3, 0);
field.value = setCharAt(field.value, 4, char);
cursor += 2;
} else {
field.value = setCharAt(field.value, 3, char);
}
} else {
field.value = setCharAt(field.value, 4, char);
cursor += 2;
}
break;
case 5:
if (field.value.charAt(3) == " " && field.value.charAt(4) == " ") {
if (char > 1) {
field.value = setCharAt(field.value, 3, 0);
field.value = setCharAt(field.value, 4, char);
cursor += 1;
} else {
field.value = setCharAt(field.value, 4, char);
}
} else if (field.value.charAt(3) != " " && field.value.charAt(4) == " ") {
field.value = setCharAt(field.value, 4, char);
cursor += 1;
} else if (field.value.charAt(3) == " " && field.value.charAt(4) != " ") {
if (field.value.charAt(4) > 1) {
field.value = setCharAt(field.value, 3, 0);
cursor += 1;
} else {
field.value = setCharAt(field.value, 3, field.value.charAt(4));
field.value = setCharAt(field.value, 4, char);
}
} else {
field.value = setCharAt(field.value, 6, char);
cursor += 2;
}
break;
default:
field.value = setCharAt(field.value, cursor, char);
cursor += 1;
break;
}
createSelection(field, cursor, cursor);
return false;
}
//Delete pressionado
if (key == 46) {
var dropped = "undefined";
for (var i = 0; i <= 9; i++) {
if (before.charAt(i) != after.charAt(i)) {
dropped = before.charAt(i);
break;
}
}
if (dropped != "undefined") {
if ((i - cursor) != 0) {
i -= (i - cursor);
}
if (cursor == 0 || cursor == 3) {
field.value = after.substring(0, i + 1) + " " + after.substring(i + 1, 10);
} else if (cursor == 1 || cursor == 4) {
field.value = after.substring(0, i) + " " + after.substring(i, 10);
} else if (cursor == 2) {
i + 1;
field.value = before.substring(0, 3) + before.substring(4, 10);
field.value = field.value.substring(0, 4) + " " + field.value.substring(4, 10);
} else if (cursor == 5) {
i + 1;
field.value = before.substring(0, 6) + before.substring(7, 10);
field.value = field.value + " ";
} else {
field.value = field.value + " ";
}
createSelection(field, i, i);
}
}
}
};
//Criar seleção/Mover o cursor intermitente
function createSelection(field, start, end) {
if ((navigator.userAgent.indexOf("MSIE") != -1) || (!!document.documentMode == true)) {
if (field.createTextRange) {
var selRange = field.createTextRange();
var range = field.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', start);
range.select();
field.focus();
} else if (field.setSelectionRange) {
field.focus();
field.setSelectionRange(start, startr);
} else if (typeof field.selectionStart != 'undefined') {
field.selectionStart = start;
field.selectionEnd = end;
field.focus();
}
} else {
if (field.createTextRange) {
var selRange = field.createTextRange();
selRange.collapse(true);
selRange.moveStart('character', start);
selRange.moveEnd('character', end);
selRange.select();
field.focus();
} else if (field.setSelectionRange) {
field.focus();
field.setSelectionRange(start, end);
} else if (typeof field.selectionStart != 'undefined') {
field.selectionStart = start;
field.selectionEnd = end;
field.focus();
}
}
};
//Substituir o char
function setCharAt(str, index, chr) {
if (index > str.length - 1) return str;
return str.substr(0, index) + chr + str.substr(index + 1);
};
//Recolocar a máscara
function putMaskAgain(field) {
var natural = field.value.replace(/[/]/g, "");
while (natural.length < 10) {
natural += " ";
}
field.value = (natural.substring(0, 2) + "/" + natural.substring(2, 4) + "/" + natural.substring(4, 8));
for (var i = 0; i <= 10; i++) {
if (isNaN(field.value.charAt(i)) && (field.value.charAt(i) != "/") && (i != 2 || i != 5)) {
field.value = setCharAt(field.value, i, " ");
} else if ((i != 2 && i != 5) && (field.value.charAt(i) == "/")) {
field.value = setCharAt(field.value, i, " ");
} else if ((i == 2 || i == 5) && (field.value.charAt(i) != "/")) {
field.value = setCharAt(field.value, i, "/");
}
createSelection(field, i, i);
}
createSelection(field, field.value.indexOf(" "), field.value.indexOf(" "));
return;
};
function putTheRangeOnTheStart(field) {
var start = field.selectionStart;
var end = field.selectionEnd;
if (start != end) {
return false;
}
if (field.value.trim().length == 10) {
return true;
}
createSelection(field, field.value.indexOf(" "), field.value.indexOf(" "));
};
body {
margin: 0;
padding: 0;
background-color: #EDEEF2;
}
.header {
padding-top: 20px;
background-color: #fff;
height: 250px;
margin: 0px;
}
.box {
background-color: #323A45;
width: 400px;
height: 350px;
font-size: 20px;
font-family: sans-serif;
text-align: center;
box-shadow: 0px 0px 10px #888;
border-radius: 5px;
}
.box p {
color: #fff;
font-weight: 700;
}
.box input {
margin-top: 10px;
background-color: #eaeaea;
padding: 10px;
border-style: none;
font-size: 20px;
border-radius: 3px;
width: 90%;
}
.conteudo {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.linha {
background: #529FD3;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
padding: 0.5px;
}
input[type=text]::-ms-clear {
display: none;
width: 0;
height: 0;
}
<html>
<head>
<title>Mascaras</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/estilo.css">
<script language="JavaScript" src="script.js"></script>
</head>
<body>
<div class="conteudo">
<div class="box">
<p>MÁSCARA DINÂMICA</p>
<div class="header">
<input type="text" id="input" onclick="putTheRangeOnTheStart(this)" onkeydown="return beforeDate(this,event)" onkeyup="return afterDate(this,event)" name= "teste" maxlength="10" value = " / / ">
</div>
</div>
</div>
</body>
</html>