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




foco quitar (7)

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

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

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.


ACTUALIZACIÓN: Estoy dejando esta respuesta aquí como un ejemplo de cómo usar los eventos del mouse para usar las interacciones de rango / control deslizante en los navegadores de escritorio (pero no móviles). Sin embargo, ahora también he escrito una respuesta completamente diferente y, en mi opinión, mejor en otra parte de esta página que utiliza un enfoque diferente para proporcionar una solución de escritorio y dispositivo móvil para este problema.

Respuesta original:

Resumen: una solución de JavaScript simple (es decir, sin jQuery) para permitir la lectura de valores de entrada de rango sin usar on('input'... y / o on('change'... que funcionan de manera inconsistente entre navegadores.

A partir de hoy (finales de febrero de 2016), todavía hay una inconsistencia en el navegador, así que estoy proporcionando una nueva forma de trabajo aquí.

El problema: cuando se usa una entrada de rango, es decir, un control deslizante, activado on('input'... proporciona valores de rango actualizados continuamente en Mac y Windows Firefox, Chrome y Opera, así como Mac Safari, mientras está on('change'... solo reporta el valor de rango en el mouse-up. Por el contrario, en Internet Explorer (v11), on('input'... no funciona en absoluto, y on('change'... se actualiza continuamente.

Aquí informo 2 estrategias para obtener un informe de valor de rango continuo idéntico en todos los navegadores que usan JavaScript de vainilla (es decir, no jQuery) mediante el uso de los eventos mousedown, mousemove y (posiblemente) mouseup.

Estrategia 1: más corta pero menos eficiente.

Si prefiere un código más corto en lugar de un código más eficiente, puede usar esta primera solución que usa mousesdown y mousemove pero no mouseup. Esto lee el control deslizante según sea necesario, pero continúa disparándose innecesariamente durante cualquier evento de mouse-over, incluso cuando el usuario no ha hecho clic y, por lo tanto, no está arrastrando el control deslizante. Básicamente, lee el valor de rango después de los eventos 'mousedown' y durante 'mousemove', retrasando ligeramente cada uno utilizando requestAnimationFrame .

var rng = document.querySelector("input");

read("mousedown");
read("mousemove");
read("keydown"); // include this to also allow keyboard control

function read(evtType) {
  rng.addEventListener(evtType, function() {
    window.requestAnimationFrame(function () {
      document.querySelector("div").innerHTML = rng.value;
      rng.setAttribute("aria-valuenow", rng.value); // include for accessibility
    });
  });
}
<div>50</div><input type="range"/>

Estrategia 2: más larga pero más eficiente.

Si necesita un código más eficiente y puede tolerar una longitud de código más larga, entonces puede usar la siguiente solución que usa mousedown, mousemove y mouseup. Esto también lee el control deslizante según sea necesario, pero deja de leerlo tan pronto como se suelta el botón del mouse. La diferencia esencial es que solo comienza a escuchar 'mousemove' después de 'mousedown', y deja de escuchar 'mousemove' después de 'mouseup'.

var rng = document.querySelector("input");

var listener = function() {
  window.requestAnimationFrame(function() {
    document.querySelector("div").innerHTML = rng.value;
  });
};

rng.addEventListener("mousedown", function() {
  listener();
  rng.addEventListener("mousemove", listener);
});
rng.addEventListener("mouseup", function() {
  rng.removeEventListener("mousemove", listener);
});

// include the following line to maintain accessibility
// by allowing the listener to also be fired for
// appropriate keyboard events
rng.addEventListener("keydown", listener);
<div>50</div><input type="range"/>

Demostración: explicación más completa de la necesidad y la implementación de las soluciones provisionales anteriores

El siguiente código demuestra más detalladamente numerosos aspectos de esta estrategia. Las explicaciones están integradas en la demostración:

var select, inp, listen, unlisten, anim, show, onInp, onChg, onDn1, onDn2, onMv1, onMv2, onUp, onMvCombo1, onDnCombo1, onUpCombo2, onMvCombo2, onDnCombo2;

select   = function(selctr)     { return document.querySelector(selctr);      };
inp = select("input");
listen   = function(evtTyp, cb) { return inp.   addEventListener(evtTyp, cb); };
unlisten = function(evtTyp, cb) { return inp.removeEventListener(evtTyp, cb); };
anim     = function(cb)         { return window.requestAnimationFrame(cb);    };
show = function(id) {
	return function() {
    select("#" + id + " td~td~td"   ).innerHTML = inp.value;
    select("#" + id + " td~td~td~td").innerHTML = (Math.random() * 1e20).toString(36); // random text
  };
};

onInp      =                  show("inp" )                                      ;
onChg      =                  show("chg" )                                      ;
onDn1      =                  show("mdn1")                                      ;
onDn2      = function() {anim(show("mdn2"));                                   };
onMv1      =                  show("mmv1")                                      ;
onMv2      = function() {anim(show("mmv2"));                                   };
onUp       =                  show("mup" )                                      ;
onMvCombo1 = function() {anim(show("cmb1"));                                   };
onDnCombo1 = function() {anim(show("cmb1"));   listen("mousemove", onMvCombo1);};
onUpCombo2 = function() {                    unlisten("mousemove", onMvCombo2);};
onMvCombo2 = function() {anim(show("cmb2"));                                   };
onDnCombo2 = function() {anim(show("cmb2"));   listen("mousemove", onMvCombo2);};

listen("input"    , onInp     );
listen("change"   , onChg     );
listen("mousedown", onDn1     );
listen("mousedown", onDn2     );
listen("mousemove", onMv1     );
listen("mousemove", onMv2     );
listen("mouseup"  , onUp      );
listen("mousedown", onDnCombo1);
listen("mousedown", onDnCombo2);
listen("mouseup"  , onUpCombo2);
table {border-collapse: collapse; font: 10pt Courier;}
th, td {border: solid black 1px; padding: 0 0.5em;}
input {margin: 2em;}
li {padding-bottom: 1em;}
<p>Click on 'Full page' to see the demonstration properly.</p>
<table>
  <tr><th></th><th>event</th><th>range value</th><th>random update indicator</th></tr>
  <tr id="inp" ><td>A</td><td>input                                </td><td>100</td><td>-</td></tr>
  <tr id="chg" ><td>B</td><td>change                               </td><td>100</td><td>-</td></tr>
  <tr id="mdn1"><td>C</td><td>mousedown                            </td><td>100</td><td>-</td></tr>
  <tr id="mdn2"><td>D</td><td>mousedown using requestAnimationFrame</td><td>100</td><td>-</td></tr>
  <tr id="mmv1"><td>E</td><td>mousemove                            </td><td>100</td><td>-</td></tr>
  <tr id="mmv2"><td>F</td><td>mousemove using requestAnimationFrame</td><td>100</td><td>-</td></tr>
  <tr id="mup" ><td>G</td><td>mouseup                              </td><td>100</td><td>-</td></tr>
  <tr id="cmb1"><td>H</td><td>mousedown/move combo                 </td><td>100</td><td>-</td></tr>
  <tr id="cmb2"><td>I</td><td>mousedown/move/up combo              </td><td>100</td><td>-</td></tr>
</table>
<input type="range" min="100" max="999" value="100"/>
<ol>
  <li>The 'range value' column shows the value of the 'value' attribute of the range-type input, i.e. the slider. The 'random update indicator' column shows random text as an indicator of whether events are being actively fired and handled.</li>
  <li>To see browser differences between input and change event implementations, use the slider in different browsers and compare A and&nbsp;B.</li>
  <li>To see the importance of 'requestAnimationFrame' on 'mousedown', click a new location on the slider and compare C&nbsp;(incorrect) and D&nbsp;(correct).</li>
  <li>To see the importance of 'requestAnimationFrame' on 'mousemove', click and drag but do not release the slider, and compare E&nbsp;(often 1&nbsp;pixel behind) and F&nbsp;(correct).</li>
  <li>To see why an initial mousedown is required (i.e. to see why mousemove alone is insufficient), click and hold but do not drag the slider and compare E&nbsp;(incorrect), F&nbsp;(incorrect) and H&nbsp;(correct).</li>
  <li>To see how the mouse event combinations can provide a work-around for continuous update of a range-type input, use the slider in any manner and note whichever of A or B continuously updates the range value in your current browser. Then, while still using the slider, note that H and I provide the same continuously updated range value readings as A or B.</li>
  <li>To see how the mouseup event reduces unnecessary calculations in the work-around, use the slider in any manner and compare H and&nbsp;I. They both provide correct range value readings. However, then ensure the mouse is released (i.e. not clicked) and move it over the slider without clicking and notice the ongoing updates in the third table column for H but not&nbsp;I.</li>
</ol>


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>


Las soluciones de Andrew Willem no son compatibles con dispositivos móviles.

Aquí hay una modificación de su segunda solución que funciona en Edge, IE, Opera, FF, Chrome, iOS Safari y equivalentes móviles (que podría probar):

Actualización 1: Se eliminó la parte "requestAnimationFrame", ya que estoy de acuerdo en que no es necesario:

var listener = function() {
  // do whatever
};

slider1.addEventListener("input", function() {
  listener();
  slider1.addEventListener("change", listener);
});
slider1.addEventListener("change", function() {
  listener();
  slider1.removeEventListener("input", listener);
}); 

Actualización 2: Respuesta a la respuesta actualizada de Andrew's 2nd Jun 2016:

Gracias, Andrew, que parece funcionar en todos los navegadores que pude encontrar (escritorio de Win: IE, Chrome, Opera, FF; Android Chrome, Opera y FF, iOS Safari).

Actualización 3: solución if ("oninput in slider)

Lo siguiente parece funcionar en todos los navegadores anteriores. (No puedo encontrar la fuente original ahora). Estaba usando esto, pero luego falló en IE y fui a buscar una diferente, por lo que terminé aquí.

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

Pero antes de comprobar su solución, noté que esto estaba funcionando nuevamente en IE, tal vez hubo algún otro conflicto.


Aquí hay una buena manera de abordarlo. Si desea mezclar las directivas de escritura de jQuery con Angular .. en AngularJS y en la sección de enlaces de esas directivas puede incluir jQuery para la manipulación de DOM.

Tenga en cuenta que AngularJS usa jQuery lite, por lo que gran parte de lo que hace jQuery ya está integrado en Angular.

Por ejemplo, puede usar jQuery lite en un ángulo como este en cualquier lugar de una aplicación angular:

angular.element('.class').append('<p>foo</p>');

y dentro de una función de enlace directivo,

angular.module('TestModule')
.directive('jqueryTestDirective', ['$timeout', function($timeout) {
    return {
      restrict: 'E',
      link : function (scope, element) {
        $timeout(function(){  
           element.append('<p>foo</p>');
        });
      }
}]);

<jquery-test-directive></jquery-test-directive>






javascript html5 firefox input onchange