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.