Rileva tutte le modifiche a <input type = "text"> (immediatamente) usando JQuery


397

Esistono molti modi in cui il valore di a <input type="text">può cambiare, tra cui:

  • pressione dei tasti
  • copia incolla
  • modificato con JavaScript
  • completato automaticamente dal browser o da una barra degli strumenti

Voglio che la mia funzione JavaScript venga chiamata (con il valore di input corrente) ogni volta che cambia. E voglio che venga chiamato immediatamente, non solo quando l'ingresso perde la messa a fuoco.

Sto cercando il modo più pulito e robusto per farlo su tutti i browser (preferibilmente usando jQuery).



Risposte:


352

Questo codice jQuery rileva le modifiche immediate a qualsiasi elemento e dovrebbe funzionare su tutti i browser:

 $('.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
       ....
     }
   });
 });

19
Per riferimento di tutti, inputè l'evento HTML5 che credo dovrebbe coprire tutti i browser moderni ( riferimento MDN ). keyupdovrebbe prendere il resto, anche se con un leggero ritardo ( inputviene attivato a chiave giù). propertychangeè un evento proprietario MS e non sono sicuro che pastesia effettivamente necessario.
Jo Liss,

71
Sbaglio o questo non gestisce quando il testo viene modificato tramite javascript comedocument.getElementById('txtInput').value = 'some text';
Mehmet Ataş

5
Mehmet, il codice non ha lo scopo di catturare i valori modificati tramite JS.
Phatmann,

12
@ MehmetAtaş è in parte corretto. Il riferimento per l' inputevento qui afferma che non si attiva quando i contenuti vengono modificati tramite JavaScript. Tuttavia, l' onpropertychangeevento si attiva alla modifica tramite JS (vedi qui ). Quindi questo codice funzionerà quando i contenuti vengono modificati tramite JS su IE, ma non funzionerà su altri browser.
Vicky Chijwani,

2
È possibile attivare un evento personalizzato sull'input durante il cambio di proprietà, il keyup ecc. E quindi utilizzarlo ovunque.
Ivan Ivković,

122

Una soluzione di fantasia in tempo reale per jQuery> = 1.9

$("#input-id").on("change keyup paste", function(){
    dosomething();
})

se vuoi rilevare anche un evento "click", basta:

$("#input-id").on("change keyup paste click", function(){
    dosomething();
})

se stai usando jQuery <= 1.4, usa liveinvece di on.


3
Questo ha uno svantaggio. Se si lascia il campo di input con il tasto Tab, genererà un evento keyup anche se il contenuto non è stato modificato.
Pawka,

2
Come rilevare quando il datetimepicker riempie il # input-id? Nessuno degli eventi (modifica, incolla) funziona.
Pathros,

Questo è fantastico! L'ho provato con jquery 1.8.3 e funziona. Ho ancora un po 'di codice livequery () che devo sostituire, quindi non riesco ad aggiornare a 1.9.1. So che è vecchio ma lo è anche l'intero sito web.
Asle,

Cordiali saluti: Questi eventi genereranno un valore vuoto se la tastiera viene utilizzata per selezionare una data non valida. vale a dire. Febbraio 30. stackoverflow.com/questions/48564568/...
Olmstov

107

Sfortunatamente, penso che setIntervalvince il premio:

<input type=text id=input_id />
<script>
setInterval(function() { ObserveInputValue($('#input_id').val()); }, 100);
</script>

È la soluzione più pulita, con solo 1 riga di codice. È anche il più robusto, poiché non devi preoccuparti di tutti i diversi eventi / modi in cui inputpuoi ottenere un valore.

Gli svantaggi dell'utilizzo di 'setInterval' non sembrano applicarsi in questo caso:

  • La latenza di 100 ms? Per molte applicazioni, 100 ms è abbastanza veloce.
  • Aggiunto carico sul browser? In generale, l'aggiunta di un sacco di set pesanti Intervalli sulla tua pagina non è buona. Ma in questo caso particolare, il caricamento della pagina aggiunta non è rilevabile.
  • Non si adatta a molti input? La maggior parte delle pagine non ha più di una manciata di input, che puoi annusare tutti nello stesso setInterval.

21
Questo sembra essere l'unico modo per rilevare le modifiche a un campo di input in un modulo quando si utilizza il browser Nintendo 3DS (Versione / 1.7552.EU).
Johan

4
Nota: il sovraccarico può essere facilitato. Se si avvia setInterval quando l'input viene messo a fuoco e clearInterval quando l'input ha perso la messa a fuoco
Tebe

10
Perché dovresti creare un intervallo di 100 ms in esecuzione costante in cui non vi è motivo per cui sia in esecuzione costantemente? EVENTI persone. Usali.
Gavin,

15
@Gavin, in questo caso particolare JS manca di eventi .. ci trova una serie di eventi che possono riconoscere, input dell'utente, paste dell'utente, tagli dell'utente, inserimenti javascript, rimozioni javascript, completamenti automatici di moduli, moduli nascosti, nessuno visualizzato le forme.
Naramsim,

2
@Gavin JS non sembra avere un evento invariato che viene attivato OGNI TEMPO, un input viene modificato. (basta fare un document.getElementById (nome) .value = Math.random ()) per vedere nessuna delle soluzioni di trigger di eventi funziona.
Joeri,

58

Associare oninputall'evento sembra funzionare bene nella maggior parte dei browser sani di mente. Anche IE9 lo supporta, ma l'implementazione è errata (l'evento non viene generato durante l'eliminazione dei caratteri).

Con jQuery versione 1.7+ il onmetodo è utile per associare l'evento in questo modo:

$(".inputElement").on("input", null, null, callbackFunction);

12
oninputevento non funziona con input[type=reset]o modifica javascript come puoi vedere in questo test: codepen.io/yukulele/pen/xtEpb
Yukulélé

2
@Yukulélé, almeno possiamo aggirare il problema più facilmente rispetto al tentativo di rilevare tutte le possibili azioni dell'utente .
Pacerier,

30

Risposta 2017 : l' evento di input fa esattamente questo per qualcosa di più recente di IE8.

$(el).on('input', callback)

6
Ci dispiace ma ... in cosa differisce dalla risposta 2012 di HRJ sopra? Ad ogni modo, l' inputevento non riesce a rilevare le modifiche di JS.
David,

16

Sfortunatamente non esiste alcun evento o insieme di eventi che corrisponda ai tuoi criteri. Keypress e copia / incolla possono entrambi essere gestiti con l' keyupevento. Le modifiche tramite JS sono più complicate. Se hai il controllo del codice che imposta la casella di testo, la soluzione migliore è modificarla per chiamare direttamente la tua funzione o attivare un evento utente nella casella di testo:

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

Se non hai il controllo su quel codice, puoi usare setInterval()'guarda' la casella di testo per le modifiche:

// Check the textbox every 100 milliseconds.  This seems to be pretty responsive.
setInterval(watchTextbox, 100);

Questo tipo di monitoraggio attivo non rileverà gli aggiornamenti "immediatamente", ma sembra essere abbastanza veloce da non avere ritardi percettibili. Come ha sottolineato DrLouie nei commenti, questa soluzione probabilmente non si ridimensiona bene se devi guardare molti input. È sempre possibile regolare il secondo parametro su setInterval()per controllare più o meno frequentemente.


Cordiali saluti, in realtà ci sono molti eventi che possono essere combinati per corrispondere ai criteri dei PO in vari gradi tra i browser (vedere i collegamenti nel commento della prima domanda). Questa risposta non utilizza nessuno di questi eventi e, ironia della sorte, probabilmente funzionerà altrettanto bene in tutti i browser, anche se con un leggero ritardo;)
Crescent Fresh

L'OP vuole rilevare le modifiche alla casella di testo tramite JavaScript (ad es myTextBox.value = 'foo';. Nessun evento JavaScript gestisce tale situazione.
Annabelle,

1
E se qualcuno avesse 50 campi da tenere d'occhio?
DoctorLouie,

1
Sì, ho solo 1 campo nel mio caso, ma non vedo perché questo non funzioni abbastanza bene per un certo numero di campi. Probabilmente sarebbe più efficiente avere solo 1 setTimeout che controlla tutti gli input.
Dustin Boswell,

1
@Douglas: nessun evento JavaScript gestisce questa situazione - Correzione: IE può gestirla con input.onpropertychange, e FF2 +, Opera 9.5, Safari 3 e Chrome 1 possono gestirla con input.__defineSetter__('value', ...)(che, sebbene sia documentata come non funzionante sui nodi DOM, posso verificare Funziona). L'unica divergenza rispetto all'implementazione di IE è che IE spinge il gestore non solo sull'impostazione programmatica ma anche durante gli eventi chiave.
Crescent Fresh,

6

Ecco una soluzione leggermente diversa se non hai voglia di nessuna delle altre risposte:

var field_selectors = ["#a", "#b"];
setInterval(function() { 
  $.each(field_selectors, function() { 
    var input = $(this);
    var old = input.attr("data-old-value");
    var current = input.val();
    if (old !== current) { 
      if (typeof old != 'undefined') { 
        ... your code ...
      }
      input.attr("data-old-value", current);
    }   
  }   
}, 500);

Considera che non puoi fare affidamento su clic e keyup per acquisire il menu contestuale incolla.


Questa risposta ha funzionato meglio per me. Ho avuto dei problemi con i miei selettori fino a quando non ho usato: $("input[id^=Units_]").each(function() {
robr

4

Aggiungi questo codice da qualche parte, questo farà il trucco.

var originalVal = $.fn.val;
$.fn.val = function(){
    var result =originalVal.apply(this,arguments);
    if(arguments.length>0)
        $(this).change(); // OR with custom event $(this).trigger('value-changed');
    return result;
};

Questa soluzione trovata su val () non attiva change () in jQuery


3

Ho creato un campione. Possa funzionerà per te.

var typingTimer;
var doneTypingInterval = 10;
var finaldoneTypingInterval = 500;

var oldData = $("p.content").html();
$('#tyingBox').keydown(function () {
    clearTimeout(typingTimer);
    if ($('#tyingBox').val) {
        typingTimer = setTimeout(function () {
            $("p.content").html('Typing...');
        }, doneTypingInterval);
    }
});

$('#tyingBox').keyup(function () {
    clearTimeout(typingTimer);
    typingTimer = setTimeout(function () {
        $("p.content").html(oldData);
    }, finaldoneTypingInterval);
});


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>


<textarea id="tyingBox" tabindex="1" placeholder="Enter Message"></textarea>
<p class="content">Text will be replace here and after Stop typing it will get back</p>

http://jsfiddle.net/utbh575s/


3

In realtà non è necessario configurare i loop per rilevare le modifiche javaScript. Abbiamo già impostato molti listener di eventi per l'elemento che vogliamo rilevare. solo innescando qualsiasi evento non dannoso renderà il lavoro.

$("input[name='test-element']").on("propertychange change click keyup input paste blur", function(){
console.log("yeh thats worked!");
});

$("input[name='test-element']").val("test").trigger("blur");

e spesso questo è disponibile solo se hai il pieno controllo delle modifiche javascript sul tuo progetto.


2

Bene, il modo migliore è quello di coprire quelle tre basi che hai elencato da solo. Un semplice: onblur,: onkeyup, ecc. Non funzionerà per quello che vuoi, quindi basta combinarli.

KeyUp dovrebbe coprire i primi due, e se Javascript sta modificando la casella di input, spero che sia il tuo javascript, quindi aggiungi un callback nella funzione che lo modifica.


1
+1 per la soluzione semplice, anche se è possibile che OP non possa / non voglia modificare il codice apportando modifiche alla casella di testo.
Annabelle,

Enumerare tutti i possibili eventi non mi sembra robusto. Il keyup funziona se l'utente tiene premuto il tasto Canc (ovvero un tasto di ripetizione)? Che dire del completamento automatico (o delle barre degli strumenti che riempiono automaticamente i valori)? Oppure ci sono fonti di input speciali che non attivano i tasti premuti? Sarei preoccupato che ci sarebbe qualcosa del genere che ti mancherebbe.
Dustin Boswell,

1

Ecco un esempio funzionante che sto usando per implementare una variazione di completamento automatico popola un selettore jqueryui (elenco), ma non voglio che funzioni esattamente come il completamento automatico jqueryui che fa un menu a discesa.

$("#tagFilter").on("change keyup paste", function() {
     var filterText = $("#tagFilter").val();
    $("#tags").empty();
    $.getJSON("http://localhost/cgi-bin/tags.php?term=" + filterText,
        function(data) {
            var i;
            for (i = 0; i < data.length; i++) {
                var tag = data[i].value;
                $("#tags").append("<li class=\"tag\">" + tag + "</li>");
            }
        }); 
});

1

NO JQUERY! (È un po 'obsoleto in questi giorni comunque)

Modifica: ho rimosso gli eventi HTML. NON utilizzare eventi HTML ... utilizzare invece i listener di eventi Javascript.

document.querySelector("#testInput").addEventListener("input", test);

function test(e) {
 var a = document.getElementById('output');
 var b = /^[ -~]+$/;
 if (e.target.value == '' || b.test(e.target.value)) {
  a.innerText = "Text is Ascii?.. Yes";
 } else if (!b.test(e.target.value)) {
  a.innerText = "Text is Ascii?.. No";
 }
}
Try pressing Alt+NumPad2+NumPad3 in the input, it will instantly detect a change, whether you Paste, Type, or any other means, rather than waiting for you to unselect the textbox for changes to detect.

<input id="testInput">
<br>
<a id="output">Text is Ascii?.. Yes</a>


0

Non puoi semplicemente usare l' <span contenteditable="true" spellcheck="false">elemento al posto di <input type="text">?

<span>(con contenteditable="true" spellcheck="false"come attributi) si distingue <input>principalmente perché:

  • Non è in stile <input>.
  • Non ha una valueproprietà, ma il testo è reso come innerTexte fa parte del suo corpo interno.
  • È multilinea mentre <input>non lo è anche se si imposta l'attributo multiline="true".

Per ottenere l'aspetto puoi, ovviamente, modellarlo in CSS, mentre scrivendo il valore come innerTextpuoi ottenere per esso un evento:

Ecco un violino .

Sfortunatamente c'è qualcosa che in realtà non funziona in IE e Edge, che non riesco a trovare.


Penso che ci siano problemi di accessibilità riguardo all'uso di quel metodo.
Daniel Tonon,

0

Sebbene questa domanda sia stata pubblicata 10 anni fa, credo che abbia ancora bisogno di alcuni miglioramenti. Quindi ecco la mia soluzione.

$(document).on('propertychange change click keyup input paste', 'selector', function (e) {
    // Do something here
});

L'unico problema con questa soluzione è che non si innescherà se il valore cambia da javascript come $('selector').val('some value'). Puoi attivare qualsiasi evento nel tuo selettore quando cambi il valore da javascript.

$(selector).val('some value');
// fire event
$(selector).trigger('change');

-2

puoi vedere questo esempio e scegliere quali sono gli eventi che ti interessano:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<title>evetns</title>
</head>
<body>
<form>
    <input class="controlevents" id="i1" type="text" /><br />
    <input class="controlevents" id="i2" type="text" /><br />
    <input class="controlevents" id="i3" type="text" /><br />
    <input class="controlevents" id="i4" type="text" /><br />
    <input class="controlevents" id="i5" type="text" /><br />
</form>
<div id="datatext"></div>
</body>
</html>
<script>
$(function(){

function testingevent(ev){
    if (ev.currentTarget.tagName=="INPUT")
        $("#datatext").append("<div>id : " + ev.currentTarget.id + ", tag: " + ev.currentTarget.tagName + ", type: "+ ev.type +"</div>");
}   

    var eventlist = ["resizeend","rowenter","dragleave","beforepaste","dragover","beforecopy","page","beforeactivate","beforeeditfocus","controlselect","blur",
                    "beforedeactivate","keydown","dragstart","scroll","propertychange","dragenter","rowsinserted","mouseup","contextmenu","beforeupdate",
                    "readystatechange","mouseenter","resize","copy","selectstart","move","dragend","rowexit","activate","focus","focusin","mouseover","cut",
                    "mousemove","focusout","filterchange","drop","blclick","rowsdelete","keypress","losecapture","deactivate","datasetchanged","dataavailable",
                    "afterupdate","mousewheel","keyup","movestart","mouseout","moveend","cellchange","layoutcomplete","help","errorupdate","mousedown","paste",
                    "mouseleave","click","drag","resizestart","datasetcomplete","beforecut","change","error","abort","load","select"];

    var inputs = $(".controlevents");

    $.each(eventlist, function(i, el){
        inputs.bind(el, testingevent);
    });

});
</script>

4
Penso che hai dimenticato un tipo di evento :)
Dustin Boswell il

-3

Potrei essere in ritardo alla festa qui, ma non puoi semplicemente usare l'evento .change () fornito da jQuery.

Dovresti essere in grado di fare qualcosa come ...

$(#CONTROLID).change(function(){
    do your stuff here ...
});

Puoi sempre associarlo a un elenco di controlli con qualcosa come ...

var flds = $("input, textarea", window.document);

flds.live('change keyup', function() {
    do your code here ...
});

Il raccoglitore live garantisce che tutti gli elementi esistenti nella pagina adesso e in futuro vengano gestiti.


2
L'evento change si attiva solo dopo aver perso lo stato attivo, quindi non si attiva mentre un utente sta digitando nella casella, solo dopo che hanno finito e continuano a fare qualcos'altro.
Eli Sand,

2
Come molte altre risposte qui, questo non funzionerà quando il valore dell'elemento viene modificato da Javascript. Non so se manchi o meno qualsiasi altro caso di modifica richiesto dall'OP.
Mark Amery,

-4

Questo è il modo più veloce e pulito per farlo:

Sto usando Jquery ->

$('selector').on('change', function () {
    console.log(this.id+": "+ this.value);
});

Funziona abbastanza bene per me.


7
Questo è già stato suggerito. Risolve solo casi semplici, quando l'utente digita il testo.
Christophe,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.