Вимкнути прокрутку на `<type type = number>`


121

Чи можна відключити колесо прокрутки, змінивши номер у полі вхідного номера? Я заплутався з CSS-специфічним для веб-файлів, щоб видалити спінер, але я хотів би позбутися такої поведінки. Мені подобається використовувати, type=numberоскільки вона створює приємну клавіатуру на iOS.


7
використовувати тип введення tel (type = "tel") замість типу type = число. У ньому з’явиться клавіатура iOS num.
Правен Віджаян

Що станеться, коли ви додасте onscrollобробник, що знаходиться лише event.preventDefault()в ньому?
robertc

14
На мою скромну думку, я навіть не думаю, що це має бути особливістю. Якби я мав щось сказати в розробці браузера, я б, ймовірно, намагався видалити цю функцію. Це не що інше, як дратує, і я не знаю нікого, хто би насправді цим користувався.
Кіркленд

3
Я повністю згоден з вами Кіркленд. Просто UX - це прокрутка сторінки за формою, і, коли елемент введення числа проходить під вашою мишкою, він починає збільшуватися, і сторінка перестає прокручуватися. Повністю дезорієнтує.
kjs3

3
@PraveenVijayan: Але якщо це рішення, це суперечить будь-якій причині використання нових типів введення html5. В майбутньому може бути, що телефони дадуть вам можливість вибирати номер із контактів чи чого завгодно, що буде виглядати дуже дивно, якщо ви мали на увазі це номер іншого типу.
трепет

Відповіді:


92

Запобігайте поведінці події мишоподібного колеса за замовчуванням на елементах вхідних чисел, як запропоновано іншими (виклик "blur ()", як правило, не є кращим способом цього зробити, тому що це не буде те, чого хоче користувач).

АЛЕ Я б уникав прослуховування події миші на всіх елементах вхідної кількості весь час і робити це лише тоді, коли елемент знаходиться в фокусі (саме тоді проблема існує). В іншому випадку користувач не може прокручувати сторінку, коли вказівник миші знаходиться де-небудь над елементом введення числа.

Рішення для jQuery:

// disable mousewheel on a input number field when in focus
// (to prevent Cromium browsers change the value when scrolling)
$('form').on('focus', 'input[type=number]', function (e) {
  $(this).on('wheel.disableScroll', function (e) {
    e.preventDefault()
  })
})
$('form').on('blur', 'input[type=number]', function (e) {
  $(this).off('wheel.disableScroll')
})

(Делегуйте події фокусування на навколишній елемент форми - щоб уникнути багатьох слухачів подій, які погані для продуктивності.)


2
Чудова відповідь. Я думаю, якби я робив це сьогодні, я б використав Modernizr.touch, щоб умовно застосувати слухач подій на нетипових пристроях. В основному те, що користувач2863715 сказав нижче.
kjs3

Чудова відповідь, але, принаймні, у веб-програмі, це також запобігає прокрученню вікна, поки курсор знаходиться над вхідним елементом. Я подумав, що події мишоподібного колеса теж повинні пузирити.
Райан Макгірі

Якщо застосувати функцію відключення прокрутки до елемента лише тоді, коли він знаходиться у фокусі, це не повинно запобігати прокрутці, коли миша над вхідним елементом. Але це не дозволяє прокручувати вікно, коли елемент знаходиться у фокусі. І так, чому подія
мишоподібного колеса не кипить

6
Це приємне виправлення поведінки, яка не повинна існувати в першу чергу.
Джонні

Це не працює на більшості платформ Unix типу gnome, osx, android (за допомогою миші), оскільки поведінка прокрутки не вимагає зосередження вводу. Крім того, я щойно використав тип тексту введення даних і поклав на нього обмеження чисельності (втрачаючи комбінацію клавіш вгору / вниз, але також можна додати і js)
zeachco


20

Один слухач подій, щоб керувати ними всіма

Це схоже на @Simon Перепелиця «s відповіді в чистому JS, але трохи простіше, так як вона кладе слухач подій на елементі документа і перевіряє , якщо сфокусований елемент введення номера:

document.addEventListener("wheel", function(event){
    if(document.activeElement.type === "number"){
        document.activeElement.blur();
    }
});

Якщо ви хочете вимкнути поведінку прокрутки значень у деяких полях, а не в інших, просто виконайте це:

document.addEventListener("wheel", function(event){
    if(document.activeElement.type === "number" &&
       document.activeElement.classList.contains("noscroll"))
    {
        document.activeElement.blur();
    }
});

з цим:

<input type="number" class="noscroll"/>

Якщо вхід має клас noscroll, він не буде змінюватися в прокрутці, інакше все залишається таким же.

Тестуйте тут за допомогою JSFiddle


Я бачу, що це було знято. Якщо ви бачите проблему, будь ласка, залиште коментар також із голосною заявою. Якщо я щось пропустив, я хотів би дізнатися, що це таке. Дякую.
Петро Ракманій

1
Для сучасного веб-переглядача використовуйте подію wheelзамість mousewheel. Довідка: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event PS. Я не той, хто проголосував.
vee

19
input = document.getElementById("the_number_input")
input.addEventListener("mousewheel", function(event){ this.blur() })

http://jsfiddle.net/bQbDm/2/

Для прикладу jQuery та крос-браузерного рішення див. Відповідне питання:

Слухач подій HTML5 для прокрутки введення цифр - лише Chrome


2
Спасибі Сеймон, мені вдалося це зробити для введення всіх цифр за допомогою jQuery таким чином: $(':input[type=number]' ).live('mousewheel',function(e){ $(this).blur(); });я використав розмиття замість запобігання за замовчуванням, щоб він не блокував прокрутку сторінки!
Thibaut Colson

Приємне доповнення про розмиття, я не знав, що ви можете дозволити прокручування сторінки. Я оновив свою відповідь.
Саймон Перепелиця

13
FYI, live()застаріла. Тепер вам слід скористатися on(): $(':input[type=number]').on('mousewheel',function(e){ $(this).blur(); });
Саїд Зебардаст

3
@SaeidZebardast Ваш коментар заслуговує на відповідь
лукавий

Для сучасного веб-переглядача використовуйте подію wheelзамість mousewheel. Довідка: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
vee

16

Ви можете просто використовувати атрибут HTML onwheel .

Цей параметр не впливає на прокручування інших елементів сторінки.

І додайте слухача, щоб усі входи не працювали на входах, динамічно створених заднім числом.

Додатково ви можете видалити стрілки введення за допомогою CSS.

input[type="number"]::-webkit-outer-spin-button, 
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
}
<input type="number" onwheel="this.blur()" />


1
Дякую брате !! він прекрасно працював у кутовому - Матеріал 6
Насіруддін Саїєд,


Цю CSS ми можемо знайти у багатьох джерелах. У будь-якому випадку, CSS - це лише бонус. Справжнє рішення питання - атрибут HTML onwheel. ;-)
Майкон Матей

5
Мені подобається це рішення! Дякую. У моєму випадку це onBlur()було не так, як очікувалося. Я налаштовую простуreturn false натомість дійсно "нічого не робити на колесі". <input type="number" onwheel="return false;">
Даніель

14

@Semyon Перепелиця

Для цього є краще рішення. Розмиття знімає фокус із входу, і це побічний вплив, який ви не хочете. Натомість слід використовувати evt.preventDefault. Це запобігає поведінці вводу за замовчуванням, коли користувач прокручує. Ось код:

input = document.getElementById("the_number_input")
input.addEventListener("mousewheel", function(evt){ evt.preventDefault(); })

6
Це працює, але подія не спливає, тому сторінка не прокручується. Чи є спосіб зберегти поведінку за замовчуванням (прокручування сторінки) без розмивання?
GuiGS

Для сучасного веб-переглядача використовуйте подію wheelзамість mousewheel. Довідка: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
vee

7

Спочатку ви повинні зупинити подія миші, виконавши будь-яке:

  1. Відключення за допомогою mousewheel.disableScroll
  2. Перехоплюючи це с e.preventDefault();
  3. Видаляючи фокус від елемента el.blur();

Перші два підходи обидва зупиняють прокручування вікна, а останній видаляє фокус від елемента; обидва з них є небажаними наслідками.

Одне вирішення полягає у використанні el.blur()та перефокусуванні елемента після затримки:

$('input[type=number]').on('mousewheel', function(){
  var el = $(this);
  el.blur();
  setTimeout(function(){
    el.focus();
  }, 10);
});

3
Гарне рішення, але під час тестування я виявив, що це рішення має побічну дію крадіжки фокусу. Я налаштував це на тест: тест, щоб перевірити, чи елемент має фокус: var hadFocus = el.is(':focus');перед розмиванням, а потім охоронець, щоб встановити час очікування лише у випадку, якщо hadFocs був істинним.
Роб Доусон

2

Надані відповіді не працюють у Firefox (Quantum). Слухача події потрібно змінити з колеса миші на колесо:

$(':input[type=number]').on('wheel',function(e){ $(this).blur(); });

Цей код працює на Firefox Quantum та Chrome.


2

Для всіх, хто працює з React та шукає рішення. Я з'ясував, що найпростішим способом є використання опори onWheelCapture для компонента Input, як це:

onWheelCapture={e => { e.target.blur() }}


2

Варіант написання тексту

Typescript повинен знати, що ви працюєте з HTMLElement для безпеки типу, інакше ви побачите багато Property 'type' does not exist on type 'Element'типів помилок.

document.addEventListener("mousewheel", function(event){
  let numberInput = (<HTMLInputElement>document.activeElement);
  if (numberInput.type === "number") {
    numberInput.blur();
  }
});

1

Намагаючись вирішити це для себе, я помітив, що насправді можна зберегти прокрутку сторінки та фокус введення, відключивши зміни чисел, намагаючись повторно запустити подію, що потрапила, на батьківський елемент того, <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події лише на введеннях чисел, які знаходяться у фокусі та під курсором миші (саме так позначають три вищевказані умови), негативний вплив на користувацький досвід буде близьким до жодного.


1

Якщо ви хочете рішення, яке не потребує JavaScript, комбінування деяких функціональних можливостей HTML з псевдоелементом CSS виконує завдання:

span {
  position: relative;
  display: inline-block; /* Fit around contents */
}

span::after {
  content: "";
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0; /* Stretch over containing block */
  cursor: text; /* restore I-beam cursor */
}

/* Restore context menu while editing */
input:focus {
  position: relative;
  z-index: 1;
}
<label>How many javascripts can u fit in u mouth?
  <span><input type="number" min="0" max="99" value="1"></span>
</label>

Це працює, оскільки натискання на вміст <label> , пов’язаного з полем форми, зосередить поле. Однак "вікно" псевдоелемента над полем блокує події мишового колеса від його досягнення.

Недолік полягає в тому, що кнопки віджимання вгору / вниз більше не працюють, але ви сказали, що все одно ви їх видалили.


Теоретично можна відновити контекстне меню, не вимагаючи, щоб вхід було сфокусовано спочатку: :hoverстилі не повинні запускатись, коли користувач прокручує, оскільки браузери уникають перерахунку їх під час прокрутки з міркувань продуктивності, але я не ретельно переглядав браузер / пристрій випробував це.


0
function fixNumericScrolling() {
$$( "input[type=number]" ).addEvent( "mousewheel", function(e) {
    stopAll(e);     
} );
}

function stopAll(e) {
if( typeof( e.preventDefault               ) != "undefined" ) e.preventDefault();
if( typeof( e.stopImmediatePropagation     ) != "undefined" ) e.stopImmediatePropagation();
if( typeof( event ) != "undefined" ) {
    if( typeof( event.preventDefault           ) != "undefined" ) event.preventDefault();
    if( typeof( event.stopImmediatePropagation ) != "undefined" ) event.stopImmediatePropagation();
}

return false;
}

0

Найпростішим рішенням є додавання onWheel={ event => event.currentTarget.blur() }}на сам вхід.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.