Detectar todos los cambios en un <input type="text"> (inmediatamente) usando JQuery
Hay muchas maneras en que el valor de a <input type="text">
puede cambiar, entre ellas:
- pulsaciones de teclas
- copiar pegar
- modificado con JavaScript
- autocompletado por el navegador o una barra de herramientas
- restablecer formulario
Quiero que se llame a mi función JavaScript (con el valor de entrada actual) cada vez que cambie. Y quiero que se llame de inmediato, no sólo cuando la entrada pierda el foco.
Estoy buscando la forma más limpia y sólida de hacer esto en todos los navegadores (preferiblemente usando jQuery).
Este código jQuery se utiliza .bind()
para detectar cambios inmediatos en cualquier elemento y debería funcionar en todos los navegadores:
$('.myElements').each(function() {
var elem = $(this);
// Save current value of element
elem.data('oldVal', elem.val());
// Look for changes in the value
elem.bind("propertychange change click keyup input paste", function(event){
// If value has changed...
if (elem.data('oldVal') != elem.val()) {
// Updated stored value
elem.data('oldVal', elem.val());
// Do action
....
}
});
});
Sin embargo, tenga en cuenta que .bind()
quedó obsoleto en la versión 3.0 de jQuery. Cualquiera que use jQuery versión 1.7 o posterior debería usarlo .on()
en su lugar.
Una solución en tiempo real para jQuery >= 1.7 eson
$("#input-id").on("change keyup paste", function(){
dosomething();
})
Si también desea detectar el evento "clic", simplemente:
$("#input-id").on("change keyup paste click", function(){
dosomething();
})
Si estás usando jQuery <= 1.6, simplemente usa bind
o live
en lugar de on
.
Desafortunadamente, creo que setInterval
gana el premio:
<input type=text id=input_id />
<script>
setInterval(function() { ObserveInputValue($('#input_id').val()); }, 100);
</script>
Es la solución más limpia, con solo 1 línea de código. También es el más sólido, ya que no tiene que preocuparse por todos los diferentes eventos/formas en que puede input
obtener un valor.
Las desventajas de usar 'setInterval' no parecen aplicarse en este caso:
- ¿La latencia de 100 ms? Para muchas aplicaciones, 100 ms es suficiente.
- ¿Carga agregada en el navegador? En general, agregar muchos setIntervals pesados en su página es malo. Pero en este caso particular, la carga de página agregada es indetectable.
- ¿No se escala a muchas entradas? La mayoría de las páginas no tienen más que un puñado de entradas, que puedes detectar todas en el mismo setInterval.
La vinculación al input
evento parece funcionar bien en la mayoría de los navegadores sensatos. IE9 también lo admite, pero la implementación tiene errores (el evento no se activa al eliminar caracteres).
Con jQuery versión 1.7+, el on
método es útil para vincularse al evento de esta manera:
$(".inputElement").on("input", null, null, callbackFunction);
Lamentablemente no existe ningún evento o conjunto de eventos que coincida con sus criterios. Las pulsaciones de teclas y copiar/pegar se pueden manejar con el keyup
evento. Los cambios a través de JS son más complicados. Si tiene control sobre el código que configura el cuadro de texto, lo mejor que puede hacer es modificarlo para llamar a su función directamente o activar un evento de usuario en el cuadro de texto:
// Compare the textbox's current and last value. Report a change to the console.
function watchTextbox() {
var txtInput = $('#txtInput');
var lastValue = txtInput.data('lastValue');
var currentValue = txtInput.val();
if (lastValue != currentValue) {
console.log('Value changed from ' + lastValue + ' to ' + currentValue);
txtInput.data('lastValue', currentValue);
}
}
// Record the initial value of the textbox.
$('#txtInput').data('lastValue', $('#txtInput').val());
// Bind to the keypress and user-defined set event.
$('#txtInput').bind('keypress set', null, watchTextbox);
// Example of JS code triggering the user event
$('#btnSetText').click(function (ev) {
$('#txtInput').val('abc def').trigger('set');
});
Si no tiene control sobre ese código, puede usarlo setInterval()
para "observar" el cuadro de texto en busca de cambios:
// Check the textbox every 100 milliseconds. This seems to be pretty responsive.
setInterval(watchTextbox, 100);
Este tipo de monitoreo activo no detecta actualizaciones "inmediatamente", pero parece ser lo suficientemente rápido como para que no haya un retraso perceptible. Como señaló DrLouie en los comentarios, esta solución probablemente no se adapte bien si necesita observar muchas entradas. Siempre puedes ajustar el segundo parámetro para setInterval()
comprobarlo con mayor o menor frecuencia.