web-dev-qa-db-fra.com

Désactiver le défilement sur `<type d'entrée = numéro>`

Est-il possible de désactiver la molette de défilement en modifiant le numéro dans un champ de numéro? ?__. J'ai modifié le CSS spécifique au webkit pour supprimer le spinner, mais j'aimerais supprimer ce problème. J'aime utiliser type=number car il fait apparaître un beau clavier sur iOS. 

89
kjs3

Empêchez le comportement par défaut de l'événement mousewheel sur les éléments avec un nombre d'entrée comme suggéré par d'autres (appeler "blur ()" ne serait normalement pas la méthode préférée, car ce ne serait pas ce que l'utilisateur voudrait).

MAIS. J'éviterais d'écouter l'événement mousewheel sur tous les éléments avec un nombre d'entrée tout le temps et ne le ferais que lorsque l'élément est actif (c'est le cas lorsque le problème existe). Sinon l'utilisateur ne peut pas faire défiler la page lorsque le pointeur de la souris se trouve n'importe où sur un élément avec un numéro d'entrée. 

Solution pour 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('mousewheel.disableScroll', function (e) {
    e.preventDefault()
  })
})
$('form').on('blur', 'input[type=number]', function (e) {
  $(this).off('mousewheel.disableScroll')
})

(Déléguer des événements de focus à l'élément de formulaire environnant - pour éviter à de nombreux écouteurs d'événements, qui sont mauvais pour la performance.)

70
Grantzau
$(document).on("wheel", "input[type=number]", function (e) {
    $(this).blur();
});
19
stovroz
input = document.getElementById("the_number_input")
input.addEventListener("mousewheel", function(event){ this.blur() })

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

Pour un exemple jQuery et une solution multi-navigateur, voir la question connexe:

Écouteur d'événements HTML5 pour le défilement des chiffres - Chrome uniquement

17
Simon Perepelitsa

Un écouteur d'événement pour les gouverner tous

Ceci est similaire à la réponse de @Semyon Perepelitsa en js pur, mais un peu plus simple, car elle met un écouteur d'événement sur l'élément de document et vérifie si l'élément ciblé est une entrée numérique:

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

Si vous souhaitez désactiver le comportement de défilement de valeur sur certains champs, mais pas d'autres , procédez comme suit:

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

avec ça:

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

Si une entrée a la classe noscroll, elle ne changera pas au défilement, sinon tout reste identique.

12
Peter Rakmanyi

@Semyon Perepelitsa

Il y a une meilleure solution pour cela. Flou supprime la focalisation de l'entrée et constitue un effet secondaire que vous ne souhaitez pas. Vous devez plutôt utiliser evt.preventDefault. Cela empêche le comportement par défaut de l'entrée lorsque l'utilisateur fait défiler. Voici le code:

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

Tout d'abord, vous devez arrêter l'événement mousewheel en:

  1. Désactiver avec mousewheel.disableScroll
  2. L'intercepter avec e.preventDefault();
  3. En supprimant le focus de l'élément el.blur();

Les deux premières approches empêchent le défilement de la fenêtre et la dernière supprime le focus de l'élément; les deux sont des résultats indésirables.

Une solution de contournement consiste à utiliser el.blur() et à recentrer l'élément après un délai:

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

Les réponses fournies ne fonctionnent pas dans Firefox (Quantum). L'auditeur d'événement doit être changé de molette en molette:

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

Ce code fonctionne sur Firefox Quantum et Chrome.

2
Mathias Bank

Pour tous ceux qui travaillent avec React et qui cherchent une solution. J'ai découvert que le moyen le plus simple est d'utiliser onWheelCapture prop dans le composant Input comme ceci:

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

2
Aleš Chromec
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
syb

En essayant de résoudre ce problème 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 modifications de numéro en tentant de relancer l'événement intercepté sur l'élément parent du <input type="number"/> sur lequel il a été pris, 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 qu’il fonctionnera partout (j’ai seulement testé sur Firefox), car c’est un code intentionnellement non valide.

Une autre solution qui fonctionne bien au moins sur Firefox et Chromium consiste à rendre temporairement l'élément <input>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); });

L’un des effets secondaires que j’ai remarqué est que le champ peut scintiller pendant une fraction de seconde si vous avez un style différent pour les champs readOnly, mais dans mon cas du moins, cela ne semble pas être un problème. problème.

De même, (comme expliqué dans la réponse de James) au lieu de modifier la propriété readOnly, vous pouvez blur() le champ puis focus() le revenir, mais encore une fois, en fonction des styles utilisés, un scintillement pourrait se produire.

Alternativement, comme mentionné dans d'autres commentaires ici, vous pouvez simplement appeler preventDefault() sur l'événement. En supposant que vous ne gériez que les événements wheel sur les entrées numériques qui sont en surbrillance et placées 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 presque nul.

0
Rimas Kudelis