Come rilevare il contenuto di una casella di testo è cambiato


417

Voglio rilevare ogni volta che il contenuto di una casella di testo è cambiato. Posso usare il metodo keyup, ma questo rileverà anche i tasti che non generano lettere, come i tasti freccia. Ho pensato a due metodi per farlo usando l'evento keyup:

  1. Controlla esplicitamente se il codice ASCII del tasto premuto è una lettera \ backspace \ delete
  2. Usa le chiusure per ricordare qual era il testo nella casella di testo prima del tratto del tasto e controlla se questo è cambiato.

Entrambi sembrano un po 'ingombranti.


7
Sì, catturare keyup per questo è male. Puoi incollare oggetti senza premere alcun tasto.
spender,

2
qualche possibilità che tu possa pubblicare la tua soluzione finale? Devo risolvere anche questo problema :)
Matt Dotson

1
o .keyup()evento ... maggiori informazioni qui: stackoverflow.com/questions/3003879/…
Victor S

1
Vedi $ ("# some-input"). ChangePolling () ; per un wrapper che controlla il valore corrente e si attiva .change()se è cambiato.
Joel Purra,

è necessario controllare anche questo stackoverflow.com/a/23266812/3160597
azerafati

Risposte:


714

Inizia a osservare l'evento "input" anziché "change".

jQuery('#some_text_box').on('input', function() {
    // do your stuff
});

... che è bello e pulito, ma può essere esteso ulteriormente a:

jQuery('#some_text_box').on('input propertychange paste', function() {
    // do your stuff
});

12
'live' è deprecato. quindi fare uso di 'on' stackoverflow.com/a/15111970/1724777
NavaRajan

21
L'unico inconveniente di 'input' è che non è compatibile con IE <9.
Catfish

5
l'input è un evento html5 che non è supportato in tutti i browser. developer.mozilla.org/en-US/docs/Web/API/window.oninput
commonpike

18
Puoi anche coprire più basi usando: .on ('input propertychange paste', function () {
Graeck

23
L'unico inconveniente di IE <9 è che nessuno lo usa!
sohaiby,

67

Utilizzare l'evento onchange in HTML / JavaScript standard.

In jQuery questo è l' evento change () . Per esempio:

$('element').change(function() { // do something } );

MODIFICARE

Dopo aver letto alcuni commenti, che dire di:

$(function() {
    var content = $('#myContent').val();

    $('#myContent').keyup(function() { 
        if ($('#myContent').val() != content) {
            content = $('#myContent').val();
            alert('Content has been changed');
        }
    });
});

3
Sì, questo è simile a quello che ho suggerito nell'opzione n. 2 nella mia domanda. Preferisco le chiusure poiché l'utilizzo di un globale farà funzionare questa funzione solo per una casella di testo. Ad ogni modo, sembra strano che jquery non abbia un modo più semplice di farlo.
olamundo,

1
È davvero strano, ma dubito che ci sia un modo migliore per farlo. È possibile utilizzare setInterval e quindi verificare se il contenuto è stato modificato ogni 0,1 secondi, quindi fare qualcosa. Ciò includerà anche le paste di topo e così via. Ma non sembra troppo elegante.
Waleed Amjad,

4
È ancora possibile che il contenuto possa essere modificato senza premere un tasto, ad esempio incollando con il mouse. Se ti preoccupi di questo, potresti teoricamente catturare anche eventi del mouse, ma quella configurazione è ancora più brutta. D'altra parte, se sei disposto a ignorare le modifiche guidate dal mouse, lo farà.
Adam Bellaire,

45

L'evento "change" non funziona correttamente, ma "input" è perfetto.

$('#your_textbox').bind('input', function() {
    /* This will be fired every time, when textbox's value changes. */
} );

7
Questo funziona perfettamente per la mia situazione, anche se l'uso di .onè raccomandato dall'1.7 in poi (piuttosto che .bind).
Nick,

8
OP non ha specificato la necessità di compatibilità tra browser. @schwarzkopfb ha fornito una soluzione. Nessun motivo per votare perché hai il rappresentante per farlo.
David East,

3
@David non ha nemmeno specificato quale browser
ozz

9
@ jmo21 Penso che possiamo supporre per lo sviluppo web quando un browser non è specifico, la soluzione dovrebbe essere interfunzionale. La norma supporta tutti i browser.
Chris,

3
@Chris "La norma supporta tutti i browser" - solo se sei un sadico. Non ci sono buoni motivi per evitare la bontà di HTML5 per il 2% degli utenti globali su Internet Explorer 8/9. caniuse.com/#feat=input-event
Yarin

39

Cosa ne pensi di questo:

<jQuery 1.7

$("#input").bind("propertychange change keyup paste input", function(){
    // do stuff;
});

> jQuery 1.7

$("#input").on("propertychange change keyup paste input", function(){
    // do stuff;
});

Funziona in IE8 / IE9, FF, Chrome


1
Il problema che ho con questa risposta è che si attiva una volta offuscata la casella di testo, anche se il valore non è cambiato. Il colpevole è il "cambiamento".
Giustino,

Stai usando Chrome? Sembra che sia un bug con Chrome e non con l'evento di modifica di jQuery bugs.jquery.com/ticket/9335
Catfish

funziona ma presenta un bug minore se si esegue console.logil valore del campo che registra due volte ogni volta che si digita un carattere.
Samuel M.,

21

Usa le chiusure per ricordare qual era il testo nella casella di controllo prima della pressione del tasto e controlla se questo è cambiato.

Sì. Non è necessario utilizzare le chiusure necessariamente, ma sarà necessario ricordare il vecchio valore e confrontarlo con il nuovo.

Però! Questo non accadrà ancora ogni cambiamento, perché esiste un modo per modificare il contenuto della casella di testo che non comporta la pressione di un tasto. Ad esempio, selezionando un intervallo di testo, quindi facendo clic con il pulsante destro del mouse. O trascinandolo. O trascinando il testo da un'altra app nella casella di testo. O cambiando una parola tramite il controllo ortografico del browser. O...

Quindi, se devi rilevare ogni cambiamento, devi fare il polling per questo. È possibile window.setIntervalverificare il campo con il valore precedente ogni (diciamo) secondo. Si potrebbe anche collegare onkeyupalla stessa funzione in modo che le modifiche che sono causati da pressione dei tasti si riflettono più veloce.

Ingombrante? Sì. Ma è quello o semplicemente fallo nel normale modo di scambio HTML e non provare ad aggiornare istantaneamente.


1
In questi giorni l' inputevento HTML5 è praticabile e funziona nelle versioni correnti di tutti i principali browser.
Tim Down,

13
$(document).on('input','#mytxtBox',function () { 
 console.log($('#mytxtBox').val());
});

È possibile utilizzare l'evento 'input' per rilevare la modifica del contenuto nella casella di testo. Non usare "live" per associare l'evento poiché è deprecato in Jquery-1.7, quindi usa "on".


@NavaRajan Appena testato di nuovo in IE9. non funziona davvero sul backspace.
Flores,

Non voglio usare .live, ma il problema che sto riscontrando è che in qualche modo sono tornato "indietro nel futuro" e su un progetto mvc3 in cui il team leader vuole restare "fuori dagli schemi", quindi non solo EF 4.0, ma jquery 1.5.1 viene utilizzato THUS .on () non era in 1.5.1, poiché è stato aggiunto nella versione jquery 1.7 api.jquery.com/on
Tom Stickel

5

Presumo che tu stia cercando di fare qualcosa di interattivo quando cambia la casella di testo (cioè recuperare alcuni dati tramite Ajax). Stavo cercando questa stessa funzionalità. So che usare un global non è la soluzione più robusta o elegante, ma è quello che ho scelto. Ecco un esempio:

var searchValue = $('#Search').val();
$(function () {
    setTimeout(checkSearchChanged, 0.1);
});

function checkSearchChanged() {
    var currentValue = $('#Search').val();
    if ((currentValue) && currentValue != searchValue && currentValue != '') {
        searchValue = $('#Search').val();
        $('#submit').click();
    }
    else {
        setTimeout(checkSearchChanged, 0.1);
    }
}

Una cosa fondamentale da notare qui è che sto usando setTimeout e non setInterval poiché non voglio inviare più richieste contemporaneamente. Ciò garantisce che il timer "si arresti" quando viene inviato il modulo e "si avvii" al termine della richiesta. Lo faccio chiamando checkSearchChanged al termine della mia chiamata Ajax. Ovviamente potresti espanderlo per verificare la lunghezza minima, ecc.

Nel mio caso, sto usando ASP.Net MVC in modo da poter vedere come collegarlo con MVC Ajax anche nel seguente post:

http://geekswithblogs.net/DougLampe/archive/2010/12/21/simple-interactive-search-with-jquery-and-asp.net-mvc.aspx


4

Consiglio di dare un'occhiata al widget di completamento automatico dell'interfaccia utente jQuery. Hanno gestito la maggior parte dei casi lì poiché la loro base di codice è più matura della maggior parte di quelli là fuori.

Di seguito è riportato un collegamento a una pagina demo in modo da poter verificare che funzioni. http://jqueryui.com/demos/autocomplete/#default

Otterrai il massimo beneficio leggendo la fonte e vedendo come l'hanno risolta. Puoi trovarlo qui: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js .

Fondamentalmente fanno tutto, a cui si legano input, keydown, keyup, keypress, focus and blur. Quindi hanno una gestione speciale per tutti i tipi di chiavi come page up, page down, up arrow key and down arrow key. Un timer viene utilizzato prima di ottenere il contenuto della casella di testo. Quando un utente digita una chiave che non corrisponde a un comando (tasto su, tasto giù e così via) c'è un timer che esplora il contenuto dopo circa 300 millisecondi. Sembra così nel codice:

// switch statement in the 
switch( event.keyCode ) {
            //...
            case keyCode.ENTER:
            case keyCode.NUMPAD_ENTER:
                // when menu is open and has focus
                if ( this.menu.active ) {
                    // #6055 - Opera still allows the keypress to occur
                    // which causes forms to submit
                    suppressKeyPress = true;
                    event.preventDefault();
                    this.menu.select( event );
                }
                break;
            default:
                suppressKeyPressRepeat = true;
                // search timeout should be triggered before the input value is changed
                this._searchTimeout( event );
                break;
            }
// ...
// ...
_searchTimeout: function( event ) {
    clearTimeout( this.searching );
    this.searching = this._delay(function() { // * essentially a warpper for a setTimeout call *
        // only search if the value has changed
        if ( this.term !== this._value() ) { // * _value is a wrapper to get the value *
            this.selectedItem = null;
            this.search( null, event );
        }
    }, this.options.delay );
},

Il motivo per utilizzare un timer è che l'interfaccia utente ha la possibilità di essere aggiornata. Quando Javascript è in esecuzione, l'interfaccia utente non può essere aggiornata, pertanto la chiamata alla funzione di ritardo. Questo funziona bene per altre situazioni come concentrarsi sulla casella di testo (utilizzata da quel codice).

Quindi puoi utilizzare il widget o copiare il codice nel tuo widget se non stai utilizzando l'interfaccia utente di jQuery (o nel mio caso lo sviluppo di un widget personalizzato).


2

Vorrei chiederti perché stai cercando di rilevare quando il contenuto della casella di testo è cambiato in tempo reale ?

Un'alternativa sarebbe quella di impostare un timer (tramite setIntval?) E confrontare l'ultimo valore salvato con quello attuale e quindi resettare un timer. Ciò garantirebbe di catturare QUALSIASI cambiamento, sia causato da tasti, mouse, qualche altro dispositivo di input che non hai preso in considerazione, né JavaScript che cambi il valore (un'altra possibilità che nessuno ha menzionato) da una parte diversa dell'app.


la mia situazione (che mi ha portato a questa domanda) è che devo mostrare un pulsante "Aggiorna carrello" quando la quantità in una casella di testo viene modificata. l'utente non ha idea di dover perdere la messa a fuoco e potrebbe altrimenti non vedere il pulsante.
Simon_Weaver

Siamo spiacenti, non sono sicuro che questo risponda alla domanda "perché non controllare la presenza di differenze su un programma". Basta controllare abbastanza spesso (ogni 1/4 di secondo) e l'utente non conoscerà alcuna differenza.
DVK

1

consideri l'utilizzo dell'evento change ?

$("#myTextBox").change(function() { alert("content changed"); });

5
AFAIK, viene attivato solo quando si perde il focus dell'elemento. Qualcuno che abbia familiarità con le chiusure probabilmente lo sa. :)
simon,

sì, questo non funzionerà: l'evento change viene chiamato solo quando la casella di testo perde lo stato attivo. Voglio gestire la modifica subito dopo aver premuto il tasto.
olamundo,

1

Utilizzare l' textchangeevento tramite lo shim jQuery personalizzato per la inputcompatibilità tra browser . http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html (github biforcato più di recente: https://github.com/pandell /jquery-splendid-textchange/blob/master/jquery.splendid.textchange.js )

Gestisce tutti i tag di input <textarea>content</textarea>, incluso , che non sempre funziona con change keyupecc. (!) Solo jQuery on("input propertychange")gestisce i <textarea>tag in modo coerente e quanto sopra è uno shim per tutti i browser che non comprendono l' inputevento.

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/pandell/jquery-splendid-textchange/master/jquery.splendid.textchange.js"></script>
<meta charset=utf-8 />
<title>splendid textchange test</title>

<script> // this is all you have to do. using splendid.textchange.js

$('textarea').on("textchange",function(){ 
  yourFunctionHere($(this).val());    });  

</script>
</head>
<body>
  <textarea style="height:3em;width:90%"></textarea>
</body>
</html>

Test bin JS

Questo gestisce anche incolla, elimina e non duplica lo sforzo sul keyup.

Se non si utilizza uno shim, utilizzare gli on("input propertychange")eventi jQuery .

// works with most recent browsers (use this if not using src="...splendid.textchange.js")

$('textarea').on("input propertychange",function(){ 
  yourFunctionHere($(this).val());    
});  

0

C'è un esempio di lavoro completo qui .

<html>
<title>jQuery Summing</title>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> </script>
$(document).ready(function() {
$('.calc').on('input', function() {
var t1 = document.getElementById('txt1');
var t2 = document.getElementById('txt2');
var tot=0;
if (parseInt(t1.value))
tot += parseInt(t1.value);
if (parseInt(t2.value))
tot += parseInt(t2.value);
document.getElementById('txt3').value = tot;
});
});
</script>
</head>
<body>
<input type='text' class='calc' id='txt1'>
<input type='text' class='calc' id='txt2'>
<input type='text' id='txt3' readonly>
</body>
</html>

0

Qualcosa del genere dovrebbe funzionare, principalmente perché focuse focusoutfinirebbe con due valori separati. Sto usando dataqui perché memorizza i valori nell'elemento ma non tocca il DOM. È anche un modo semplice per memorizzare il valore connesso al suo elemento. È possibile utilizzare altrettanto facilmente una variabile con ambito superiore.

var changed = false;

$('textbox').on('focus', function(e) {
    $(this).data('current-val', $(this).text();
});

$('textbox').on('focusout', function(e) {
    if ($(this).data('current-val') != $(this).text())
        changed = true;
    }
    console.log('Changed Result', changed);
}

0

Questo codice rileva ogni volta che il contenuto di una casella di testo viene modificato dall'utente e modificato dal codice Javascript.

var $myText = jQuery("#textbox");

$myText.data("value", $myText.val());

setInterval(function() {
    var data = $myText.data("value"),
    val = $myText.val();

    if (data !== val) {
        console.log("changed");
        $myText.data("value", val);
    }
}, 100);
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.