L'événement onchange sur le type d'entrée = la plage ne déclenche pas dans Firefox lorsque vous traînez

Lorsque j'ai joué avec <input type="range"> , Firefox déclenche un événement onchange uniquement si nous déposons le curseur sur une nouvelle position où Chrome et autres déclenche les événements onchange pendant que le curseur est traîné.

Comment puis-je faire en sorte de faire glisser dans Firefox?

HTML

 <span id="valBox"></span> <input type="range" min="5" max="10" step="1" onchange="showVal(this.value)"> 

SCÉNARIO

 function showVal(newVal){ document.getElementById("valBox").innerHTML=newVal; } 

Apparemment, Chrome et Safari sont faux: onchange ne devrait être déclenché que lorsque l'utilisateur relâche la souris. Pour obtenir des mises à jour continues, vous devez utiliser l'événement oninput , qui capture des mises à jour en direct sur Firefox, Safari et Chrome, tant de la souris que du clavier.

Cependant, oninput n'est pas pris en charge dans IE10, donc votre meilleur pari est de combiner les deux gestionnaires d'événements, comme ceci:

 <span id="valBox"></span> <input type="range" min="5" max="10" step="1" oninput="showVal(this.value)" onchange="showVal(this.value)"> 

Découvrez ce thread Bugzilla pour plus d'informations.

MISE À JOUR: Je laisse cette réponse ici comme un exemple de la façon d'utiliser les événements de souris pour utiliser les interactions de la gamme / curseur dans les navigateurs de bureau (mais pas mobiles). Cependant, j'ai maintenant écrit une réponse complètement différente et, je crois, mieux sur cette page qui utilise une approche différente pour fournir une solution de bureau et mobile multi-navigateur à ce problème.

Réponse originale:

Résumé: Une solution de navigateur croisé, simple JavaScript (c'est-à-dire sans jQuery) pour permettre la lecture des valeurs de saisie de la plage sans utiliser on('input'... et / ou on('change'... qui fonctionne de manière incompatible entre les navigateurs.

À compter d'aujourd'hui (fin février 2016), il y a toujours une incohérence dans le navigateur, donc je propose un nouveau travail ici.

Le problème: lors de l'utilisation d'une entrée de gamme, c'est-à-dire d'un curseur, on('input'... fournit des valeurs de portée mises à jour en permanence dans Mac, Windows Firefox, Chrome et Opera, ainsi que Mac Safari, en cours on('change'... Relève uniquement la valeur de la plage lors de la souris. En revanche, dans Internet Explorer (v11), on('input'... ne fonctionne pas du tout, et on('change'... est continuellement mis à jour.

Je rapporte ici 2 stratégies pour obtenir des rapports de valeur de gamme continue identiques dans tous les navigateurs en utilisant le logiciel vanilla JavaScript (c.-à-d. JQuery) en utilisant les événements mousem, mousemove et (éventuellement) mouseup.

Stratégie 1: plus courte mais moins efficace

Si vous préférez un code plus court sur un code plus efficace, vous pouvez utiliser cette 1ère solution qui utilise mousesdown et mousemove mais pas mouseup. Cela permet de lire le curseur au besoin, mais continue de déclencher inutilement pendant les événements de souris, même lorsque l'utilisateur n'a pas cliqué et ne traîne donc pas le curseur. Il lit essentiellement la valeur de la gamme à la fois après 'mousedown' et pendant les événements 'mousemove', retardant légèrement chacun en utilisant la requestAnimationFrame .

 var rng = document.querySelector("input"); read("mousedown"); read("mousemove"); function read(evtType) { rng.addEventListener(evtType, function() { window.requestAnimationFrame(function () { document.querySelector("div").innerHTML = rng.value; }); }); } 
 <div>50</div><input type="range"/> 

Je publie ceci comme une réponse parce qu'il mérite d'être sa propre réponse plutôt qu'un commentaire sous une réponse moins utile. Je trouve cette méthode beaucoup mieux que la réponse acceptée, car elle peut conserver tous les js dans un fichier distinct du HTML.

Réponse fournie par Jamrelian dans son commentaire sous la réponse acceptée.

 $("#myelement").on("input change", function() { //do something }); 

Soyez conscient de ce commentaire de Jaime cependant

Il suffit de noter qu'avec cette solution, en chrome, vous recevrez deux appels au gestionnaire (un par événement), donc, si vous vous occupez de cela, vous devez vous protéger contre cela.

Comme cela, il déclenchera l'événement lorsque vous avez arrêté de déplacer la souris, puis, lorsque vous relâchez le bouton de la souris.

RÉSUMÉ:

Je fournis ici une capacité de bureau et mobile sans joker pour répondre de façon constante aux interactions de la gamme / slider, ce qui n'est pas possible dans les navigateurs actuels. Il oblige essentiellement tous les navigateurs à imiter les événements IE11 on("change"... pour leur activation on("change"... ou on("input"... événements. La nouvelle fonction est …

 function onRangeChange(r,f) { var n,c,m; r.addEventListener("input",function(e){n=1;c=e.target.value;if(c!=m)f(e);m=c;}); r.addEventListener("change",function(e){if(!n)f(e);}); } 

… où r est votre élément d'entrée de plage et f est votre auditeur. L'auditeur sera appelé après toute interaction qui modifie la valeur de la gamme / diapositive mais pas après les interactions qui ne changent pas cette valeur, y compris les interactions initiales de la souris ou du toucher à la position actuelle du curseur ou lors du déplacement de l'extrémité du curseur.

Problème:

À partir du début de juin 2016, différents navigateurs diffèrent en fonction de la façon dont ils répondent à l'utilisation de la gamme / slider. Cinq scénarios sont pertinents:

  1. Initiale vers le bas (ou touche-démarrage) à la position du curseur actuel
  2. Initiale vers le bas (ou touche-démarrage) sur une nouvelle position du curseur
  3. Tout mouvement ultérieur de la souris (ou touche) après 1 ou 2 le long du curseur
  4. Tout mouvement ultérieur de la souris (ou touche) après 1 ou 2 après l'extrémité du curseur
  5. Dernier mouse-up (ou touche-fin)

Le tableau suivant montre comment au moins trois navigateurs de bureau différents diffèrent dans leur comportement par rapport à lequel des scénarios ci-dessus auxquels ils répondent:

Tableau montrant les différences de navigateur par rapport aux événements auxquels ils répondent et quand

Solution:

La fonction onRangeChange offre une réponse cohérente et prévisible du navigateur croisé aux interactions gamme / slider. Cela oblige tous les navigateurs à se comporter selon le tableau suivant:

Tableau montrant le comportement de tous les navigateurs en utilisant la solution proposée

Dans IE11, le code permet essentiellement à tout fonctionner selon le statu quo, c'est-à-dire qu'il permet à l'événement "change" de fonctionner de manière standard et l'événement "input" n'est pas pertinent puisqu'il ne se déclenche jamais. Dans d'autres navigateurs, l'événement "change" est effectivement réduit au silence (pour éviter que des événements supplémentaires et parfois non facilement évidents soient déclenchés). De plus, l'événement "input" déclenche son auditeur uniquement lorsque la valeur de la gamme / du curseur change. Pour certains navigateurs (p. Ex. Firefox), cela se produit car l'auditeur est effectivement réduit au silence dans les scénarios 1, 4 et 5 de la liste ci-dessus.

(Si vous avez vraiment besoin d'un auditeur pour être activé dans les scénarios 1, 4 et / ou 5, vous pouvez essayer d'intégrer les "mousedown" / "touchstart" , "mousemove" / "touchmove" et / "mouseup" / "touchend" . Une telle solution dépasse le cadre de cette réponse.)

Fonctionnalité dans les navigateurs mobiles:

J'ai testé ce code dans les navigateurs de bureau, mais pas dans les navigateurs mobiles. Cependant, dans une autre réponse sur cette page MBourne a montré que ma solution ici "… semble fonctionner dans tous les navigateurs que je pourrais trouver (Win bureau: IE, Chrome, Opera, FF, Android Chrome, Opera et FF, iOS Safari) " . (Merci MBourne.)

Usage:

Pour utiliser cette solution, incluez la fonction onRangeChange partir du résumé ci-dessus (simplifié / minifié) ou l'extrait du code de démonstration ci-dessous (fonctionnellement identique mais plus explicite) dans votre propre code. Appelez-le comme suit:

 onRangeChange(myRangeInputElmt, myListener); 

myRangeInputElmt est l' myRangeInputElmt désiré <input type="range"> et myListener est la fonction d'écoute / gestionnaire que vous voulez invoquer lors des événements "change" .

Votre auditeur peut être sans paramètre si vous le souhaitez ou peut utiliser le paramètre de l' event , c'est-à-dire que l'un des éléments suivants fonctionnerait selon vos besoins:

 var myListener = function() {... 

ou

 var myListener = function(evt) {... 

(En supprimant l'écouteur d'événement de l'élément de input (par exemple, using removeEventListener ) n'est pas abordé dans cette réponse.)

Description de la démonstration:

Dans l'extrait de code ci-dessous, la fonction onRangeChange fournit la solution universelle. Le reste du code est simplement un exemple pour démontrer son utilisation. Toute variable qui commence par my... n'est pas pertinente pour la solution universelle et n'est présente que pour la démo.

La démonstration montre la valeur de la plage / glissement ainsi que le nombre de fois que les événements "change" , "input" et "onRangeChange" personnalisés ont été déclenchés (lignes A, B et C respectivement). Lorsque vous exécutez cet extrait dans différents navigateurs, notez ce qui suit lorsque vous interagissez avec la gamme / curseur:

  • Dans IE11, les valeurs dans les lignes A et C changent toutes deux dans les scénarios 2 et 3 ci-dessus tandis que la ligne B ne change jamais.
  • Dans Chrome et Safari, les valeurs dans les lignes B et C changent toutes deux dans les scénarios 2 et 3 alors que la ligne A ne change que pour le scénario 5.
  • Dans Firefox, la valeur de la ligne A ne change que pour le scénario 5, les changements de ligne B pour les cinq scénarios et la ligne C ne change que pour les scénarios 2 et 3.
  • Dans tous les navigateurs ci-dessus, les changements dans la ligne C (la solution proposée) sont identiques, c'est-à-dire uniquement pour les scénarios 2 et 3.

Code de démo:

 // main function for emulating IE11's "change" event: function onRangeChange(rangeInputElmt, listener) { var inputEvtHasNeverFired = true; var rangeValue = {current: undefined, mostRecent: undefined}; rangeInputElmt.addEventListener("input", function(evt) { inputEvtHasNeverFired = false; rangeValue.current = evt.target.value; if (rangeValue.current !== rangeValue.mostRecent) { listener(evt); } rangeValue.mostRecent = rangeValue.current; }); rangeInputElmt.addEventListener("change", function(evt) { if (inputEvtHasNeverFired) { listener(evt); } }); } // example usage: var myRangeInputElmt = document.querySelector("input" ); var myRangeValPar = document.querySelector("#rangeValPar" ); var myNumChgEvtsCell = document.querySelector("#numChgEvtsCell"); var myNumInpEvtsCell = document.querySelector("#numInpEvtsCell"); var myNumCusEvtsCell = document.querySelector("#numCusEvtsCell"); var myNumEvts = {input: 0, change: 0, custom: 0}; var myUpdate = function() { myNumChgEvtsCell.innerHTML = myNumEvts["change"]; myNumInpEvtsCell.innerHTML = myNumEvts["input" ]; myNumCusEvtsCell.innerHTML = myNumEvts["custom"]; }; ["input", "change"].forEach(function(myEvtType) { myRangeInputElmt.addEventListener(myEvtType, function() { myNumEvts[myEvtType] += 1; myUpdate(); }); }); var myListener = function(myEvt) { myNumEvts["custom"] += 1; myRangeValPar.innerHTML = "range value: " + myEvt.target.value; myUpdate(); }; onRangeChange(myRangeInputElmt, myListener); 
 table { border-collapse: collapse; } th, td { text-align: left; border: solid black 1px; padding: 5px 15px; } 
 <input type="range"/> <p id="rangeValPar">range value: 50</p> <table> <tr><th>row</th><th>event type </th><th>number of events </th><tr> <tr><td>A</td><td>standard "change" events </td><td id="numChgEvtsCell">0</td></tr> <tr><td>B</td><td>standard "input" events </td><td id="numInpEvtsCell">0</td></tr> <tr><td>C</td><td>new custom "onRangeChange" events</td><td id="numCusEvtsCell">0</td></tr> </table> 

Les solutions d'Andrew Willem ne sont pas compatibles avec les appareils mobiles.

Voici une modification de sa deuxième solution qui fonctionne dans Edge, IE, Opera, FF, Chrome, iOS Safari et équivalents mobiles (que je pourrais tester):

Mise à jour 1: Suppression de la demande "demandeAnimationFrame", car je suis d'accord, cela n'est pas nécessaire:

 var listener = function() { // do whatever }; slider1.addEventListener("input", function() { listener(); slider1.addEventListener("change", listener); }); slider1.addEventListener("change", function() { listener(); slider1.removeEventListener("input", listener); }); 

Mise à jour 2: Réponse à la réponse mise à jour de Andrew 2ème juin 2016:

Merci, Andrew, qui semble fonctionner dans tous les navigateurs que je pourrais trouver (Win desktop: IE, Chrome, Opera, FF, Android Chrome, Opera et FF, iOS Safari).

Mise à jour 3: si (solution "oninput in slider")

Les éléments suivants apparaissent dans tous les navigateurs ci-dessus. (Je ne peux pas trouver la source originale maintenant.) J'utilisais cela, mais il échoua par la suite sur IE et je suis donc allé chercher un autre, d'où j'ai fini ici.

 if ("oninput" in slider1) { slider1.addEventListener("input", function () { // do whatever; }, false); } 

Mais avant de vérifier votre solution, j'ai remarqué que cela fonctionnait à nouveau dans IE – peut-être qu'il y avait un autre conflit.

Pour un bon comportement entre les navigateurs, un code moins compréhensible, il est préférable d'utiliser l'attribut onchange en combinaison avec un formulaire:

Il s'agit d'une solution html / javascript uniquement, et peuvent également être utilisés en ligne.

 function showVal(){ document.getElementById("valBox").innerHTML=document.getElementById("inVal").value; } 
 <form onchange="showVal()"> <input type="range" min="5" max="10" step="1" id="inVal"> </form> <span id="valBox"> </span> 

Vous pouvez utiliser l'événement "ondrag" de Javascript pour tirer en continu. C'est mieux que "input" en raison des raisons suivantes,

  1. Support du navigateur
  2. Pourrait différencier l'événement "ondrag" et "changement". Feux "entrée" pour le glisser et le changement.

Dans Jquery:

  $ ('# Sample'). On ('drag', function (e) {

 }); 

Ref: http://www.w3schools.com/TAgs/ev_ondrag.asp