Disable scrolling on `<input type=number>`

混江龙づ霸主 提交于 2019-11-26 22:32:51

问题


Is it possible to disable the scroll wheel changing the number in an input number field? I've messed with webkit-specific CSS to remove the spinner but I'd like to get rid of this behavior altogether. I like using type=number since it brings up a nice keyboard on iOS.


回答1:


Prevent the default behavior of the mousewheel event on input-number elements like suggested by others (calling "blur()" would normally not be the preferred way to do it, because that wouldn't be, what the user wants).

BUT. I would avoid listening for the mousewheel event on all input-number elements all the time and only do it, when the element is in focus (that's when the problem exists). Otherwise the user cannot scroll the page when the mouse pointer is anywhere over a input-number element.

Solution for 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')
})

(Delegate focus events to the surrounding form element - to avoid to many event listeners, which are bad for performance.)




回答2:


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



回答3:


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

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

For jQuery example and a cross-browser solution see related question:

HTML5 event listener for number input scroll - Chrome only




回答4:


@Semyon Perepelitsa

There is a better solution for this. Blur removes the focus from the input and that is a side affect that you do not want. You should use evt.preventDefault instead. This prevents the default behavior of the input when the user scrolls. Here is the code:

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



回答5:


One event listener to rule them all

This is similar to @Semyon Perepelitsa's answer in pure js, but a bit simpler, as it puts one event listener on the document element and check if the focused element is a number input:

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

If you want to turn off the value scrolling behaviour on some fields, but not others just do this instead:

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

with this:

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

If an input has the noscroll class it wont change on scroll, otherwise everything stays the same.




回答6:


You can simply use the HTML onwheel attribute.

This option have no effects on scrolling over other elements of the page.

And add a listener for all inputs don't work in inputs dynamically created posteriorly.

Aditionaly, you can remove the input arrows with 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()" />



回答7:


First you must stop the mousewheel event by either:

  1. Disabling it with mousewheel.disableScroll
  2. Intercepting it with e.preventDefault();
  3. By removing focus from the element el.blur();

The first two approaches both stop the window from scrolling and the last removes focus from the element; both of which are undesirable outcomes.

One workaround is to use el.blur() and refocus the element after a delay:

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



回答8:


The provided answers do not work in Firefox (Quantum). The event listener needs to be changed from mousewheel to wheel:

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

This code works on Firefox Quantum and Chrome.




回答9:


For anyone working with React and looking for solution. I’ve found out that easiest way is to use onWheelCapture prop in Input component like this:

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




回答10:


While trying to solve this for myself, I noticed that it's actually possible to retain the scrolling of the page and focus of the input while disabling number changes by attempting to re-fire the caught event on the parent element of the <input type="number"/> on which it was caught, simply like this:

e.target.parentElement.dispatchEvent(e);

However, this causes an error in browser console, and is probably not guaranteed to work everywhere (I only tested on Firefox), since it is intentionally invalid code.

Another solution which works nicely at least on Firefox and Chromium is to temporarily make the <input> element readOnly, like this:

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); });

One side effect that I've noticed is that it may cause the field to flicker for a split-second if you have different styling for readOnly fields, but for my case at least, this doesn't seem to be an issue.

Similarly, (as explained in James' answer) instead of modifying the readOnly property, you can blur() the field and then focus() it back, but again, depending on styles in use, some flickering might occur.

Alternatively, as mentioned in other comments here, you can just call preventDefault() on the event instead. Assuming that you only handle wheel events on number inputs which are in focus and under the mouse cursor (that's what the three conditions above signify), negative impact on user experience would be close to none.




回答11:


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;
}



回答12:


Typescript Variation

Typescript needs to know that you're working with an HTMLElement for type safety, else you'll see lots of Property 'type' does not exist on type 'Element' type of errors.

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



回答13:


If you want a solution that doesn’t need JavaScript, combining some HTML functionality with a CSS pseudo-element does the trick:

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>

This works because clicking on the contents of a <label> that’s associated with a form field will focus the field. However, the “windowpane” of the pseudo-element over the field will block mousewheel events from reaching it.

The drawback is that the up/down spinner buttons no longer work, but you said you had removed those anyway.


In theory, one could restore the context menu without requiring the input to be focused first: :hover styles shouldn’t fire when the user scrolls, since browsers avoid recalculating them during scrolling for performance reasons, but I haven’t thoroughly cross-browser/device tested it.



来源:https://stackoverflow.com/questions/9712295/disable-scrolling-on-input-type-number

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!