JS Input Masking 🎭
Thomas Steiner, Google�tomac@google.com or @tomayac�
Input masks are everywhere.
Some of them unintuitive.
Some of them unintuitive.
Some of them unintuitive.
Some of them surprising.
Some of them surprising.
Some of them surprising.
Some of them actually helpful.
Some of them actually helpful.
There are client-side solutions to this.
Full-size screenshot of 15 JavaScript Input Mask Libraries (https://bashooka.com/coding/javascript-input-mask-libraries/)
A lot actually.
Full-size screenshot of a search on npm for “input-mask” (https://www.npmjs.com/search?q=keywords:input-mask)
There are a number of Intl.* formatters already…
What if there was an Intl.InputMask formatter?
// 16 digits.
new Intl.InputMask("credit-card-number")� .format("4012888888881881");
// "4012 8888 8888 1881"
// 15 digits.
new Intl.InputMask("credit-card-number")� .format("378282246310005");
// "3782 822463 10005"
Credit card numbers
What if there was an Intl.InputMask formatter?
new Intl.InputMask("phone-number", {
locale: "DE"
}).format("00494012345678");
// "00 49 40 12345678"
Phone numbers
What if there was an Intl.InputMask formatter?
new Intl.InputMask("international-bank-account-number")
.format("de04200411330524962800");
// "DE04 2004 1133 0524 9628 00"
IBAN numbers
What if there was an Intl.InputMask formatter?
// Custom "dashed" phone number formatter based on
// `Intl.InputMask("phone-number")`.
new Intl.InputMask("custom", {
maskFunction: (input) => {� return new Intl.InputMask("phone-number", {
locale: "DE"
}).format(input).replaceAll(" ", "-");� }
}).format("00494012345678");
// "00-49-40-12345678"
Custom formatter
Started working on a polyfill.
How would code using this look like in practice?
creditCardInput.addEventListener('input', (e) => {
if (e.inputType === 'deleteContentBackward') {
e.target.value = e.target.value.trim();
return;
}
// Save the caret position.
let caretPos = creditCardInput.selectionStart;
const value = e.target.value;
// Apply the input masking.
e.target.value = new Intl.InputMask('credit-card-number').format(
e.target.value,
);
// Restore the caret position while neutralizing the masking.
if (value !== e.target.value) {
caretPos += e.target.value.length - value.length;
}
creditCardInput.selectionStart = caretPos;
creditCardInput.selectionEnd = caretPos;
});
Open questions
Where to draw the line? ISBN numbers, telephone numbers, IBANs, credit card numbers,… Someone suggested IPv6 formatting.��Should this just be left to the client side? There is a solid ecosystem of input masking libraries, but the introductory examples have shown that it’s still hard.�
Iff you all think this should happen, what’re the next steps? Right now I have an explainer (https://github.com/tomayac/js-input-masking), a “try before you buy” polyfill (https://github.com/tomayac/js-input-masking-polyfill/), and a TC39 idea (https://es.discourse.group/t/input-masking/835). What’s next?
JS Input Masking 🎭
Thomas Steiner, Google�tomac@google.com or @tomayac�