|
In HTML erstellen Sie Formulare nach einem einfachen Rezept: Man nehme ein
<form>-Tag; füge nach Geschmack User-Eingabetags hinzu; backe
das Ganze eine Stunde lang bei 350 Grad, serviere und genieße.
In Flash geht das traditionell nicht ganz so einfach. Zwar hat die
Veröffentlichung der Flash
UI-Komponenten für Flash MX das Ganze spürbar vereinfacht, aber das Absenden
von Formularen ist und bleibt dennoch in Flash kniffliger als in HTML. In HTML
können Sie Formulare über einen Submit-Button oder "automagisch" über die
Eingabetaste absenden. Da Flash hingegen keine integrierte Unterstützung für das
Versenden mittels Eingabetaste bietet, müssen Sie diese manuell implementieren.
Und genau dies wird im Rest dieses Artikels erklärt. Den Quellcode können Sie
von dieser URL herunterladen.
Flash-Formulare bestehen normalerweise aus einer Ansammlung von User
Interface (UI)-Komponenten. Um ein Formular an ein Skript oder Programm auf der
Serverseite zu "übermitteln", müssen Sie den Wert jeder Komponente manuell in
ein LoadVars- oder XML-Objekt speichern und dann die sendAndLoad()-
oder send()-Methode dieses Objekts aufrufen.
Diese Schritte übernimmt normalerweise eine selbst programmierte Funktion
oder Methode. Nehmen Sie als Beispiel ein einfaches Anmeldeformular mit einem
Textfeld für den Usernamen, einem Textfeld für das Passwort und einem
Submit-Button. Die Textfelder sind einzeilige Eingabetextfelder und haben die
Instanznamen username_txt und password_txt. Der Submit-Button ist ein
FPushButton-Objekt namens submit_pb. Für die
Formularübermittlung dient eine benutzerdefinierte
submitForm()-Funktion. Der Code auf der Zeitleiste des Formulars
sieht folgendermaßen aus: // Erstellung des Datenübermittlungsobjekts.
// Der Einfachheit halber wird davon ausgegangen, dass die
// Ergebnisse der Anmeldung als Webseite im Browser
// dargestellt werden, also nicht in Flash.
var sender = new LoadVars();
// Benutzerdefinierte Funktion zur Formularübermittlung.
function submitForm () {
// Sammele Textfeldwerte im LoadVars-Objekt.
sender.user = username_txt.text;
sender.pass = password_txt.text;
// Übertrage Daten an das Skript auf der Serverseite.
sender.send("http://www.somesite.com/cgi-bin/login.pl", "_blank", "GET");
}
Damit der Submit-Button (submit_pb) beim Anklicken die Methode
submitForm() aufruft, verwenden Sie die Methode
setClickHandler() der Komponente FPushButton wie
folgt: // Dieser Code muss mit einem Bild auf derselben
// Zeitleiste wie die obige submitForm()-Funktion verknüpft sein.
submit_pb.setClickHandler("submitForm");
Und nun kommt der schwierige Teil: Beim Drücken der Eingabetaste soll
submitForm() aufgerufen werden, allerdings nur, wenn eines der
Textfelder im Formular den Fokus hat. Zur Behandlung der Eingabetaste werden der
Klasse TextField weitere benutzerdefinierte Methoden hinzugefügt.
Als Erstes entwickeln wir eine neue Methode namens onKeyDown(), die
nachschaut, ob die Eingabetaste gedrückt wird. Nun kann sich jede
TextField-Instanz registrieren lassen, um vom integrierten
Key-Objekt Benachrichtigungen über Tastendruck-Events zu empfangen. TextField.prototype.onKeyDown = function () {
if (Key.getCode() == Key.ENTER) {
// Eingabetaste wurde gedrückt.
}
};
Die neue Methode macht jedoch Probleme: Wenn der User die Eingabetaste
gedrückt hält, sendet sie gleich mehrere Tastendruck-Events. Da aber nur der
erste Tastendruck von Interesse ist, wird die Methode onKeyDown()
jetzt so abgeändert, dass sie alle Eingabetasten-Events außer dem ersten
verwirft. Sie bekommt die Eigenschaft pressedOnce, die das erste
Drücken der Eingabetaste registriert, und die neue Methode
onKeyUp(), mit der die Eigenschaft pressedOnce
zurückgesetzt wird, wenn die Eingabetaste losgelassen wird.
TextField.prototype.onKeyDown = function () {
if (Key.getCode() == Key.ENTER && this.pressedOnce == undefined) {
// Notiere das Drücken der Eingabetaste. Dann brauchen wir uns
// bei der nächsten onKeyDown-Event-Benachrichtigung nicht mehr
// darum zu kümmern.
this.pressedOnce = true;
}
};
TextField.prototype.onKeyUp = function () {
// Wenn die Eingabetaste losgelassen wird,
// wird die Eigenschaft pressedOnce zurückgesetzt.
if (Key.getCode() == Key.ENTER) {
this.pressedOnce = undefined;
}
}
Es reicht aber nicht aus, lediglich zu entdecken, dass die Eingabetaste
gedrückt wurde. Denn das Drücken der Eingabetaste ist nur dann von Belang, wenn
gleichzeitig ein Textfeld im Formular den Fokus hat. Also benötigt die Klasse
TextField zusätzlich die Methode isFocused(), um
festzustellen, ob ein Textfeld den Eingabefokus hat. In ActionScript sagt Ihnen
die Methode getFocus() des Selection-Objekts, welches
Element gerade den Fokus hat.
TextField.prototype.isFocused = function () {
// ('this' ist die aktuelle Textfeld-Instanz.)
if (Selection.getFocus() == targetPath(this)) {
return true;
}
return false;
};
Beachten Sie, dass die Methode Selection.getFocus() den Pfad zu
dem fokussierten Objekt als String statt als Objektreferenz liefert. Daher
müssen Sie zunächst entweder den Rückgabewert von getFocus() mit
eval() in ein Objekt umwandeln, oder mit targetPath()
den vollständigen Pfad zu dem Textfeld abfragen. Erst dann können Sie den Wert
mit dem aktuellen Textfeld vergleichen. In unserer benutzerdefinierten
isFocused()-Methode wird targetPath() verwendet.
Nun, da die Methode isFocused() fertig ist, muss die Methode
onKeyDown() ein letztes Mal angepasst werden, damit sie erkennen
kann, dass die Eingabetaste gedrückt wird, und das Textfeld, das diesen
Tastendruck registriert hat, gleichzeitig den Fokus hat. Wenn diese Bedingungen
beide erfüllt sind, wird direkt auf dem Textfeld eine benutzerdefinierte
onSubmit()-Methode aufgerufen. Die Implementierung dieser Methode
muss der Formularentwickler allerdings selbst liefern.
TextField.prototype.onKeyDown = function () {
if (Key.getCode() == Key.ENTER
&& this.pressedOnce == undefined
&& this.isFocused()) {
this.onSubmit();
this.pressedOnce = true;
}
};
TextField.prototype.onKeyUp = function () {
if (Key.getCode() == Key.ENTER) {
this.pressedOnce = undefined;
}
}
So werden TextField-Eingaben behandelt. Die Textfelder des
Formulars sind jetzt in der Lage, auf das Drücken der Eingabetaste zu reagieren.
Nun müssen die Textfelder nur noch mit der Funktion submitForm()
verbunden und für den Empfang von Key-Events registriert werden:
// Verbinde Textfeld mit submitForm().
username_txt.onSubmit = submitForm;
// Registriere Textfeld für den Empfang von Key-Events.
Key.addListener(username_txt);
// Verbinde...
password_txt.onSubmit = submitForm;
// Registriere...
Key.addListener(password_txt);
Das ist alles. Jetzt wird das Formular abgeschickt, wenn in den Textfeldern
für den Usernamen und das Passwort die Eingabetaste gedrückt wird. Die
Endfassung des Codes sieht folgendermaßen aus:
// ===============================================
// Erweiterte TextField-Klasse
// ===============================================
TextField.prototype.onKeyDown = function () {
if (Key.getCode() == Key.ENTER
&& this.pressedOnce == undefined
&& this.isFocused()) {
this.onSubmit();
this.pressedOnce = true;
}
};
TextField.prototype.onKeyUp = function () {
if (Key.getCode() == Key.ENTER) {
this.pressedOnce = undefined;
}
}
TextField.prototype.isFocused = function () {
if (Selection.getFocus() == targetPath(this)) {
return true;
}
return false;
};
// ===============================================
// Formularimplementierung
// ===============================================
// Erstelle das Datenübermittlungsobjekt.
var sender = new LoadVars();
// Aktiviere Eingabetaste für Textfelder.
username_txt.onSubmit = submitForm;
Key.addListener(username_txt);
password_txt.onSubmit = submitForm;
Key.addListener(password_txt);
// Richte Handler für den Submit-Button ein.
submit_pb.setClickHandler("submitForm");
// Benutzerdefinierte Funktion für die Formularübermittlung.
function submitForm () {
sender.user = username_txt.text;
sender.pass = password_txt.text;
sender.send("http://www.somesite.com/cgi-bin/login.pl", "_blank", "GET");
}
Zum Abschluss
Einige verwandte Themen verdienen es, besonders erwähnt zu werden.
Die Eingabetaste im Zusammenspiel mit anderen Komponenten
Der obige Artikel stellt die Formularübermittlung per Eingabetaste aus einem
Textfeld in den Mittelpunkt, doch Formulare bergen häufig auch noch andere
UI-Komponenten wie beispielsweise Listenfelder und Optionsfelder. Um die
Eingabetaste auch für diese Komponenten zu aktivieren, müssen Sie der Komponente
entweder Handler-Methoden für Tastendrücke und Fokus hinzufügen, wie es im
voliegenden Fall bei TextField getan wurde, oder eine zentrale
Strategie zur Behandlung von Tastendrücken, wobei ein einzelnes Objekt
Tastendrücke erkennt und dann die Komponenten im Formular durchläuft, um zu
ermitteln, ob das Formular übermittelt werden soll. Doch wenn es derart komplex
wird, dann könnten Sie auch gleich eine eigene Formularklasse kreieren.
Validierung
Formulareingabe sollte in Flash vor der Übermittlung an ein serverseitiges
Skript oder Programm grundsätzlich validiert werden. Ebenso wie die
Formularübertragung sollte auch die Validierung in eine Funktion oder Methode
gepackt werden. Das Formular könnte beispielsweise eine
validateForm()-Funktion haben, die bei gültigen Daten true und bei
ungültigen false zurückgibt. Die submitForm()-Funktion könnte
folgendermaßen umgeschrieben werden:
function submitForm () {
if (validateForm()) {
sender.user = username_txt.text;
sender.pass = password_txt.text;
sender.send("http://www.somesite.com/cgi-bin/login.pl", "_blank", "GET");
} else {
// User-Feedback...
}
}
Guter OOP-Stil
In einer streng objektorientierten Sprache wie Java würde es nicht
funktionieren, der integrierten Klasse TextField benutzerdefinierte
Funktionen hinzuzufügen, wie es oben beschrieben wird. In Java können Sie einer
eingebauten Klasse nicht einfach für einzelne Programme nach Belieben neue
Funktionen beigeben. Da im obigen Beispiel eine spezielle Art von Textfeld
benötigt wird, wäre es besser gewesen, eine Unterklasse von
TextField zu bilden und die neuen Methoden dieser Unterklasse
hinzuzufügen. Doch leider ist es nicht möglich, von TextField
direkt in ActionScript eine Unterklasse zu erstellen, da alle Werkzeuge zur
Textfelderstellung ihrerseits die Klasse TextField für diesen
Erstellungsprozess benutzen. Es gibt keine Möglichkeit, etwa die Methode
MovieClip.createTextField() zu veranlassen, eine neue
Textfeldinstanz statt aus TextField aus einer anderen,
benutzerdefinierten Klasse zu erzeugen. Wer sich scheut, eingebauten Klassen
neue Methoden hinzuzufügen, kann ein Textfeld in eine Komponente hüllen und die
neuen Methoden dann dieser Komponentenklasse statt der
TextField-Klasse selbst beigeben.
Mehrzeilige Textfelder
Im obigen Formularbeispiel ging es um einzeilige Eingabetextfelder.
Informationen über die Behandlung der Eingabetaste in mehrzeiligen Textfeldern
finden Sie in der Technote zu diesem Thema unter moock.org.
Weitere bei O'Reilly erschienene Veröffentlichungen zu ActionScript für Flash MX :
|