Detectar todos los cambios en un <input type="text"> (inmediatamente) usando JQuery

Resuelto Dustin Boswell asked hace 15 años • 16 respuestas

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).

Dustin Boswell avatar Dec 23 '09 01:12 Dustin Boswell
Aceptado

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.

phatmann avatar May 21 '2010 21:05 phatmann

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 bindo liveen lugar de on.

Felix avatar Mar 19 '2013 04:03 Felix

Desafortunadamente, creo que setIntervalgana 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 inputobtener 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.
Dustin Boswell avatar Dec 22 '2009 21:12 Dustin Boswell

La vinculación al inputevento 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 onmétodo es útil para vincularse al evento de esta manera:

$(".inputElement").on("input", null, null, callbackFunction);
HRJ avatar Mar 28 '2012 05:03 HRJ

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 keyupevento. 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.

Annabelle avatar Dec 22 '2009 19:12 Annabelle