The patterns nobody ships
CNIC, Emirates ID, UAE TRN, Saudi VAT, IBAN, cards and a MAC address — by name, with a token of your own where the built-in classes run out.
<div class="demo demo--wide">
<div class="demo-row">
<div class="demo-seg" id="preset" role="group" aria-label="Pattern">
<button type="button" data-preset="cnic" aria-pressed="true">CNIC</button>
<button type="button" data-preset="emirates-id">Emirates ID</button>
<button type="button" data-preset="uae-trn">UAE TRN</button>
<button type="button" data-preset="saudi-vat">Saudi VAT</button>
<button type="button" data-preset="iban">IBAN</button>
<button type="button" data-preset="card">Card</button>
<button type="button" data-preset="mac">MAC</button>
</div>
</div>
<input class="demo-input" id="field" inputmode="numeric">
<dl class="demo-kv" id="out"></dl>
<p class="demo-hint">Switching the pattern keeps what is typed and regroups it — which is what a
card field has to do the moment it works out the issuer. Every length here is the one
<strong>Devix Validators</strong> checks, so the mask and the rule cannot disagree.</p>
</div>
import { createMaskedInput, PRESETS } from 'https://devix.pk/cdn/oss/masked-input@1.0.0/index.js';
const field = document.getElementById('field');
const out = document.getElementById('out');
const group = document.getElementById('preset');
const SAMPLE = {
cnic: '4210112345671',
'emirates-id': '784199012345671',
'uae-trn': '100345678901234',
'saudi-vat': '310122393500003',
iban: 'AE070331234567890123456',
card: '4111111111111111',
mac: 'a1b2c3d4e5f6',
};
let name = 'cnic';
const widget = createMaskedInput(field, { mask: name, onChange: () => show() });
function show() {
const state = widget.read();
out.innerHTML = `
<div><dt>pattern</dt><dd>${PRESETS[name].pattern}</dd></div>
<div><dt>takes</dt><dd>${widget.mask.capacity} characters</dd></div>
<div><dt>you would store</dt><dd>${state.raw || '—'}</dd></div>
<div><dt>complete</dt><dd>${state.complete ? 'yes' : 'not yet'}</dd></div>`;
}
group.addEventListener('click', (event) => {
const button = event.target.closest('button');
if (!button) return;
for (const other of group.querySelectorAll('button')) other.setAttribute('aria-pressed', String(other === button));
name = button.dataset.preset;
// The digits already typed are kept and re-grouped, not thrown away.
widget.setMask(name);
if (widget.read().empty) widget.setValue(SAMPLE[name]);
field.focus();
show();
});
widget.setValue(SAMPLE.cnic);
show();
@import url('https://devix.pk/cdn/oss/masked-input@1.0.0/masked-input.min.css');
#field { width: 100%; font-size: 15px; }
.demo-kv dd { font-variant-numeric: tabular-nums; }