La gestion de la molette de la souris NumberInput ignore le filtrage des événements de phase de capture
P粉318928159
P粉318928159 2024-04-05 12:21:04
0
1
1569

Version très courte :

Je suis un peu coincé et je ne comprends pas très bien pourquoi ce code intercepte et empêche effectivement les événements de la molette de la souris d'être interprétés par l'éditeur de nombres pour modifier les nombres. Je veux comprendre pourquoi les événements de capture d'interception et de filtrage ne fonctionnent pas :

Code HTML :

<p id="p-number-1">
  <input id="number-1" type="number" min="0" max="100" value="50" class="number-input">
</p>
<p id="log">
</p>

Code JavaScript :

function log(m) {
  const logp = document.getElementById("log")
  logp.innerHTML += "" + m + "<br>";
}

log("Logging started")

const pnum1 = document.getElementById("p-number-1")
const num1 = document.getElementById("number-1")

pnum1.addEventListener("wheel", function(e) { 
    log("captured outer");
    e.stopPropagation();
}, true);

num1.addEventListener("wheel", function(e) { 
    log("bubble inner");
}, false);

num1.addEventListener("wheel", function(e) { 
    log("capture inner");
}, true);

function log(m) {
  const logp = document.getElementById("log")
  logp.innerHTML += "" + m + "<br>";
}

log("Logging started")

const pnum1 = document.getElementById("p-number-1")
const num1 = document.getElementById("number-1")

pnum1.addEventListener("wheel", function(e) { 
    log("captured outer");
    e.stopPropagation();
}, true);

num1.addEventListener("wheel", function(e) { 
    log("bubble inner");
}, false);

num1.addEventListener("wheel", function(e) { 
    log("capture inner");
}, true);

Instructions : Cliquez sur le numéro saisi pour le focaliser, puis utilisez la molette de la souris. La molette de la souris est interceptée par le code JavaScript, mais même si j'arrête la propagation sur les

environnants pendant la phase de capture, les chiffres changent quand même.

Pour votre commodité : https://jsfiddle.net/Ljku4gha/6/

Qu’est-ce que je veux réaliser ?

Je souhaite écrire un composant réutilisable en utilisant le champ de saisie numérique par défaut (et le curseur en fait). Je ne veux pas que l'utilisateur puisse utiliser la molette de défilement sur ces entrées pour modifier les chiffres. Au lieu de cela, la molette de la souris devrait déclencher des événements sur certains div (inconnus !) (très probablement) autour d'elle à des fins de défilement. Je souhaite donc empêcher l'éditeur de nombres (et le curseur) de gérer les événements de la molette de la souris d'une manière ou d'une autre.

Version longue : mes analyses/hypothèses

Je ne peux pas complètement l'expliquer, mais il y a deux hypothèses sur ce qui se passe.

Ma première pensée, et ce qui me semble le plus probable, est qu'il s'agit d'un artefact de la façon dont les navigateurs gèrent les événements utilisateur (mot clé "agent utilisateur" je pense). Cependant, si quelqu'un pouvait m'indiquer où je peux lire comment les navigateurs gèrent les événements utilisateur, ce serait le bienvenu. En attendant, ma compréhension de la gestion des événements dans les navigateurs est la suivante :

  • L'utilisateur fait défiler la molette de la souris
  • C'est au tour de JavaScript de gérer l'événement
    • JavaScript effectue une opération de capture/bulle
    • Les gestionnaires d'événements peuvent marquer les événements comme gérés (preventDefault())
  • En dehors de JavaScript : Si le gestionnaire d'événements en JavaScript n'appelle pas PreventDefault(), "l'agent utilisateur" prendra à son tour la gestion de l'événement. Puisqu’il n’existe aucun contrôle précis à ce sujet, cette étape ne peut être que complètement arrêtée ou poursuivie. Étant donné que la « gestion par défaut » de l'édition des nombres modifie la valeur du nombre, le nombre change et aucun événement de défilement n'est émis.

Résultat : *sad me*

Cependant, je pense que cette théorie est la plus logique, mais peut-être est-elle complètement fausse ? !

Explication alternative ennuyeuse : est-ce que j'écoute le mauvais événement ?

Peut-être qu'il me manque quelque chose et que les événements de la roue sont convertis en d'autres événements sur lesquels je peux bloquer Default() ? Je ne trouve aucune information à ce sujet, mais cela me semble parfaitement logique... peut-être ? Ce n'est même pas un "reel", c'est tout ce que je peux dire.


J'aimerais surtout avoir des conseils pour m'aider à comprendre pourquoi ce que je fais ne fonctionne pas... et j'apprécierais également des solutions !

P粉318928159
P粉318928159

répondre à tous(1)
P粉262073176

Utilisez event.preventDefault() pour empêcher le comportement par défaut de la saisie des nombres.

Nous avons 2 améliorations :

  • Empêchez la molette de défilement uniquement lorsque la saisie est ciblée (lorsque la molette change de valeur). De cette façon, lorsque l'entrée n'est pas focalisée, la molette de défilement se comportera normalement
  • Lorsque l'entrée est focalisée, empêche la valeur par défaut et brouille l'entrée afin que le défilement des événements de la roue suivante fonctionne à nouveau (vous devez décider si vous souhaitez cet ajustement).

Vous ne pouvez pas résoudre ce problème en capturant parce que

Malheureusement, lorsque vous capturez, le comportement par défaut se produit avant que l'événement n'atteigne l'entrée

Par conséquent stopPropagation() n'est pas utile pendant la phase de capture.

const p = document.getElementById("p-number-1")
const num1 = document.getElementById("number-1")



num1.addEventListener("wheel", function(e) { 
    console.log("input wheel");
    if(e.target.matches(':focus')){
      console.log("input wheel prevented");
      e.preventDefault();
      e.target.blur();
    }
}, false);
p{
  height:1000px;
}
input{
  pointer-events: none1;
}

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal