2010-10-13 6 views
18

Ist es möglich, das eingegebene Zeichen bei Tastendruck zu ändern, ohne es manuell zu tun?Kann ich das eingegebene Zeichen bei Tastendruck bedingt ändern?

Zum Beispiel, wenn ich Großbuchstaben erzwingen wollen, basierend auf einer Bedingung, wäre es schön, folgendes zu tun:

function onKeypressHandler(e) 
{ 
    if (condition) 
    { 
     e.which -= 32; 
    } 
} 

Aber natürlich, das nicht funktioniert.

HINWEIS: Dies ist nicht ein auf der ganzen Linie großgeschrieben, aber nur bestimmte Zeichen.

Vielleicht will ich if (e.which >= 97 && e.which <= 102) oder if (Wind.Direction == 'South') oder was auch immer sagen - die Bedingung selbst ist nicht wichtig, aber die großgeschrieben muss nur auf den aktuellen Charakter gilt nicht die gesamte Eingabe.


Ich kann es tun, indem ich das geänderte Zeichen manuell angehängt habe, aber das ist eine hässliche und chaotische Art, es zu tun, und wahrscheinlich langsamer als es sein könnte.

function onKeypressHandler(e) 
{ 
    if (condition) 
    { 
     $j(this).val($j(this).val() + String.fromCharCode(e.which - 32)); 
     return false; 
    } 
} 

Ein spezifischen Fehler mit dieser Methode - wenn alle eingegebenen Texte auswählen und einen Schlüssel eingeben, wenn sie in diesen fallen dann ist es vorhandene Inhalte nicht zu entfernen, sondern einfach anhängt zum Inhalt wollte der Benutzer entfernt. (Müsste untersuchen, jeden ausgewählten Text zu erkennen, um das zu lösen, der dieses noch hässlicher macht.)

Kann jemand eine bessere Lösung zur Verfügung stellen?

+0

Wie würden Sie Einfügen behandeln, Undo/Redo, Drag & Drop oder andere Instanzen von mehreren Zeichen sein zur gleichen Zeit eingegeben oder ist das nicht wichtig? –

+0

Andy, das ist nicht sehr wichtig hier, aber wäre immer noch nützlich zu handhaben - ich denke, es würde erfordern, die Schnur manuell zu führen, innerhalb der Onchange-Event? –

+1

Oder die Ereignisse * oninput * und * onpropertychange *. Ich habe das vor kurzem in meinem Blog beschrieben - http://whatcheheadid.com/2010/09/effectively-detection-user-input-in-javascript und ich habe ein fast vollständiges jQuery-Plugin dafür in Arbeit. –

Antwort

17

Das folgende wird die Aufgabe erledigen. Es basiert auf an answer I wrote to another question. Passen Sie die transformTypedChar Funktion an Ihre Bedürfnisse an; Mein Beispiel kapitalisiert nur die Buchstaben a-g.

Wenn Sie dies auf einem Textarea statt <input type="text"> benötigen, dann beachten Sie, dass es Probleme gibt in IE < = 8 mit Zeilenumbrüchen, die der folgenden Code aus Gründen der Kürze nicht behandelt. Sie können hier in ein Textfeld die Cross-Browser-Funktion zum Erhalten der Auswahl: Is there an Internet Explorer approved substitute for selectionStart and selectionEnd?

function transformTypedChar(charStr) { 
    return /[a-g]/.test(charStr) ? charStr.toUpperCase() : charStr; 
} 

document.getElementById("your_input_id").onkeypress = function(evt) { 
    var val = this.value; 
    evt = evt || window.event; 

    // Ensure we only handle printable keys, excluding enter and space 
    var charCode = typeof evt.which == "number" ? evt.which : evt.keyCode; 
    if (charCode && charCode > 32) { 
     var keyChar = String.fromCharCode(charCode); 

     // Transform typed character 
     var mappedChar = transformTypedChar(keyChar); 

     var start, end; 
     if (typeof this.selectionStart == "number" && typeof this.selectionEnd == "number") { 
      // Non-IE browsers and IE 9 
      start = this.selectionStart; 
      end = this.selectionEnd; 
      this.value = val.slice(0, start) + mappedChar + val.slice(end); 

      // Move the caret 
      this.selectionStart = this.selectionEnd = start + 1; 
     } else if (document.selection && document.selection.createRange) { 
      // For IE up to version 8 
      var selectionRange = document.selection.createRange(); 
      var textInputRange = this.createTextRange(); 
      var precedingRange = this.createTextRange(); 
      var bookmark = selectionRange.getBookmark(); 
      textInputRange.moveToBookmark(bookmark); 
      precedingRange.setEndPoint("EndToStart", textInputRange); 
      start = precedingRange.text.length; 
      end = start + selectionRange.text.length; 

      this.value = val.slice(0, start) + mappedChar + val.slice(end); 
      start++; 

      // Move the caret 
      textInputRange = this.createTextRange(); 
      textInputRange.collapse(true); 
      textInputRange.move("character", start - (this.value.slice(0, start).split("\r\n").length - 1)); 
      textInputRange.select(); 
     } 

     return false; 
    } 
}; 
+0

Danke Tim, das sieht aus, als ob es auch das neue Textauswahlproblem behandelt, das ich gerade gefunden habe. Werde es ausprobieren und sehen, wie es geht. –

+0

OK. Ich habe gerade eine Notiz hinzugefügt, um dies mit Textareas zu verwenden. –

+1

+1 nette Antwort sehr schlau –

-1

Können Sie CSS verwenden?

<input type="text" style="text-transform: uppercase;" /> 
+2

Das ändert nicht den tatsächlichen Eingabewert und, was noch wichtiger ist, gilt nicht bedingt. –

+1

Können Sie einen Großbuchstaben eingeben, wenn Sie den übergebenen Wert verarbeiten? Was meinst du mit bedingt? –

+0

Ich habe die Frage geklärt, um zu verdeutlichen - ich möchte nur (vielleicht) das aktuelle Zeichen in Großbuchstaben schreiben, nicht die ganze Zeichenfolge - und wenn ich Großbuchstaben habe, hängt es von einer if-Bedingung ab (die genaue Prüfung ist für die Frage unwichtig). –

0

Nicht wirklich sicher, was Sie wollen, aber wird das funktionieren?

$('#my_element').keyup(function(){ $(this).val().toUpperCase(); }); 

oder eine Unterzeichenfolge verwenden, um das letzte Zeichen zu erhalten gedrückt und tun toUpperCase() auf das?

(psst ... Sie können auch Keydown oder Tastendruck verwenden).

+0

Auch dies ist nicht Bedingung, und die toUpperCase ist nicht wirklich eine Verbesserung gegenüber der String.fromCharCode() -Methode. –

+0

was meinst du mit bedingt? –

+0

Ich habe die Frage geklärt, um zu klären - ich möchte nur (vielleicht) Großbuchstaben das aktuelle Zeichen, nicht die ganze Zeichenfolge - und wenn ich Großbuchstaben es hängt von einer if-Bedingung (die genaue Prüfung ist unbedeutend für die Frage). –

1

Wie wäre es, die Standardaktion zu verhindern und dann den Tastendruck auszulösen? Etwas wie,

function onKeypressHandler(e) 
{ 
    if (condition) 
    { 
     e.preventDefault(); 
     // create new event object (you may clone current e) 
     var ne = new jQuery.Event("keypress"); 
     ne.which = e.which - 32; 
     $(e.target).trigger(ne); // you may have to invoke with setTimeout 
    } 
} 
+0

Funktioniert nicht. Sie können die Auswirkungen eines Tastendrucks im Browser nicht simulieren. –

+0

Doh! Das schien vielversprechend zu sein, bis ich Tims Kommentar sah. Nette Idee sowieso. :( –

+0

@Tim, danke für info. BTW, Beispiel von jquery docs verwendet .keypress() um das Ereignis auszulösen. Also, was passiert in diesem Fall - wird nur Event-Handler aufgerufen ohne Kontrolle Erhalt des Zeichens? – VinayC

1

Sie haben, dies zu sehen .. ich mit mir selbst ziemlich glücklich war, nachdem es immer zu arbeiten ..

Sie möchten natürlich genügend Kriterien einbeziehen, um hier nicht in eine Schleife zu geraten.

Der folgende Code gibt false zurück, wenn die Bedingung true ergibt, aber das gleiche Ereignis wird mit einem anderen charCode ausgelöst, der nicht false zurückgibt.

document.getElementById("input1").onkeypress = Handler; 
function Handler(e) 
{ 
    e = e || window.event; 
    if (e.charCode == 97) 
    { 
     var evt = document.createEvent("KeyboardEvent"); 
     evt.initKeyEvent("keypress",true, true, window, false, false,false, false, 0, e.charCode -32); 
     this.dispatchEvent(evt); 
     return false; 
    } 
    return true; 
} 

könnten Sie in IE verwenden fireevent ... I verwendet http://help.dottoro.com/ljrinokx.php und https://developer.mozilla.org/en/DOM/event.initKeyEvent Referenz

+0

Interessant. Dies funktioniert jedoch nur in Mozilla. Glücklicherweise scheint der Umfang begrenzt zu sein: Es ist nicht möglich, Tastaturkurzbefehle wie Strg-B (für Lesezeichen), Strg-A (alle auswählen) auszulösen. Ich wusste nicht, dass du so viel tun kannst. –

+0

nicht genau .. IE unterstützt auch feuern Ereignisse .. anstelle von dispatchEvent, verwenden Sie fireEvent und zum Erstellen des Ereignisses verwenden Sie object.createEventObject. Siehe http://help.dottoro.com/ljhlvomw.php. Ich bin auf Linux, kann also nicht mit dem Code/Testen helfen. Aber das scheint machbar –

+0

Scheint der Code für die Crossbrowser-Maus Ereignisbehandlung ist bereits in diesem Link zur Verfügung gestellt. –