Próbując rozwiązać ten problem samodzielnie, zauważyłem, że w rzeczywistości można zachować przewijanie strony i fokus danych wejściowych, wyłączając zmiany liczbowe, próbując ponownie uruchomić przechwycone zdarzenie na elemencie nadrzędnym, <input type="number"/>
na którym zostało przechwycone , po prostu w ten sposób:
e.target.parentElement.dispatchEvent(e);
Jednak powoduje to błąd w konsoli przeglądarki i prawdopodobnie nie ma gwarancji, że będzie działać wszędzie (testowałem tylko w przeglądarce Firefox), ponieważ jest to celowo nieprawidłowy kod.
Innym rozwiązaniem, które działa ładnie przynajmniej na Firefoksie i Chromium, jest tymczasowe utworzenie <input>
elementu w readOnly
ten sposób:
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); });
Jednym z efektów ubocznych, który zauważyłem, jest to, że może powodować migotanie pola na ułamek sekundy, jeśli masz inny styl readOnly
pól, ale przynajmniej w moim przypadku nie wydaje się to stanowić problemu.
Podobnie (jak wyjaśniono w odpowiedzi Jamesa) zamiast modyfikować readOnly
właściwość, można blur()
pole, a następnie focus()
przywrócić, ale znowu, w zależności od używanych stylów, może wystąpić migotanie.
Alternatywnie, jak wspomniano w innych komentarzach, możesz po prostu zadzwonić preventDefault()
na wydarzenie. Zakładając, że obsługujesz wheel
zdarzenia tylko na danych wejściowych liczbowych, które są w centrum uwagi i pod kursorem myszy (to właśnie oznaczają trzy powyższe warunki), negatywny wpływ na wrażenia użytkownika byłby bliski zeru.