Come ottenere il testo di una casella di testo di input durante onKeyPress?


87

Sto cercando di ottenere il testo in una casella di testo mentre l'utente lo digita ( jsfiddle playground ):

function edValueKeyPress() {
    var edValue = document.getElementById("edValue");
    var s = edValue.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: " + s;

    //var s = $("#edValue").val();
    //$("#lblValue").text(s);    
}
<input id="edValue" type="text" onKeyPress="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>

Il codice viene eseguito senza errori, tranne che il valore della input textcasella, durante onKeyPressè sempre il valore prima della modifica:

inserisci qui la descrizione dell'immagine

Domanda : come ottengo il testo di una casella di testo durante onKeyPress?

Bonus Chatter

Ci sono tre eventi relativi a "l'utente sta digitando" nel DOM HTML:

  • onKeyDown
  • onKeyPress
  • onKeyUp

In Windows , l'ordine dei WM_Keymessaggi diventa importante quando l'utente tiene premuto un tasto e il tasto inizia a ripetersi:

  • WM_KEYDOWN('a')- l'utente ha premuto il Atasto
  • WM_CHAR('a')- un acarattere è stato ricevuto dall'utente
  • WM_CHAR('a')- un acarattere è stato ricevuto dall'utente
  • WM_CHAR('a')- un acarattere è stato ricevuto dall'utente
  • WM_CHAR('a')- un acarattere è stato ricevuto dall'utente
  • WM_CHAR('a')- un acarattere è stato ricevuto dall'utente
  • WM_KEYUP('a')- l'utente ha rilasciato la Achiave

Risulterà in cinque caratteri visualizzati in un controllo di testo: aaaaa

Il punto importante è che tu risponda al WM_CHARmessaggio, quello che si ripete. Altrimenti perdi eventi quando viene premuto un tasto.

In HTML le cose sono leggermente diverse:

  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyUp

Html offre una KeyDowne KeyPressogni ripetizione dei tasti. E l' KeyUpevento viene generato solo quando l'utente rilascia la chiave.

Asporto

  • Io posso rispondere onKeyDownoonKeyPress , ma entrambi sono ancora sollevato prima che il input.valueè stato aggiornato
  • Non posso rispondere onKeyUp, perché non succede quando il testo nella casella di testo cambia.

Domanda: come ottengo il testo di una casella di testo duranteonKeyPress ?

Lettura bonus


1
Credo che sia necessario aggiungere la pressione del tasto corrente al valore prima di restituirlo; il valore viene aggiornato su keyUp, ma i dati sono disponibili su keyDown.
Mathletics

Key up funziona per me, non hai bisogno di jQ ​​per qualcosa di simile, a meno che tu non voglia aggiungere bloat
Ryan B

è sufficiente solo onKeyUp per il tuo compito
dmytro

La gestione di @mit Only onKeyUpnon mostra le modifiche nella casella di testo mentre si verificano.
Ian Boyd

se vuoi tenere premuto un tasto qualsiasi e ottenere il risultato nella casella di testo, dovresti usare entrambi gli eventi onKeyPress e onKeyDown Il violino di Jonathan M , ma se vuoi ottenere risultati senza tenere premuti i tasti è sufficiente solo su KeyUp il mio violino .
dmytro

Risposte:


20

Gestione della inputmanifestazione è una soluzione coerente: è supportato per textareae inputgli elementi in tutti i browser moderni e spara esattamente quando ne avete bisogno:

function edValueKeyPress() {
    var edValue = document.getElementById("edValue");
    var s = edValue.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: " + s;
}
<input id="edValue" type="text" onInput="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>

Lo riscriverei un po ', però:

function showCurrentValue(event)
{
    const value = event.target.value;
    document.getElementById("lblValue").innerText = value;
}
<input id="edValue" type="text" onInput="showCurrentValue(event)"><br>
The text box contains: <span id="lblValue"></span>


54

Sii semplice. Usa sia onKeyPress()e onKeyUp():

<input id="edValue" type="text" onKeyPress="edValueKeyPress()" onKeyUp="edValueKeyPress()">

Questo si occupa di ottenere il valore di stringa più aggiornato (dopo la chiave su) e si aggiorna anche se l'utente tiene premuto un tasto.

jsfiddle: http://jsfiddle.net/VDd6C/8/


Poiché la risposta di arnaud576875 ha dovuto rinunciare e ripiegare su onKeyUp(sconfiggendo lo scopo dell'uso onKeypress), questa è la risposta più semplice, pulita e vicina che chiunque vedrà. Solo l'utente più attento noterà che il feedback non corrisponde a ciò che ha inserito.
Ian Boyd

@Ian, felice di aiutarti. Cosa intendi con "il feedback non corrisponde a quello che hai inserito"? È necessaria una regolazione?
Jonathan M

ricordo cosa intendevo adesso! Il feedback a cui mi riferisco sarebbe colorare l' <input>elemento in rosso o verde, o dare un altro feedback all'utente che ciò che ha digitato è buono o cattivo. Anche se la tua risposta accettata soffre ancora del problema di essere sempre un personaggio "off-by-one" : solo l'utente più attento noterà che il feedback non corrisponde a quello che ha inserito. " In realtà, dal momento che il off-by- un errore si verifica solo durante la ripetizione del tasto (cioè stanno tenendo premuto il tasto) nessuno (a parte me) noterà il problema.
Ian Boyd

19

il valore della casella di testo di input, durante onKeyPress è sempre il valore prima della modifica

Questo è apposta: consente al listener di eventi di annullare la pressione del tasto.

Se i listener di eventi annullano l'evento , il valore non viene aggiornato. Se l'evento non viene annullato, il valore viene aggiornato, ma dopo che è stato chiamato il listener di eventi .

Per ottenere il valore dopo che il valore del campo è stato aggiornato, pianificare una funzione da eseguire nel ciclo di eventi successivo. Il modo usuale per farlo è chiamare setTimeoutcon un timeout di 0:

$('#field').keyup(function() {
    var $field = $(this);

    // this is the value before the keypress
    var beforeVal = $field.val();

    setTimeout(function() {

        // this is the value after the keypress
        var afterVal = $field.val();
    }, 0);
});

Prova qui: http://jsfiddle.net/Q57gY/2/

Modifica : alcuni browser (ad esempio Chrome) non attivano eventi di pressione dei tasti per backspace; ha cambiato la pressione del tasto in keyup nel codice.


Stavo per postare questo. Ecco il jsFiddle che ho fatto.
kapa

Hai ragione, Chrome sembra non attivare eventi di pressione dei tasti per backspace; aggiornato
Arnaud Le Blanc

@Ian, l'OP vuole che si aggiorni quando si tiene premuto un tasto? Non ero troppo sicuro se questo fosse un requisito. Questa soluzione non ha questa funzionalità, però.
Jonathan M

Per essere chiari: non attivare eventi di pressione dei tasti per backspace è per Standard: "tasto che produce un valore di carattere" - per altri tasti usa "tasto giù" (prima della modifica, cancellabile) o "tasto su" (dopo la modifica)
sebilasse

5

mantenerlo compatto.
Ogni volta che si preme un tasto, edValueKeyPress()viene chiamata la funzione .
Hai anche dichiarato e inizializzato alcune variabili in quella funzione, che rallentano il processo e richiedono anche più CPU e memoria.
Puoi semplicemente usare questo codice, derivato da una semplice sostituzione.

function edValueKeyPress()
{
    document.getElementById("lblValue").innerText =""+document.getElementById("edValue").value;
}

È tutto ciò che vuoi ed è più veloce!


3
<asp:TextBox ID="txtMobile" runat="server" CssClass="form-control" style="width:92%;  margin:0px 5px 0px 5px;" onkeypress="javascript:return isNumberKey(event);" MaxLength="12"></asp:TextBox>

<script>
    function isNumberKey(evt) {
        var charCode = (evt.which) ? evt.which : event.keyCode;
        if (charCode > 31 && (charCode < 48 || charCode > 57)) {
            return false;
        }
        return true;
    }
</script>

3

Nessuna delle risposte finora offre una soluzione completa. Ci sono alcuni problemi da affrontare:

  1. Non tutte le pressioni dei tasti vengono trasferite a keydownekeypress gestori (ad esempio, tornare indietro e cancellare le chiavi vengono soppressi da alcuni browser).
  2. La manipolazione keydownnon è una buona idea. Ci sono situazioni in cui un tasto premuto NON si traduce in una pressione di un tasto!
  3. setTimeout() le soluzioni di stile vengono ritardate nei browser Web Google Chrome / Blink fino a quando l'utente non smette di digitare.
  4. Gli eventi di tocco e mouse possono essere utilizzati per eseguire azioni come tagliare, copiare e incollare. Questi eventi non attiveranno gli eventi della tastiera.
  5. Il browser, a seconda del metodo di immissione, potrebbe non fornire la notifica che l'elemento è cambiato fino a quando l'utente non esce dal campo.

Una soluzione più corretta gestirà i keypress, keyup, input, e changegli eventi.

Esempio:

<p><input id="editvalue" type="text"></p>
<p>The text box contains: <span id="labelvalue"></span></p>

<script>
function UpdateDisplay()
{
    var inputelem = document.getElementById("editvalue");
    var s = inputelem.value;

    var labelelem = document.getElementById("labelvalue");
    labelelem.innerText = s;
}

// Initial update.
UpdateDisplay();

// Register event handlers.
var inputelem = document.getElementById("editvalue");
inputelem.addEventListener('keypress', UpdateDisplay);
inputelem.addEventListener('keyup', UpdateDisplay);
inputelem.addEventListener('input', UpdateDisplay);
inputelem.addEventListener('change', UpdateDisplay);
</script>

Violino:

http://jsfiddle.net/VDd6C/2175/

La gestione di tutti e quattro gli eventi cattura tutti i casi limite. Quando si lavora con l'input di un utente, è necessario considerare tutti i tipi di metodi di immissione e verificare la funzionalità cross-browser e cross-device. Il codice sopra è stato testato su Firefox, Edge e Chrome su desktop e sui dispositivi mobili che possiedo.


Perché non solo inputevento?
YakovL

inputnon si accende sempre. Nessun singolo evento copre tutte le situazioni.
CubicleSoft

sarebbe carino da parte tua se descrivi "non sempre" in modo più dettagliato, come hai specificato keypressnella risposta
YakovL

1

Normalmente concateno il valore del campo (cioè prima che venga aggiornato) con la chiave associata all'evento chiave. Quanto segue utilizza JS recente, quindi sarebbe necessario modificare il supporto per i vecchi IE.

Esempio JS recente

document.querySelector('#test').addEventListener('keypress', function(evt) {
    var real_val = this.value + String.fromCharCode(evt.which);
    if (evt.which == 8) real_val = real_val.substr(0, real_val.length - 2);
    alert(real_val);
}, false);

Supporto per i vecchi esempi di IE

//get field
var field = document.getElementById('test');

//bind, somehow
if (window.addEventListener)
    field.addEventListener('keypress', keypress_cb, false);
else
    field.attachEvent('onkeypress', keypress_cb);

//callback
function keypress_cb(evt) {
    evt = evt || window.event;
    var code = evt.which || evt.keyCode,
        real_val = this.value + String.fromCharCode(code);
    if (code == 8) real_val = real_val.substr(0, real_val.length - 2);
}

[MODIFICA - questo approccio, per impostazione predefinita, disabilita la pressione dei tasti per cose come lo spazio indietro, CTRL + A. Il codice sopra si adatta al primo, ma richiederebbe ulteriori ritocchi per consentire il secondo e alcune altre eventualità. Vedi il commento di Ian Boyd di seguito.]


1
@ bažmegakapa Oppure con il deletetasto, o se l'utente preme un tasto che non modifica il contenuto ( Ctrl+A), o se l'utente seleziona del testo e poi preme aper sostituire un sottoinsieme. È una bella idea, Utkanos, ma fragile.
Ian Boyd

1
Concordato. Lascerò perdere perché c'è un po 'di chilometraggio ma, come dici tu, dovresti aumentare le indennità per questi avvertimenti.
Mitya

1

facile...

Nel gestore dell'evento keyPress, scrivi

void ValidateKeyPressHandler(object sender, KeyPressEventArgs e)
{
    var tb = sender as TextBox;
    var startPos = tb.SelectionStart;
    var selLen= tb.SelectionLength;

    var afterEditValue = tb.Text.Remove(startPos, selLen)
                .Insert(startPos, e.KeyChar.ToString()); 
    //  ... more here
}

Cosa succede se e.KeyCharè la Backspacechiave? O la Deletechiave? Oppure Ctrl+A?
Ian Boyd

È anche JavaScript? void? object? metodi prima maiuscola?
YakovL

1

Quindi ci sono vantaggi e svantaggi per ogni evento. Gli eventi onkeypresse onkeydownnon recuperano il valore più recente eonkeypress non vengono attivati ​​per i caratteri non stampabili in alcuni browser. Ilonkeyup evento non rileva quando un tasto viene tenuto premuto per più caratteri.

Questo è un po 'complicato, ma fa qualcosa di simile

function edValueKeyDown(input) {
    var s = input.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: "+s;

    //var s = $("#edValue").val();
    //$("#lblValue").text(s);    
}
<input id="edValue" type="text" onkeydown="setTimeout(edValueKeyDown, 0, this)" />

sembra gestire il meglio di tutti i mondi.


1

Utilizzando event.key possiamo ottenere i valori prima dell'immissione nella casella di testo di input HTML. Ecco il codice.

function checkText()
{
  console.log("Value Entered which was prevented was - " + event.key);
  
  //Following will prevent displaying value on textbox
  //You need to use your validation functions here and return value true or false.
  return false;
}
<input type="text" placeholder="Enter Value" onkeypress="return checkText()" />


Questo va in pezzi quando il testo viene modificato tramite qualcosa che non è la pressione di un tasto (taglia, incolla, elimina selezionati, ecc.)
Ian Boyd

@IanBoyd sì d'accordo. Per mantenere l'esempio semplice, ho implementato solo le convalide dei tasti.
vibs2006

0

Prova a concatenare l'evento charCode al valore che ottieni. Ecco un esempio del mio codice:

<input type="text" name="price" onkeypress="return (cnum(event,this))" maxlength="10">
<p id="demo"></p>

js:

function cnum(event, str) {
    var a = event.charCode;
    var ab = str.value + String.fromCharCode(a);
    document.getElementById('demo').innerHTML = ab;
}

Il valore in abotterrà l'ultimo valore nel campo di input.


Scusa, ho notato un altro post con un approccio ancora migliore in questa pagina dopo averlo pubblicato. Non l'ho visto prima di postare. Ma penso che il mio sia più semplice da capire il concetto.
Rama Krishna

Che cade a pezzi piuttosto veloce quando la chiave è di cancellazione , backspace , Ctrl + X o Ctrl + V , o quando il mouse selezionato tutto il testo e premo spazio
Ian Boyd

Ho appena scritto la mia idea. puoi implementarlo in base alle tue esigenze utilizzando codici chiave o altri metodi. Questa è solo una mia idea.
Rama Krishna

1
Le idee non sono risposte. Le risposte su SO dovrebbero essere soluzioni concise che rispondano definitivamente alla domanda del PO in modo che tutti possano trarne vantaggio. Questo chiaramente non soddisfa tali criteri.
CubicleSoft

0

C'è un modo migliore per farlo. Usa il metodo concat. Esempio

dichiarare una variabile globale. funziona bene su angular 10, basta passarlo a Vanilla JavaScript. Esempio:

HTML

<input id="edValue" type="text" onKeyPress="edValueKeyPress($event)"><br>
<span id="lblValue">The text box contains: </span>

CODICE

emptyString = ''

edValueKeyPress ($event){
   this.emptyString = this.emptyString.concat($event.key);
   console.log(this.emptyString);
}

E quando la chiave è Delete, Ctrl+ X, Ctrl+ V, Backspace? O se hanno selezionato del testo e quindi premere A?
Ian Boyd
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.