Намагаючись вирішити це для себе, я помітив, що насправді можна зберегти прокрутку сторінки та фокус введення, відключивши зміни чисел, намагаючись повторно запустити подію, що потрапила, на батьківський елемент того, <input type="number"/>
на який він потрапив. , просто так:
e.target.parentElement.dispatchEvent(e);
Однак це спричиняє помилку в консолі браузера і, ймовірно, не гарантовано працювати всюди (я тестувався лише на Firefox), оскільки це навмисно недійсний код.
Ще одне рішення, яке приємно працює принаймні на Firefox та Chromium, це тимчасово зробити <input>
елемент readOnly
, як це:
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); });
Один із побічних ефектів, який я помітив, - це те, що це може спричинити мерехтіння поля на частку секунди, якщо ви маєте різні стилі для readOnly
полів, але, принаймні, у моєму випадку це не є проблемою.
Аналогічно, (як пояснено у відповіді Джеймса) замість зміни readOnly
властивості, ви можете blur()
ввести поле і потімfocus()
повернути його назад, але знову, залежно від стилів, що використовуються, може виникнути деяке мерехтіння.
Крім того, як згадується в інших коментарях тут, ви можете просто зателефонувати preventDefault()
на подію. Якщо припустити, що ви обробляєте wheel
події лише на введеннях чисел, які знаходяться у фокусі та під курсором миші (саме так позначають три вищевказані умови), негативний вплив на користувацький досвід буде близьким до жодного.