En essayant de résoudre cela par moi-même, j'ai remarqué qu'il était en fait possible de conserver le défilement de la page et le focus de l'entrée tout en désactivant les changements de nombre en tentant de relancer l'événement capturé sur l'élément parent de l'élément <input type="number"/>
sur lequel il a été capturé , simplement comme ceci:
e.target.parentElement.dispatchEvent(e);
Cependant, cela provoque une erreur dans la console du navigateur, et il n'est probablement pas garanti de fonctionner partout (je n'ai testé que sur Firefox), car il s'agit d'un code intentionnellement invalide.
Une autre solution qui fonctionne bien au moins sur Firefox et Chromium est de créer temporairement l' <input>
élément readOnly
, comme ceci:
function handleScroll(e) {
if (e.target.tagName.toLowerCase() === 'input'
&& (e.target.type === 'number')
&& (e.target === document.activeElement)
&& !e.target.readOnly
) {
e.target.readOnly = true;
setTimeout(function(el){ el.readOnly = false; }, 0, e.target);
}
}
document.addEventListener('wheel', function(e){ handleScroll(e); });
Un effet secondaire que j'ai remarqué est que cela peut faire scintiller le champ pendant une fraction de seconde si vous avez un style différent pour les readOnly
champs, mais pour mon cas au moins, cela ne semble pas être un problème.
De même, (comme expliqué dans la réponse de James) au lieu de modifier la readOnly
propriété, vous pouvez blur()
le champ, puis focus()
le retourner, mais encore une fois, selon les styles utilisés, un scintillement peut se produire.
Alternativement, comme mentionné dans d'autres commentaires ici, vous pouvez simplement appeler preventDefault()
l'événement à la place. En supposant que vous gérez uniquement les wheel
événements sur les entrées numériques qui sont au point et sous le curseur de la souris (c'est ce que signifient les trois conditions ci-dessus), l'impact négatif sur l'expérience utilisateur serait proche de zéro.