Это немного похоже на CertainPerformance ответ , но сохраняет позицию каретки и не переходит к концу ввода
Править
Добавлена визуальная обратная связь
;(() => {
const inp = document.querySelector('#inp');
const nospaces = function(elem) {
// find spaces at start of input
const spacesReg = /^\s+/;
let match
if (match = elem.value.match(spacesReg)) {
// save current caret position
const pos = elem.selectionStart;
const len = match[0].length;
elem.value = elem.value.replace(spacesReg, '');
// reset caret position
elem.selectionStart = elem.selectionEnd = Math.min(0, pos - len)
return true
}
return false
}
const onlyAllowedCharacters = function(elem) {
// search for not allowed characters
const allowed = "A-Za-z0-9-,.;'&/.() ";
const notAllowedReg = new RegExp(`(.*?)[^${allowed}]`);
// prevent infinite loop
var max = 255;
let match;
let blink = false
// replace one not allowed character per loop run
while ((max > 0) && (match = elem.value.match(notAllowedReg))) {
blink = true
const pos = elem.selectionStart;
const len = match[1].length
elem.value = elem.value.replace(notAllowedReg, '$1');
elem.selectionStart = elem.selectionEnd = pos - 1
max--
}
return blink;
}
const blink = function(elem, duration = 200) {
const to = setTimeout(() => {
elem.classList.remove('blink')
}, duration)
elem.classList.add('blink')
}
// use function literal to get correct `this` value
inp.addEventListener('input', function(e) {
const nosp = nospaces(this);
const only = onlyAllowedCharacters(this);
if (nosp || only) {
blink(this)
}
})
})();
.blink {
background: red;
}
No spaces at start of input<br>
Only allowed characters a–zA–Z0–9-,.;'&\.()<br>
<input type="text" id="inp">