Das Erkennen des Inhalts eines Textfelds hat sich geändert

417

Ich möchte erkennen, wann sich der Inhalt eines Textfelds geändert hat. Ich kann die Keyup-Methode verwenden, aber das erkennt auch Tastenanschläge, die keine Buchstaben erzeugen, wie die Pfeiltasten. Ich dachte an zwei Methoden, um dies mit dem Keyup-Ereignis zu tun:

  1. Überprüfen Sie explizit, ob der ASCII-Code der gedrückten Taste ein Buchstabe \ Rücktaste \ Löschen ist
  2. Verwenden Sie Verschlüsse, um sich den Text im Textfeld vor dem Tastenanschlag zu merken und zu überprüfen, ob sich dieser geändert hat.

Beide sehen etwas umständlich aus.

Olamundo
quelle
7
Ja, Keyup dafür zu bekommen ist schlecht. Sie können Inhalte ohne Tastendruck einfügen.
Spender
2
Gibt es eine Chance, dass Sie Ihre endgültige Lösung veröffentlichen können? Ich muss dieses Problem auch lösen :)
Matt Dotson
1
oder .keyup()Veranstaltung ... mehr Infos hier: stackoverflow.com/questions/3003879/…
Victor S
1
Siehe $ ("# some-input"). ChangePolling () ; für einen Wrapper, der den aktuellen Wert überprüft und auslöst, .change()wenn er sich geändert hat.
Joel Purra
Sie müssen dies auch überprüfen stackoverflow.com/a/23266812/3160597
azerafati

Antworten:

714

Beobachten Sie das 'Eingabe'-Ereignis anstelle von' Ändern '.

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

... was schön und sauber ist, aber noch erweitert werden kann auf:

jQuery('#some_text_box').on('input propertychange paste', function() {
    // do your stuff
});
Atul Vani
quelle
12
'live' ist veraltet. Nutzen Sie also 'on' stackoverflow.com/a/15111970/1724777
NavaRajan
21
Der einzige Nachteil von 'Eingabe' ist, dass es nicht mit IE <9 kompatibel ist.
Catfish
5
Die Eingabe ist ein HTML5-Ereignis, das nicht in allen Browsern unterstützt wird. developer.mozilla.org/en-US/docs/Web/API/window.oninput
commonpike
18
Sie können auch mehr Basen abdecken, indem Sie Folgendes verwenden: .on ('input propertychange paste', function () {
Graeck
23
Der einzige Nachteil von IE <9 ist, dass niemand es benutzt!
Sohaiby
67

Verwenden Sie das Ereignis onchange in HTML / Standard-JavaScript.

In jQuery ist dies das Ereignis change () . Zum Beispiel:

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

BEARBEITEN

Was ist nach dem Lesen einiger Kommentare:

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

    $('#myContent').keyup(function() { 
        if ($('#myContent').val() != content) {
            content = $('#myContent').val();
            alert('Content has been changed');
        }
    });
});
Waleed Amjad
quelle
3
Ja, dies ähnelt dem, was ich in Option 2 in meiner Frage vorgeschlagen habe. Ich bevorzuge Schließungen, da diese Funktion bei Verwendung einer globalen Funktion nur für ein Textfeld funktioniert. Wie auch immer, es scheint seltsam, dass jquery keinen einfacheren Weg hat, dies zu tun.
Olamundo
1
Es ist in der Tat komisch, aber ich bezweifle, dass es einen besseren Weg gibt, es zu tun. Sie können setInterval verwenden und dann alle 0,1 Sekunden überprüfen, ob der Inhalt geändert wurde, und dann etwas unternehmen. Dies schließt auch Mauspasten usw. ein. Aber es klingt nicht zu elegant.
Waleed Amjad
4
Es ist weiterhin möglich, dass der Inhalt ohne Tastendruck geändert werden kann, beispielsweise durch Einfügen mit der Maus. Wenn Sie sich dafür interessieren, könnten Sie theoretisch auch Mausereignisse abfangen, aber dieses Setup ist noch hässlicher. Wenn Sie jedoch bereit sind, mausgesteuerte Änderungen zu ignorieren, reicht dies aus.
Adam Bellaire
45

Das 'change'-Ereignis funktioniert nicht richtig, aber die' input 'ist perfekt.

$('#your_textbox').bind('input', function() {
    /* This will be fired every time, when textbox's value changes. */
} );
schwarzkopfb
quelle
7
Dies funktioniert perfekt für meine Situation, obwohl die Verwendung von .onab 1.7 (anstatt .bind) empfohlen wird .
Nick
8
OP hat keine Notwendigkeit für Cross-Browser-Kompatibilität angegeben. @schwarzkopfb lieferte eine Lösung. Kein Grund, abzustimmen, weil Sie den Repräsentanten dazu haben.
David East
3
@ David er hat auch nicht angegeben, welcher Browser
ozz
9
@ jmo21 Ich denke, wir können für die Webentwicklung davon ausgehen, dass die Lösung funktionsübergreifend sein sollte, wenn ein Browser nicht spezifisch ist. Die Norm unterstützt alle Browser.
Chris
3
@Chris "Die Norm unterstützt alle Browser" - nur wenn Sie ein Sadist sind. Es gibt keinen guten Grund, die HTML5-Güte für 2% der globalen Benutzer im IE 8/9 zu vermeiden. caniuse.com/#feat=input-event
Yarin
39

Wie wäre es damit:

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

Dies funktioniert in IE8 / IE9, FF, Chrome

Wels
quelle
1
Das Problem mit dieser Antwort ist, dass sie ausgelöst wird, sobald Sie das Textfeld verwischen, auch wenn sich der Wert nicht geändert hat. Der Schuldige ist "Veränderung".
Justin
Verwenden Sie Chrome? Scheint, es ist ein Fehler mit Chrom und nicht jQuerys
Catfish
funktioniert, hat aber einen kleinen Fehler, wenn Sie console.logden Wert des Feldes eingeben, das zweimal protokolliert wird, wenn Sie ein Zeichen eingeben.
Samuel M.
21

Verwenden Sie Verschlüsse, um sich den Text im Kontrollkästchen vor dem Tastendruck zu merken und zu überprüfen, ob sich dies geändert hat.

Ja. Sie müssen nicht unbedingt Verschlüsse verwenden, aber Sie müssen sich den alten Wert merken und ihn mit dem neuen vergleichen.

Jedoch! Dies wird immer noch nicht jede Änderung erfassen, da es Möglichkeiten zum Bearbeiten von Textfeldinhalten gibt, bei denen kein Tastendruck erforderlich ist. Wählen Sie beispielsweise einen Textbereich aus und klicken Sie mit der rechten Maustaste. Oder ziehen Sie es. Oder legen Sie Text aus einer anderen App in das Textfeld ab. Oder ändern Sie ein Wort über die Rechtschreibprüfung des Browsers. Oder...

Wenn Sie also jede Änderung erkennen müssen, müssen Sie danach fragen. Sie window.setIntervalkönnen das Feld jede (sagen wir) Sekunde mit seinem vorherigen Wert vergleichen. Sie könnten auch Draht onkeyupauf die gleiche Funktion , so dass Änderungen , die sich durch Drücken von Tasten verursacht schneller reflektiert werden .

Schwerfällig? Ja. Aber es ist das oder machen Sie es einfach auf die normale Art und Weise beim HTML-Wechsel und versuchen Sie nicht, sofort zu aktualisieren.

Bobince
quelle
1
Heutzutage inputist das HTML5- Ereignis realisierbar und funktioniert in den aktuellen Versionen aller gängigen Browser.
Tim Down
13
$(document).on('input','#mytxtBox',function () { 
 console.log($('#mytxtBox').val());
});

Sie können das Ereignis 'Eingabe' verwenden, um die Inhaltsänderung im Textfeld zu erkennen. Verwenden Sie nicht 'live', um das Ereignis zu binden, da es in Jquery-1.7 veraltet ist. Verwenden Sie also 'on'.

NavaRajan
quelle
@NavaRajan Habe es gerade nochmal in IE9 getestet. funktioniert wirklich nicht auf Rücktaste.
Flores
Ich möchte .live NICHT verwenden, aber das Problem, das ich habe, ist, dass ich irgendwie "zurück in die Zukunft" und in ein mvc3-Projekt gegangen bin, in dem der Teamleiter "out of the box" bleiben möchte, also nicht Nur EF 4.0, aber jquery 1.5.1 wird verwendet. Daher war .on () nicht in 1.5.1 enthalten, da es in jquery Version 1.7 hinzugefügt wurde. api.jquery.com/on
Tom Stickel
5

Ich gehe davon aus, dass Sie etwas Interaktives tun möchten, wenn sich das Textfeld ändert (dh einige Daten über Ajax abrufen). Ich habe nach der gleichen Funktionalität gesucht. Ich weiß, dass die Verwendung einer globalen Lösung nicht die robusteste oder eleganteste Lösung ist, aber genau das habe ich gewählt. Hier ist ein Beispiel:

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

Hierbei ist zu beachten, dass ich setTimeout und nicht setInterval verwende, da ich nicht mehrere Anforderungen gleichzeitig senden möchte. Dies stellt sicher, dass der Timer "stoppt", wenn das Formular gesendet wird, und "startet", wenn die Anforderung abgeschlossen ist. Dazu rufe ich checkSearchChanged auf, wenn mein Ajax-Aufruf abgeschlossen ist. Natürlich können Sie dies erweitern, um die Mindestlänge usw. zu überprüfen.

In meinem Fall verwende ich ASP.Net MVC, sodass Sie im folgenden Beitrag sehen können, wie Sie dies auch mit MVC Ajax verknüpfen können:

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

Doug Lampe
quelle
4

Ich würde empfehlen, einen Blick auf das Widget für die automatische Vervollständigung der jQuery-Benutzeroberfläche zu werfen. Sie haben die meisten Fälle dort bearbeitet, da ihre Codebasis ausgereifter ist als die der meisten anderen.

Unten finden Sie einen Link zu einer Demoseite, auf der Sie überprüfen können, ob sie funktioniert. http://jqueryui.com/demos/autocomplete/#default

Sie werden den größten Nutzen daraus ziehen, die Quelle zu lesen und zu sehen, wie sie sie gelöst haben. Sie finden es hier: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js .

Im Grunde machen sie alles, an das sie sich binden input, keydown, keyup, keypress, focus and blur. Dann haben sie spezielle Handhabung für alle Arten von Schlüsseln wie page up, page down, up arrow key and down arrow key. Ein Timer wird verwendet, bevor der Inhalt des Textfelds abgerufen wird. Wenn ein Benutzer eine Taste eingibt, die keinem Befehl entspricht (Aufwärts-Taste, Abwärts-Taste usw.), gibt es einen Timer, der den Inhalt nach etwa 300 Millisekunden untersucht. Im Code sieht es so aus:

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

Der Grund für die Verwendung eines Timers besteht darin, dass die Benutzeroberfläche aktualisiert werden kann. Wenn Javascript ausgeführt wird, kann die Benutzeroberfläche nicht aktualisiert werden, daher der Aufruf der Verzögerungsfunktion. Dies funktioniert gut in anderen Situationen, z. B. wenn Sie sich auf das Textfeld konzentrieren (das von diesem Code verwendet wird).

Sie können also entweder das Widget verwenden oder den Code in Ihr eigenes Widget kopieren, wenn Sie nicht die jQuery-Benutzeroberfläche verwenden (oder in meinem Fall ein benutzerdefiniertes Widget entwickeln).

Michael Yagudaev
quelle
2

Ich möchte fragen, warum Sie versuchen zu erkennen, wann sich der Inhalt des Textfelds in Echtzeit geändert hat .

Eine Alternative wäre, einen Timer (über setIntval?) Einzustellen und den zuletzt gespeicherten Wert mit dem aktuellen zu vergleichen und dann einen Timer zurückzusetzen. Dies würde garantieren, dass JEDE Änderung erfasst wird, sei es durch Tasten, Maus, ein anderes Eingabegerät, das Sie nicht in Betracht gezogen haben, oder sogar durch JavaScript, das den Wert (eine andere Möglichkeit, die niemand erwähnt hat) von einem anderen Teil der App aus ändert.

DVK
quelle
Meine Situation (die mich zu dieser Frage geführt hat) ist, dass ich eine Schaltfläche "Warenkorb aktualisieren" anzeigen muss, wenn die Menge in einem Textfeld geändert wird. Der Benutzer hat keine Ahnung, dass er den Fokus verlieren muss, und sieht die Schaltfläche ansonsten möglicherweise nicht.
Simon_Weaver
Entschuldigung, ich bin mir nicht sicher, ob dies die Frage "Warum nicht nach Unterschieden in einem Zeitplan suchen" beantwortet. Überprüfen Sie einfach oft genug (jede 1/4 Sekunde) und der Benutzer wird keinen Unterschied bemerken.
DVK
1

Ziehen Sie in Betracht, ein Änderungsereignis zu verwenden ?

$("#myTextBox").change(function() { alert("content changed"); });
Canavar
quelle
5
AFAIK wird nur ausgelöst, wenn der Fokus des Elements verloren geht. Jemand, der mit Verschlüssen vertraut ist, weiß wahrscheinlich davon. :)
Simon
Ja, das geht nicht - das Änderungsereignis wird nur aufgerufen, wenn das Textfeld den Fokus verliert. Ich möchte die Änderung direkt nach dem Drücken der Taste durchführen.
Olamundo
1

Verwenden Sie das textchangeEreignis über einen benutzerdefinierten jQuery-Shim, um die Cross-Browser- inputKompatibilität zu gewährleisten. http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html (zuletzt gegabelter Github: https://github.com/pandell /jquery-splendid-textchange/blob/master/jquery.splendid.textchange.js )

Dies behandelt alle Eingabe-Tags einschließlich <textarea>content</textarea>, was nicht immer mit change keyupusw. funktioniert . (!) Nur jQuery on("input propertychange")behandelt <textarea>Tags konsistent, und das oben Genannte ist ein Shim für alle Browser, die das inputEreignis nicht verstehen .

<!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>

JS Bin Test

Dies behandelt auch das Einfügen, Löschen und dupliziert den Aufwand beim Keyup nicht.

Wenn Sie kein Shim verwenden, verwenden Sie jQuery- on("input propertychange")Ereignisse.

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

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

Es gibt ein komplettes Arbeits Beispiel hier .

<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>
worldofjr
quelle
0

So etwas sollte funktionieren, hauptsächlich weil focusund focusoutam Ende zwei separate Werte vorliegen würden. Ich verwende es datahier, weil es Werte im Element speichert, aber das DOM nicht berührt. Es ist auch eine einfache Möglichkeit, den mit seinem Element verbundenen Wert zu speichern. Sie können genauso gut eine Variable mit höherem Gültigkeitsbereich verwenden.

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

Dieser Code erkennt, wann immer sich der Inhalt eines Textfelds vom Benutzer geändert und durch Javascript-Code geändert hat.

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);
Sandeep Yadav
quelle