Skip to content

Instantly share code, notes, and snippets.

@BananaAcid
Last active July 18, 2023 15:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BananaAcid/30600d75c102dbac8906298d74c8bee5 to your computer and use it in GitHub Desktop.
Save BananaAcid/30600d75c102dbac8906298d74c8bee5 to your computer and use it in GitHub Desktop.
HTML number input with rules
// Nabil Redmann, ISC
/*
<input type="number" maxlength="3" data-digits="2" placeholder="format xxx.xx" />
<br><br><br>
<input type="number" maxlength="3" data-digits="0" placeholder="no fractions" />
<br><br><br>
<input type="number" maxlength="0" data-digits="3" placeholder="only dot first and digits " />
*/
export default function numberFieldsMagic() {
//document.addEventListener('DOMContentLoaded', e => {
// '[type="number"][maxlength]'
document.querySelectorAll('[type="number"]').forEach( (element) => {
let el = element as HTMLInputElement;
console.log(el);
// prepare element
el.dataset.type = el.dataset.type ?? el.type;
el.type = 'text';
el.dataset.maxLength = el.dataset.maxLength ?? ''+el.maxLength;
if (el.attributes.getNamedItem('maxlength'))
el.attributes.removeNamedItem('maxlength');
el.addEventListener('input', oIe => {
//console.log(oIe);
let t = oIe.target as HTMLInputElement;
let digits = +(t.dataset.digits ?? 2);
let pos = t.selectionStart ?? 0; // only works, if type="text"
let x = 0;
let dataStart = t.value;
let data = t.value;
data = data
// only allow: - , . 01234567890
.replace(/[^-,.0-9]/g, '')
// comma will become dots
.replaceAll(',', '.')
// only one dot
.replace(/\./g, (c, i, text) => text.indexOf(c) === i ? c : '')
// no .00
.replace(/\.00/g, '')
// limit digits
.replace(/\.\d+/, (c, i, text) => {x++; return c.slice(0, digits + 1);})
;
if (data && data[0] == '0' && data[1] !== '.') {
data = data.slice(1);
}
// digits before dot, allow 0 as length
if (t.dataset.maxLength !== undefined && t.dataset.maxLength !== '-1') {
// regex needs a leading digit to work
if (data[0] == '.') {
data = '0' + data;
x++
};
data = data
.replace(/(\d+)([\.]|$)/, (complete, group1, group2) => group1.slice(0, t.dataset.maxLength) + group2.trim())
}
if (data !== dataStart) {
t.value = data;
let substract = (data.length < dataStart.length) ? -1 : 0;
substract += x;
t.selectionStart = pos + substract;
t.selectionEnd = pos + substract;
}
});
el.addEventListener('blur', oBe => {
let t = oBe.target as HTMLInputElement;
let dataStart = t.value;
let data = t.value;
// no trailing dot
data = data.replace(/\.$/, '');
if (data && data[0] == '0' && data[1] !== '.') {
data = data.slice(1);
}
if (data[0] == '.') {
data = '0' + data;
}
/* Force '0' on leaving field
if (data.trim() == '')
data = '0';
*/
if (data !== dataStart) {
t.value = data;
}
});
});//querySelectorAll.forEach
//});//DOMContentLoaded
}//FN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment