Rilevazione onchange di Textarea


132

Come posso rilevare l'evento change su textarea usando javascript?
Sto cercando di rilevare quanti caratteri sono disponibili durante la digitazione.

Ho provato a utilizzare l'evento onchange, ma sembra che entri in azione solo quando lo stato attivo è fuori.

Risposte:


97

Dovrai usare onkeyup e onchange per questo. L'onchange impedirà l'incollaggio del menu di scelta rapida e l'onkeyup verrà attivato per ogni sequenza di tasti.

Vedi la mia risposta su Come imporre maxlength su textArea per un esempio di codice.


3
Volevo solo sottolineare ciò che Josh aveva già detto, che dovresti usare il keyup, non il keydown per questo: il keydown sembra essere chiamato prima che la modifica venga effettivamente apportata alla textarea, quindi utilizzerai la lunghezza sbagliata (e non so davvero come stai: potrebbe essere digitando o eliminando e potrebbe avere testo selezionato, il che significa che è più di solo +/- 1).
brianmearns,

65
Sto dando un -1 qui, scusa! onkeyupè un evento terribile per il rilevamento degli input. Usa oninpute onpropertychange(per supporto IE).
Andy E,

6
Il "solo" problema NONonchange viene generato quando si verifica un incolla / taglia menu di scelta rapida.
Tom,

4
È molto più reattivo utilizzare onkeydown e un setTimeout in modo da ottenere un rilevamento delle modifiche istantaneo piuttosto che attendere il rilascio della chiave. Se devi anche catturare taglia e incolla, usa gli eventi taglia e incolla.
Kevin B,

1
Avvertenza: onkeyup può causare problemi. Esempio: diciamo che dovresti fare qualcosa solo se il contenuto dell'input è cambiato. Se si assume che un keyup cambierà l'input, non è vero. Concentrati sull'input. Utilizzare "tab" per passare al campo successivo. Ora usa "shift + tab" per tornare all'input. il keyup si attiva ma l'input non è stato effettivamente modificato dall'utente.
Zig Mandel

117

È il 2012, l'era post-PC è arrivata e dobbiamo ancora lottare con qualcosa di così semplice. Questo dovrebbe essere molto semplice .

Fino a quando quel sogno non sarà realizzato, ecco il modo migliore per farlo, cross-browser: usa una combinazione degli eventi inputeonpropertychange , in questo modo:

var area = container.querySelector('textarea');
if (area.addEventListener) {
  area.addEventListener('input', function() {
    // event handling code for sane browsers
  }, false);
} else if (area.attachEvent) {
  area.attachEvent('onpropertychange', function() {
    // IE-specific event handling code
  });
}

L' inputevento si occupa di IE9 +, FF, Chrome, Opera e Safari e onpropertychangesi occupa di IE8 (funziona anche con IE6 e 7, ma ci sono alcuni bug).

Il vantaggio di usare inputed onpropertychangeè che non sparano inutilmente (come quando si premono i tasti Ctrlo Shift); quindi se si desidera eseguire un'operazione relativamente costosa quando cambiano i contenuti dell'area di testo, questa è la strada da percorrere .

Ora IE, come sempre, fa un lavoro a metà per sostenere questo: inputné si onpropertychangeattiva in IE quando i caratteri vengono eliminati dalla textarea. Quindi, se hai bisogno di gestire la cancellazione di caratteri in IE, usa keypress(invece di usare keyup/ keydown, perché sparano solo una volta anche se l'utente preme e tiene premuto un tasto).

Fonte: http://www.alistapart.com/articles/expanding-text-areas-made-elegant/

EDIT: Sembra che anche la soluzione di cui sopra non sia perfetta, come giustamente sottolineato nei commenti: la presenza della addEventListenerproprietà nell'area di testo non implica che stai lavorando con un browser sano; allo stesso modo la presenza della attachEventproprietà non implica IE. Se vuoi che il tuo codice sia davvero a tenuta stagna, dovresti considerare di cambiarlo. Vedi il commento di Tim Down per i puntatori.


1
Questo è l'approccio migliore. Non mi piacciono le inferenze qui (il supporto del browser per addEventListenernon implica il supporto per l' inputevento, o viceversa); il rilevamento delle funzionalità sarebbe migliore. Vedi questo post sul blog per una discussione di questo.
Tim Down

Totalmente d'accordo con Tim su questo. oninputè come dovremmo farlo, ma probabilmente non dovresti usare addEventListenercome test per il supporto del browser. +1 in ogni caso.
Ben D,

1
Non sono d'accordo, l'input non si occuperà di IE9. Purtroppo è anche possibile inserire Taglia / Incolla tramite il menu contestuale, così come il backspace. Non mi sono preso la briga di provare, ma non scommetterei sulla scommessa che IE10 + ha risolto il problema.
Stefan Steiger,

1
@StefanSteiger ed è per questo che la mia risposta suggerisce di usare anche l' keypressevento per gestire quel caso in IE9 (e forse anche nelle versioni successive).
Vicky Chijwani,

inputil gestore eventi può anche essere definito implementando la .oninputproprietà object.
gestire il

20
  • Per Google-Chrome, oninput sarà sufficiente (testato su Windows 7 con la versione 22.0.1229.94 m).
  • Per IE 9, oninput catturerà tutto tranne il taglio tramite il menu contestuale e il backspace.
  • Per IE 8, onpropertychange è necessario per intercettare oltre a oninput.
  • Per IE 9 + 8, onkeyup è necessario per catturare il backspace.
  • Per IE 9 + 8, onmousemove è l'unico modo in cui ho scoperto di tagliare attraverso il menu contestuale

Non testato su Firefox.

    var isIE = /*@cc_on!@*/false; // Note: This line breaks closure compiler...

    function SuperDuperFunction() {
        // DoSomething
    }


    function SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally() {
        if(isIE) // For Chrome, oninput works as expected
            SuperDuperFunction();
    }

<textarea id="taSource"
          class="taSplitted"
          rows="4"
          cols="50"
          oninput="SuperDuperFunction();"
          onpropertychange="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
          onmousemove="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
          onkeyup="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();">
Test
</textarea>

1
Nomi fantastici di funzioni :)
Jonas Gröger il

8

So che questa non è esattamente la tua domanda, ma ho pensato che potesse essere utile. Per alcune applicazioni è bello avere la funzione di modifica attiva non ogni volta che si preme un tasto. Questo può essere ottenuto con qualcosa del genere:

var text = document.createElement('textarea');
text.rows = 10;
text.cols = 40;
document.body.appendChild(text);

text.onkeyup = function(){
var callcount = 0;
    var action = function(){
        alert('changed');
    }
    var delayAction = function(action, time){
        var expectcallcount = callcount;
        var delay = function(){
            if(callcount == expectcallcount){
                action();
            }
        }
        setTimeout(delay, time);
    }
    return function(eventtrigger){
        ++callcount;
        delayAction(action, 1200);
    }
}();

Funziona testando se un evento più recente è stato generato entro un certo periodo di ritardo. In bocca al lupo!


1
+1 per l'azione ritardata "limitazione"! Uso qualcosa di simile nella mia app.
psulek,

7

So che questa domanda era specifica di JavaScript, tuttavia, sembra che non ci sia un buon modo pulito per rilevare SEMPRE quando una textarea cambia in tutti i browser attuali. Ho imparato che jquery se ne è preso cura per noi. Gestisce anche le modifiche contestuali al menu nelle aree di testo. La stessa sintassi viene utilizzata indipendentemente dal tipo di input.

    $('div.lawyerList').on('change','textarea',function(){
      // Change occurred so count chars...
    });

o

    $('textarea').on('change',function(){
      // Change occurred so count chars...
    });

4
Ho scoperto che l'evento di modifica non era più coerente con jQuery che con JS semplice. Ho usato jQuery bind("input cut paste"...e funziona come un incantesimo: digitare, tagliare e incollare usando la tastiera o il menu contestuale; anche trascinamento / rilascio del testo.
Lawrence Dol,

2
Sfortunatamente, FF non genera changeeventi per textarea.
dma_k,

4

Puoi ascoltare l'evento al cambio di textarea ed eseguire le modifiche come desideri. Ecco un esempio

(() => {
	const textArea = document.getElementById('my_text_area');
  textArea.addEventListener('input', () => {
    let textLn =  textArea.value.length;
    if(textLn >= 100) {
      textArea.style.fontSize = '10pt';
    }

  })
})()
<html>
<textarea id='my_text_area' rows="4" cols="50" style="font-size:40pt">
This text will change font after 100.
</textarea>
</html>


1

Il keyup dovrebbe essere sufficiente se abbinato all'attributo di validazione / modello di input HTML5. Quindi, crea un modello (regex) per convalidare l'input e agire sullo stato .checkValidity (). Qualcosa come sotto potrebbe funzionare. Nel tuo caso vorresti che una regex corrispondesse alla lunghezza. La mia soluzione è in uso / demo online online qui .

<input type="text" pattern="[a-zA-Z]+" id="my-input">

var myInput = document.getElementById = "my-input";

myInput.addEventListener("keyup", function(){
  if(!this.checkValidity() || !this.value){
    submitButton.disabled = true;
  } else {
    submitButton.disabled = false;
  }
});

0

Codice che ho usato per IE 11 senza jquery e solo per una singola textarea:

Javascript:

// Impede que o comentário tenha mais de num_max caracteres
var internalChange= 0; // important, prevent reenter
function limit_char(max)
{ 
    if (internalChange == 1)
    {
        internalChange= 0;
        return;
    }
    internalChange= 1;
    // <form> and <textarea> are the ID's of your form and textarea objects
    <form>.<textarea>.value= <form>.<textarea>.value.substring(0,max);
}

e html:

<TEXTAREA onpropertychange='limit_char(5)' ...

-1

Prova questo. È semplice e dal 2016 sono sicuro che funzionerà sulla maggior parte dei browser.

<textarea id="text" cols="50" rows="5" onkeyup="check()" maxlength="15"></textarea> 
<div><span id="spn"></span> characters left</div>

function check(){
    var string = document.getElementById("url").value
    var left = 15 - string.length;
    document.getElementById("spn").innerHTML = left;
}

Quindi ricevi l'URL per ID, ma non è mostrato nel tuo codice.
AbsoluteƵERØ

-8

La cosa migliore che puoi fare è impostare una funzione da chiamare per un determinato periodo di tempo e questa funzione per controllare il contenuto della tua textarea.

self.setInterval('checkTextAreaValue()', 50);

7
il polling è una pessima idea. Distruggerà semplicemente le prestazioni. Inoltre, come altri pubblicati, esiste una soluzione
Pier-Olivier Thibault l'

2
Questo è il 21 ° secolo. Nessun browser dovrebbe avere problemi a gestire un confronto di stringhe ogni 50 ms. Metti nella cache i tuoi selettori e questa è una soluzione perfettamente accettabile.
nullability
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.