我有一个keydown
事件,我对输入做了一些更改,并直接在代码中更改了值。要使其工作,我需要使用preventDefault()
,否则我单击的类型最终会在输入中重复。我发现了一个与此问题类似的案例,我使用了建议的相同解决方案,它工作了:
preventdefault-in-a-keydown-event-onchange-event-not-trigger
$('.test').on('change', function(event) {
console.log('## run change')
});
const symbolDecimal = '.';
const ignorables = [8, 9, 37, 38, 39, 40, 46, 109, 189];
$(".test").on('keydown', function(event) {
const oldValue = event.target.value;
// debugger;
// Caso for alguma tecla alfabética sem estar segurando a tecla Control, ignora o comando
const key = event.key;
const $input = $(event.target);
// Inibi alguns eventos especiais
if (event.ctrlKey || (event.ctrlKey && (key.toLowerCase() === 'v' || key.toLowerCase() === 'a' )) ) {
return;
}
// Captura precisão do input
const precisao = 0;
// Monta a regex para a máscara
const mask = new RegExp("(\\-)?(\\d+)(\\d{"+precisao+"})$", 'g');
// Captura posição inicial e final do cursos no input
const start = $input.prop('selectionStart');
const end = $input.prop('selectionEnd');
// Distribui os caracteres do input em um buffer
let arr = $input.val().split('');
// Verifica se existe precisão e monta o retorno conforme é montado a regex
let masked = '$1$2';
if (precisao > 0)
masked = '$1$2.$3';
// Inicia o valor
let value = $input.val();
// Verifica se o número é negativo
if (event.keyCode === 8 || event.keyCode === 46) {
// Se for Backspace e o curso estiver na posição 0 do input só retornar
if (event.keyCode === 8 && start === 0 && end === 0) return;
// Calcula a diferença entre a área selecionada no Input
let diff = start === end ? 1 : end - start;
// Se não for área selecionada
// Se for Backspace, posiciona a remoção a um caractere anterior da posição do cursor
// Se for Delete, posiciona a remoção a um caractere posterior da posição do cursos
let initStart = start === 0 ? 0 : start - 1;
if (event.keyCode === 46) initStart = start;
// Verifica se o caracter a ser removido simbolo decimal
if (arr[initStart] === symbolDecimal) {
initStart -= 1;
}
// Remove o(s) caracter(s) na posição que o selector está ou os valores selecionados
arr.splice(initStart, diff);
value = arr.join('');
// Aplica a máscara no valor
$input.val(value.replace(mask, masked));
// Mantém o cursor na posição em que estava quando disparou evento de remoção
$input[0].setSelectionRange(initStart, initStart);
} else if (!isNaN(parseInt(key))) {
// Adiciona novo número ao buffer
arr.push(key);
value = arr.join('');
value = value.replace(mask, masked);
// Aplica a máscara no valor
$input.val(value);
}
// THIS PREVENTDEFAULT
event.preventDefault();
// THE SOLUTION
if (event.target.valueOnFocus === undefined) {
event.target.valueOnFocus = oldValue;
$(event.target).on('focus', function(event) {
event.target.valueOnFocus = event.target.value;
});
$(event.target).on('blur', function(event) {
if (event.target.value !== event.target.valueOnFocus)
$(event.target).trigger('change');
});
}
});
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
<input id="test" name="test" class="test">
example
如果注解掉THE SOLUTION所在的部分,onchange
事件将停止工作;如果注解掉THE SOLUTION上方的preventDefault()
,onchange
事件将工作,但按下的类型在输入中出现重复。
我的问题与这篇文章中提出的代码类似,但它已经很旧了,我还没有找到任何人有更好的解决方案或似乎是正确的。
我的问题是,为什么onchange
事件被取消了?为什么,如果你不使用preventDefault()
,这个值在输入中插入了两次?我只测试了onblur
事件,它工作了,但是它不适合我需要做的事情。
1条答案
按热度按时间nsc4cvqm1#
我有同样的问题,唯一的决定,我发现是创建这样的函数:
只是
preventDefault
不起作用,我不知道为什么...