javascript - valor - el evento onchange on input type=range no se está activando en Firefox mientras se arrastra




text change javascript (5)

Al parecer, Chrome y Safari están equivocados: onchange solo debe activarse cuando el usuario suelta el mouse. Para obtener actualizaciones continuas, debe usar el evento oninput , que capturará actualizaciones en vivo en Firefox, Safari y Chrome, tanto desde el mouse como desde el teclado.

Sin embargo, oninput no es compatible con IE10, por lo que su mejor oninput es combinar los dos controladores de eventos, como este:

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

Echa un vistazo a este hilo de Bugzilla para más información.

Cuando jugué con <input type="range"> , Firefox activa un evento onchange solo si colocamos el control deslizante en una nueva posición en la que Chrome y otros activan eventos onchange mientras se arrastra el control deslizante.

¿Cómo puedo hacer que suceda al arrastrar en Firefox?

HTML

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

GUIÓN

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

Estoy publicando esto como una respuesta porque merece ser su propia respuesta en lugar de un comentario con una respuesta menos útil. Considero que este método es mucho mejor que la respuesta aceptada, ya que puede mantener todos los js en un archivo separado del HTML.

Respuesta proporcionada por Jamrelian en su comentario bajo la respuesta aceptada.

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

Pero ten en cuenta este comentario de Jaime.

Solo tenga en cuenta que con esta solución, en Chrome, recibirá dos llamadas al controlador (una por evento), por lo que si le importa eso, entonces debe protegerse de ello.

Como se activará, se activará el evento cuando haya dejado de mover el mouse y luego nuevamente cuando suelte el botón del mouse.


Para un buen comportamiento en varios navegadores, un código menos comprensible, lo mejor es usar el atributo onchange en combinación de un formulario:

Esta es una solución solo para html / javascript y también se puede utilizar en línea.

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>


Puedes usar el evento "ondrag" de JavaScript para disparar continuamente. Es mejor que "entrada" debido a las siguientes razones:

  1. Soporte del navegador.

  2. Podría diferenciar entre evento "ondrag" y "cambio". "entrada" se activa tanto para arrastrar como para cambiar.

En jQuery:

$('#sample').on('drag',function(e){

});

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


RESUMEN:

Proporciono aquí una capacidad de escritorio y dispositivo móvil sin jQuery para responder de manera consistente a las interacciones de rango / control deslizante, algo que no es posible en los navegadores actuales. Básicamente, obliga a todos los navegadores a emular IE11's on("change"... event para su on("change"... u on("input"... events. La nueva función es ...

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

... donde r es su elemento de entrada de rango f es su oyente. Se llamará al oyente después de cualquier interacción que cambie el valor del rango / control deslizante, pero no después de las interacciones que no cambian ese valor, incluidas las interacciones iniciales con el mouse o el toque en la posición actual del control deslizante o al mover cualquiera de los extremos del control deslizante.

Problema:

A principios de junio de 2016, los diferentes navegadores difieren en cuanto a cómo responden al uso del rango / control deslizante. Cinco escenarios son relevantes:

  1. inicial del mouse hacia abajo (o toque-inicio) en la posición actual del control deslizante
  2. inicial del mouse hacia abajo (o toque-inicio) en una nueva posición del control deslizante
  3. cualquier movimiento posterior del mouse (o táctil) después de 1 o 2 a lo largo del deslizador
  4. cualquier movimiento posterior del mouse (o táctil) después de 1 o 2 más allá de cada extremo del control deslizante
  5. mouse-up final (o touch-end)

La siguiente tabla muestra cómo al menos tres navegadores de escritorio diferentes difieren en su comportamiento con respecto a cuál de los escenarios anteriores responden:

Solución:

La función onRangeChange proporciona una respuesta coherente y predecible entre navegadores para interacciones de rango / control deslizante. Obliga a todos los navegadores a comportarse de acuerdo con la siguiente tabla:

En IE11, el código esencialmente permite que todo funcione según el status quo, es decir, permite que el evento de "change" funcione de manera estándar y el evento de "input" es irrelevante ya que nunca se dispara. En otros navegadores, el evento de "change" se silencia efectivamente (para evitar que se activen eventos adicionales y, a veces, no aparentemente fáciles). Además, el evento "input" dispara a su oyente solo cuando cambia el valor del rango / control deslizante. Para algunos navegadores (por ejemplo, Firefox), esto ocurre porque el oyente se silencia efectivamente en los escenarios 1, 4 y 5 de la lista anterior.

(Si realmente requiere que se active un oyente en los escenarios 1, 4 y / o 5, puede intentar incorporar los "mousedown" / "touchstart" , "mousemove" / "touchmove" y / o "mouseup" / "touchend" . Tal solución está más allá del alcance de esta respuesta.)

Funcionalidad en los navegadores móviles:

He probado este código en navegadores de escritorio, pero no en ningún navegador móvil. Sin embargo, en otra respuesta en esta página, MBourne ha demostrado que mi solución aquí "... parece funcionar en todos los navegadores que puedo encontrar (escritorio de Win: IE, Chrome, Opera, FF; Android Chrome, Opera y FF, iOS Safari) " . (Gracias MBourne.)

Uso:

Para utilizar esta solución, incluya la función onRangeChange del resumen anterior (simplificado / reducido) o el fragmento de código de demostración a continuación (funcionalmente idéntico pero más explicativo) en su propio código. Invocarlo de la siguiente manera:

onRangeChange(myRangeInputElmt, myListener);

donde myRangeInputElmt es su elemento <input type="range"> myListener y myListener es la función de escucha / controlador que desea invocar en eventos similares a "change" .

Su oyente puede no tener parámetros si lo desea o puede usar el parámetro de event , es decir, cualquiera de los siguientes funcionaría, según sus necesidades:

var myListener = function() {...

o

var myListener = function(evt) {...

(La eliminación de la escucha de eventos del elemento de input (por ejemplo, utilizando removeEventListener ) no se aborda en esta respuesta).

Descripción de la demostración:

En el fragmento de código a continuación, la función onRangeChange proporciona la solución universal. El resto del código es simplemente un ejemplo para demostrar su uso. Cualquier variable que comience con my... es irrelevante para la solución universal y solo está presente por el bien de la demostración.

La demostración muestra el valor del rango / control deslizante, así como el número de veces que se han "onRangeChange" eventos estándar "change" , "input" y personalizado "onRangeChange" (filas A, B y C, respectivamente). Al ejecutar este fragmento de código en diferentes navegadores, tenga en cuenta lo siguiente a medida que interactúa con el rango / control deslizante:

  • En IE11, los valores en las filas A y C cambian en los escenarios 2 y 3 anteriores, mientras que la fila B nunca cambia.
  • En Chrome y Safari, los valores en las filas B y C cambian en los escenarios 2 y 3, mientras que la fila A cambia solo para el escenario 5.
  • En Firefox, el valor en la fila A cambia solo para el escenario 5, la fila B cambia para los cinco escenarios y la fila C cambia solo para los escenarios 2 y 3.
  • En todos los navegadores anteriores, los cambios en la fila C (la solución propuesta) son idénticos, es decir, solo para los escenarios 2 y 3.

Código de demostración:

// 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>

Crédito:

Si bien la implementación aquí es en gran parte mía, se inspiró en la respuesta de MBourne . Esa otra respuesta sugirió que los eventos de "entrada" y "cambio" podrían combinarse y que el código resultante funcionaría en los navegadores de escritorio y móviles. Sin embargo, el código en esa respuesta da como resultado que se activen eventos "extra" ocultos, lo que en sí mismo es problemático, y los eventos activados difieren entre los navegadores, otro problema. Mi implementación aquí resuelve esos problemas.

Palabras clave:

JavaScript tipo de entrada rango control deslizante eventos de entrada navegador compatible navegador de escritorio móvil no-jQuery





onchange