quitar - javascript onchange input value
el evento onchange on input type=range no se está activando en Firefox mientras se arrastra (7)
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.
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.
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:
Soporte del navegador.
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
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 B.</li>
<li>To see the importance of ''requestAnimationFrame'' on ''mousedown'', click a new location on the slider and compare C (incorrect) and D (correct).</li>
<li>To see the importance of ''requestAnimationFrame'' on ''mousemove'', click and drag but do not release the slider, and compare E (often 1 pixel behind) and F (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 (incorrect), F (incorrect) and H (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 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 I.</li>
</ol>
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:
- inicial del mouse hacia abajo (o toque-inicio) en la posición actual del control deslizante
- inicial del mouse hacia abajo (o toque-inicio) en una nueva posición del control deslizante
- cualquier movimiento posterior del mouse (o táctil) después de 1 o 2 a lo largo del deslizador
- cualquier movimiento posterior del mouse (o táctil) después de 1 o 2 más allá de cada extremo del control deslizante
- 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