Skip to content

Instantly share code, notes, and snippets.

@marvinhagemeister
Last active September 16, 2023 20:08
Show Gist options
  • Save marvinhagemeister/dfec9220a40d4ac08660224812ec9ca7 to your computer and use it in GitHub Desktop.
Save marvinhagemeister/dfec9220a40d4ac08660224812ec9ca7 to your computer and use it in GitHub Desktop.
DOM input masking
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<label for="foo">Input mask demo</label>
<input id="foo" type="text" pattern="\d{6}" />
<script>
/**
* @param {Event} ev
* @param {Array<string | RegExp>} expected - The input mask
*/
function maskHandler(ev, expected) {
const value = ev.target.value;
// Save selection or cursor position
const selStart = el.selectionStart;
const selEnd = el.selectionEnd;
let next = "";
let clearStart = 0;
let clearEnd = 0;
let checkIdx = 0;
for (let i = 0; i < value.length; i++) {
const check = expected[checkIdx];
const ch = value[i];
if (
check !== undefined &&
(typeof check === "string" ? ch === check : check.test(ch))
) {
checkIdx++;
next += ch;
continue;
}
// Adjust selection/cursor position for removed characters
if (i < selStart) clearStart++;
if (i > selStart && i < clearEnd) clearEnd++;
}
// Overwrite value if we needed to replace something
if (value !== next) {
ev.target.value = next;
const nextSelStart = selStart - clearStart;
const nextSelEnd = selEnd - clearStart - clearEnd;
el.setSelectionRange(nextSelStart, nextSelEnd);
}
}
const el = document.querySelector("input");
el.addEventListener("input", (ev) => {
// Usage
maskHandler(ev, [/\d/, /\d/, /\d/, /\d/, /\d/, /\d/]);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment