2013-07-26 16 views
7

Trotz vieler Artikel über SO, wie man Tastenbetätigungen (keydown/keypress) in JS simuliert, scheint keine Lösung mit den Browsern zu funktionieren, die ich benutze (Firefox ESR 17.0. 7, Chrome 28.0.1500.72, IE 10). Die Lösungen, die ich getestet habe, wurden aus here, here und here entnommen.JavaScript: Schlüsselereignisse in Textbox/Eingabe simulieren

Was ich versuche zu tun ist, jeden Tastendruck in einem Textarea/Eingabe zu simulieren. Während ich Zeichen anfügen/löschen kann, die direkt "Wert" ändern, sehe ich keine Option, sondern Eingabesimulation für die Tasten wie "Auf", "Ab", "Home" und einige andere.

Nach der documentation sollte es einfach sein. Zum Beispiel:

var e = document.createEvent("KeyboardEvent"); 
if (e.initKeyboardEvent) { // Chrome, IE 
    e.initKeyboardEvent("keydown", true, true, document.defaultView, "Enter", 0, "", false, ""); 
} else { // FF 
    e.initKeyEvent("keydown", true, true, document.defaultView, false, false, false, false, 13, 0); 
} 
document.getElementById("text").dispatchEvent(e); 

tatsächlich löst das "Enter" -Keydown-Ereignis, und mein Handler kann es fangen. Es wirkt sich jedoch nicht auf das Textfeld aus - eine neue Zeile wird nicht angezeigt. Das Gleiche gilt für andere Tastencodes: Zeichen werden nicht angezeigt, Pfeile ändern nicht den Standort des Kästchens, usw.

Ich habe den Code um Orwellophile erweitert und auf http://jsfiddle.net/npF3d/4/ gestellt, damit jeder mit dem Code spielen kann. In meinen Browsern erzeugt keine Schaltfläche einen Effekt auf den Textbereich in irgendeiner Bedingung.

Ich würde jede Hilfe zu diesem Thema schätzen.

Antwort

6

Ich bin mir ziemlich sicher, dass dies eine "Sicherheit" Sache ist, wie ich in die gleiche Sache geraten bin, wenn ich versuche, Tastenbetätigungen vorher zu simulieren.

Frage: Wie kann ich dann programmatisch schreiben?
A: Erhalten/Setzen selection, selectionEnd, etc, sowie diese mit String Methoden wie slice in Kombination verwendet Zeichen einzufügen. (Siehe HTMLTextAreaElement Referenz)

F: Warum würden Sie diese Art von Ereignis dann immer noch verwenden?
A: Alle Ereignis-Listener funktionieren so, als wäre es ein echtes Schlüsselereignis.


Reduzierte Funktionalität für Pfeile/home/Ende kann thusly DEMO

function homeKey(elm) { 
    elm.selectionEnd = 
     elm.selectionStart = 
      elm.value.lastIndexOf(
       '\n', 
       elm.selectionEnd - 1 
      ) + 1; 
} 

function endKey(elm) { 
    var pos = elm.selectionEnd, 
     i = elm.value.indexOf('\n', pos); 
    if (i === -1) i = elm.value.length; 
    elm.selectionStart = elm.selectionEnd = i; 
} 

function arrowLeft(elm) { 
    elm.selectionStart = elm.selectionEnd -= 1; 
} 

function arrowRight(elm) { 
    elm.selectionStart = elm.selectionEnd += 1; 
} 

function arrowDown(elm) { 
    var pos = elm.selectionEnd, 
     prevLine = elm.value.lastIndexOf('\n', pos), 
     nextLine = elm.value.indexOf('\n', pos + 1); 
    if (nextLine === -1) return; 
    pos = pos - prevLine; 
    elm.selectionStart = elm.selectionEnd = nextLine + pos; 
} 

function arrowUp(elm) { 
    var pos = elm.selectionEnd, 
     prevLine = elm.value.lastIndexOf('\n', pos), 
     TwoBLine = elm.value.lastIndexOf('\n', prevLine - 1); 
    if (prevLine === -1) return; 
    pos = pos - prevLine; 
    elm.selectionStart = elm.selectionEnd = TwoBLine + pos; 
} 

Q erreicht werden: Wo es schief geht?
A: Wenn die Zeilen lang genug sind, um sie zu umhüllen, werden sie so behandelt, als wären sie nicht ausgepackt.

+0

OK erreichen, ich hatte das gleiche Gefühl, dass dies absichtlich aus Sicherheitsgründen getan werden könnte. Ab Q/A: Text zu bearbeiten ist kein Problem, das Problem ist, "Up", "Down", "Home" und dergleichen zu simulieren ... – lexasss

+0

diese könnten möglicherweise implementiert werden, wenn Sie das Textfeld neu erstellen/Eingabe als ein Blockknoten, der Inline-Knoten für jedes Zeichen mit passendem Wrapping, Größe und Styling enthält, und dann Berechnung aller verschiedenen Rects, um zu finden, wo du enden willst. Ich kann mir nicht vorstellen, dass es einfach zu implementieren ist ... vielleicht wäre eine sauberere Methode, eine Monospace-Schriftart zu verwenden, herauszufinden, wo der vorherige neue Zeilen-Charakter war und dann einfach die Zeichen zählen. –

+0

Danke. Allerdings simuliere ich die Eingabe auf dritten Seiten, wie google.com. Meine virtuelle Tastatur ist als Chrome-Erweiterung implementiert und muss Benutzern ermöglichen, Text in Formularen auf jeder Seite mit nur dieser Tastatur einzugeben und zu ändern. Es wäre eine große Enttäuschung, wenn einige Funktionen fallengelassen werden müssten. – lexasss

0

Senden Schlüssel an den Browser über Selen erreicht werden: http://docs.seleniumhq.org/

Es bietet einen Treiber für jeden Browser, der programmiert werden kann. Normalerweise beginnt es mit dem Öffnen einer URL, dann fungiert das Skript als Fernbedienung für den Browser. Dadurch können Sie die tatsächlichen Schlüssel senden, anstatt sie zu simulieren, was im Browser nicht programmatisch möglich ist.

Sie zum Beispiel könnte dies mit http://webdriver.io/