Textbereich bei Änderungserkennung

132

Wie erkenne ich Änderungsereignisse im Textbereich mithilfe von Javascript?
Ich versuche festzustellen, wie viele Zeichen während der Eingabe noch verfügbar sind.

Ich habe versucht, das Ereignis onchange zu verwenden, aber das scheint nur dann zu funktionieren, wenn der Fokus nicht mehr vorhanden ist.

teepusink
quelle

Antworten:

97

Sie müssen onkeyup und onchange dafür verwenden. Der Onchange verhindert das Einfügen von Kontextmenüs, und der Onkeyup wird bei jedem Tastendruck ausgelöst.

Ein Codebeispiel finden Sie in meiner Antwort zum Auferlegen der maximalen Länge für textArea .

Josh Stodola
quelle
3
Ich wollte nur betonen, was Josh bereits gesagt hat, dass Sie dafür Keyup und nicht Keydown verwenden sollten: Keydown scheint aufgerufen zu werden, bevor die Änderung tatsächlich am Textbereich vorgenommen wird, sodass Sie die falsche Länge verwenden (und Sie nicht) Ich weiß nicht genau, wie schlecht es Ihnen geht: Sie können tippen oder löschen und Text auswählen, was bedeutet, dass er mehr als nur +/- 1) ist.
Brianmearns
65
Ich gebe hier eine -1, sorry! onkeyupist ein schreckliches Ereignis für die Eingabeerkennung. Verwenden Sie oninputund onpropertychange(für IE-Unterstützung).
Andy E
6
Das „nur“ Problem onchangewird nicht ausgelöst , wenn ein Kontextmenü Ausschneiden / Einfügen auftritt.
Tom
4
Die Verwendung von onkeydown und setTimeout reagiert viel schneller, sodass Sie eine sofortige Änderungserkennung erhalten, anstatt auf die Freigabe des Schlüssels zu warten. Wenn Sie auch Ausschneiden und Einfügen abfangen müssen, verwenden Sie die Ereignisse Ausschneiden und Einfügen.
Kevin B
1
Warnung: Onkeyup kann Ihnen Probleme bereiten. Beispiel: Nehmen wir an, Sie sollten nur etwas tun, wenn sich der Eingabeinhalt geändert hat. Wenn Sie davon ausgehen, dass ein Keyup die Eingabe ändert, ist dies nicht der Fall. Konzentrieren Sie sich auf die Eingabe. Verwenden Sie "Tab", um zum nächsten Feld zu gelangen. Verwenden Sie nun "Shift + Tab", um zur Eingabe zurückzukehren. keyup wird ausgelöst, aber die Eingabe wurde vom Benutzer nicht geändert.
Zig Mandel
117

Es ist 2012, die Post-PC-Ära ist da und wir haben immer noch mit so etwas Grundlegendem zu kämpfen. Das sollte sehr einfach sein .

Bis sich dieser Traum erfüllt hat, ist dies der beste Weg, dies über einen Browser zu tun: Verwenden Sie eine Kombination aus inputund onpropertychangeEreignissen wie folgt:

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

Das inputEreignis kümmert sich um IE9 +, FF, Chrome, Opera und Safari und onpropertychangekümmert sich um IE8 (es funktioniert auch mit IE6 und 7, aber es gibt einige Fehler).

Der Vorteil von inputund onpropertychangebesteht darin, dass sie nicht unnötig ausgelöst werden (wie beim Drücken der Tasten Ctrloder Shift). so , wenn Sie ändern , um eine relativ teure Operation , wenn die Textarea Inhalte ausführen möchten, ist dies der Weg zu gehen .

Jetzt unterstützt IE dies wie immer nur halb: Es wird im IE weder ausgelöst inputnoch ausgelöst, onpropertychangewenn Zeichen aus dem Textbereich gelöscht werden . Wenn Sie also das Löschen von Zeichen im IE behandeln müssen, verwenden Sie keypress(im Gegensatz zur Verwendung von keyup/ keydown, da diese nur einmal ausgelöst werden, selbst wenn der Benutzer eine Taste drückt und gedrückt hält).

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

BEARBEITEN: Es scheint, dass selbst die obige Lösung nicht perfekt ist, wie in den Kommentaren zu Recht ausgeführt: Das Vorhandensein der addEventListenerEigenschaft im Textbereich bedeutet nicht, dass Sie mit einem vernünftigen Browser arbeiten. in ähnlicher Weise das Vorhandensein der attachEventUnterkunft gibt es nicht bedeuten , IE. Wenn Sie möchten, dass Ihr Code wirklich luftdicht ist, sollten Sie dies ändern. Hinweise finden Sie in Tim Downs Kommentar .

Vicky Chijwani
quelle
1
Dies ist der beste Ansatz. Ich mag die Schlussfolgerungen hier nicht (Browserunterstützung für addEventListenerbedeutet keine Unterstützung für das inputEreignis oder umgekehrt); Feature-Erkennung wäre besser. In diesem Blogbeitrag finden Sie eine Diskussion dazu.
Tim Down
Stimme Tim in diesem Punkt voll und ganz zu. oninputSo sollten wir das machen, aber Sie sollten es wahrscheinlich nicht addEventListenerals Test für die Browserunterstützung verwenden. +1 auf jeden Fall.
Ben D
1
Nicht einverstanden, Eingabe kümmert sich nicht um IE9. Ausschneiden / Einfügen über das Kontextmenü wird leider auch eingegeben, ebenso wie die Rücktaste. Ich habe mich nicht darum gekümmert zu testen, aber ich würde kein Geld auf die Wette setzen, dass IE10 + dieses Problem behoben hat.
Stefan Steiger
1
@StefanSteiger, weshalb meine Antwort vorschlägt, das keypressEreignis auch zu verwenden, um diesen Fall in IE9 (und möglicherweise auch in späteren Versionen) zu behandeln.
Vicky Chijwani
inputDer Ereignishandler kann auch durch Implementieren der .oninputObjekteigenschaft definiert werden .
behandeln
20
  • Für Google-Chrome ist eine Eingabe ausreichend (getestet unter Windows 7 mit Version 22.0.1229.94 m).
  • Bei IE 9 erfasst oninput alles außer dem Schneiden über das Kontextmenü und die Rücktaste.
  • Für IE 8 ist onpropertychange erforderlich, um zusätzlich zu oninput das Einfügen abzufangen.
  • Für IE 9 + 8 ist onkeyup erforderlich, um die Rücktaste abzufangen.
  • Für IE 9 + 8 ist onmousemove die einzige Möglichkeit, das Schneiden über das Kontextmenü zu erfassen

Nicht auf Firefox getestet.

    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>
Stefan Steiger
quelle
1
Fantastische Funktionsnamen :)
Jonas Gröger
8

Ich weiß, dass dies nicht genau Ihre Frage ist, aber ich dachte, dass dies nützlich sein könnte. Für bestimmte Anwendungen ist es schön, dass die Änderungsfunktion nicht jedes Mal ausgelöst wird, wenn eine Taste gedrückt wird. Dies kann mit so etwas erreicht werden:

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

Dies funktioniert durch Testen, ob ein neueres Ereignis innerhalb einer bestimmten Verzögerungszeit ausgelöst wurde. Viel Glück!

user45743
quelle
1
+1 für 'Drosselung' verzögerte Aktion! Ich verwende etwas Ähnliches in meiner App.
psulek
7

Ich weiß, dass diese Frage spezifisch für JavaScript war. Es scheint jedoch keine gute und saubere Möglichkeit zu geben, IMMER zu erkennen, wenn sich ein Textbereich in allen aktuellen Browsern ändert. Ich habe erfahren, dass jquery sich für uns darum gekümmert hat. Es werden sogar kontextbezogene Menüänderungen an Textbereichen verarbeitet. Die gleiche Syntax wird unabhängig vom Eingabetyp verwendet.

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

oder

    $('textarea').on('change',function(){
      // Change occurred so count chars...
    });
Tim Duncklee
quelle
4
Ich stellte fest, dass das Änderungsereignis nicht konsistenter mit jQuery als mit einfachem JS war. Ich habe jQuery's verwendet bind("input cut paste"...und es funktioniert wie ein Zauber - Tippen, Ausschneiden und Einfügen über die Tastatur oder das Kontextmenü; sogar Drag & Drop von Text.
Lawrence Dol
2
Leider feuert FF kein changeEreignis für textarea.
dma_k
4

Sie können das Ereignis beim Ändern des Textbereichs anhören und die Änderungen nach Ihren Wünschen vornehmen. Hier ist ein Beispiel.

(() => {
	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>

Pankaj Manali
quelle
1

Keyup sollte ausreichen, wenn es mit dem HTML5-Eingabevalidierungs- / Musterattribut gepaart ist. Erstellen Sie also ein Muster (Regex), um die Eingabe zu validieren und auf den Status .checkValidity () zu reagieren. So etwas wie unten könnte funktionieren. In Ihrem Fall möchten Sie, dass ein regulärer Ausdruck der Länge entspricht. Meine Lösung wird hier online verwendet / demonstriert .

<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;
  }
});
Ronnie Royston
quelle
0

Code, den ich für IE 11 ohne Abfrage und nur für einen einzelnen Textbereich verwendet habe:

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

und html:

<TEXTAREA onpropertychange='limit_char(5)' ...
Rogério Silva
quelle
-1

Probier diese. Es ist einfach und seit 2016 ist es sicher für die meisten Browser geeignet.

<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;
}
Standard
quelle
Sie erhalten also eine URL nach ID, die jedoch in Ihrem Code nicht angezeigt wird.
AbsoluteƵERØ
-8

Das Beste, was Sie tun können, ist, eine Funktion festzulegen, die für einen bestimmten Zeitraum aufgerufen werden soll, und diese Funktion, um den Inhalt Ihres Textbereichs zu überprüfen.

self.setInterval('checkTextAreaValue()', 50);
Ico
quelle
7
Umfragen sind eine sehr schlechte Idee. Es wird nur die Leistung zerstören. Wie bei anderen veröffentlichten gibt es auch hier eine Lösung
Pier-Olivier Thibault
2
Dies ist das 21. Jahrhundert. Kein Browser sollte Probleme haben, alle 50 ms einen Zeichenfolgenvergleich durchzuführen. Zwischenspeichern Sie Ihre Selektoren und dies ist eine absolut akzeptable Lösung.
Nichtigkeit