200904Nov

jQuery-Tutorial: Interaktionen mit Events steuern

Interaktionen stellen wahrscheinlich den wichtigsten Aspekt eines JavaScript-Frameworks dar. Die Bedienung einer Website oder Webanwendung kann durch den Einsatz von jQuery wesentlich verbessert und moderner gestaltet werden. Die JavaScript-Bibliothek bietet etliche Möglichkeiten, um Maus- und Tastatur-Ereignisse zu verarbeiten. In diesem Tutorial will ich auf die allgemeinen Event-Funktionen von jQuery eingehen, mit denen sich schnell dynamische Bedienelemente realisieren lassen.
Basis für diesen Workshop bildet der folgende HTML-Code, der wie gehabt in JS Bin eingefügt und bearbeitet werden kann:

  • Quelltext
  • <body>
  • <a href="#" id="link1">Text1</a>
  • <a href="#" id="link2">Text2</a>
  • <a href="#" id="link3">Text3</a>
  • <input type="text" id="input1" />
  • <input type="text" id="input2" />
  • <input type="text" id="input3" />
  • </body>

Die CSS-Anpassungen nehme ich wieder mit jQuery vor:

  • Quelltext
  • $("a").css({
  • "width": "200px",
  • "height": "200px",
  • "margin": "5px",
  • "color": "white",
  • "background": "blue",
  • "float": "left"
  • });
  •  
  • $("input").css({
  • "margin": "5px",
  • "float": "left",
  • "clear": "both"
  • });

Der weitere JavaScript-Code dieses Tutorials sollte dann an den oben stehenden Code angefügt werden.
An dieser Stelle gibt es etwas zu beachten: Die Zuweisung der Attribute background und color überschreibt alle Farbwerte, die vorher in CSS definiert wurden — dazu zählen auch folgende Farben:

  • a:hover {
  • color: #654321;
  • background: #123456;
  • }

Bei Links existiert bereits ein HTML-Event (hover), das durch entsprechende jQuery-Deklarationen überschrieben wird. Dieser Effekt kann gewünscht sein oder auch nicht. Wir werden dieses Verhalten später reproduzieren.

Bevor wir mit dem Erstellen erster Beispiele beginnen, gibt es noch ein paar Dinge, die man über Events (also Ereignisse) wissen sollte:

  • bestimmte DOM-Elemente (a, input) sind von vornherein mit Events belegt (hover, Ankersprung, Zeichenausgabe, etc.)
  • jedes Event in jQuery hat verschiedene Eigenschaften (type, target, usw.)
  • Events an sich führen noch nichts aus, weshalb sie an eine Funktion (function) gekoppelt werden müssen
  • innerhalb einer Event-Funktion kann anschließend this verwendet werden, um das referenzierende Objekt anzusprechen
  • einem DOM-Element können mehrere Events zugewiesen werden
  • jedes DOM-Element kann mit Events verknüpft werden

Zur Verdeutlichung hier das Grundkonstrukt einer an ein Event (click) gebundene Funktion:

  • $("element").click(function(){
  • // Code
  • });

Ich will daher mit einem einfachen Beispiel anfangen, das mit einem Problem verknüpft ist, welches vielen Einsteigern über den Weg laufen dürfte. Zum Ausprobieren kann dieser Code in JS Bin eingefügt werden, der bei einem Klick auf das Link-Element mit der ID "link1" eine Nachricht (alert) anzeigt.

  • Quelltext
  • $("#link1").click(function(){
  • alert("Nachricht");
  • });

Was passiert: Zuerst wird die JavaScript-Anweisung "alert" ausgeführt, woraufhin das Standard-Event des Links folgt — in unserem Fall verweisen die Links auf einen unbenannten Anker, also ein Rautezeichen (#). Ein unbenannter bzw. undefinierter Anker weist den Browser an, zum Anfang einer Seite (oberer Rand) zu scrollen. In JS Bin führt das dazu, dass die Seite "in sich selbst", also in dem iframe angezeigt wird. Mit einem Klick auf die "Zurück"-Schaltfläche des Browsers gelangt man wieder zum Code-Fenster von JS Bin.
Nichtsdestotrotz ist dieses Verhalten in der Regel ungewollt, da beim Klick auf ein interaktives Element die aktuelle Scroll-Position beibehalten werden soll. Aus diesem Grund muss das zugewiesene Standard-Event des Links (ein Ankersprung) unterdrückt werden. In jQuery gibt es dazu die vordefinierte Funktion preventDefault(), die dazu verwendet werden sollte. Die Funktion benötigt jedoch das eigentliche Event als Konstruktor, welches über einen Parameter ausgewertet werden kann. Mit diesem Code werden beispielsweise Event-Objekt und Event-Typ des verknüpften DOM-Elements ausgegeben:

  • Quelltext
  • $("#link1").click(function(event){
  • alert(event + " " + event.type);
  • });

Entscheidend für die preventDefault()-Funktion ist der Parameter "event", der optional ist und nur für bestimmte Zwecke benötigt wird. In unserem Fall lässt sich damit der Ankersprung vermeiden, so dass das folgedene Code-Snippet lediglich eine Nachricht anzeigt:

  • Quelltext
  • $("#link1").click(function(event){
  • alert(event + " " + event.type);
  • event.preventDefault();
  • });

Neben dem click-Event gibt es natürlich noch eine Reihe weiterer Events, die an DOM-Elemente gebunden werden können. So zählen vor allem Maus-Events zu den beliebtesten Interaktionen — in diesem Zusammenhang werden wir ein hover-Verhalten simulieren, da wie oben erwähnt die CSS-Zuweisungen des Pseudo-Elements ":hover" durch jQuery aufgehoben werden. Ein Beispiel könnte etwa so aussehen:

  • Quelltext
  • $("a").hover(
  • function(){
  • $(this).css("background", "red");
  • },
  • function(){
  • $(this).css("background", "blue");
  • }
  • );

Wie man sieht, bietet jQuery mit der "hover()"-Funktion eine tolle Hilfsfunktion, mit der sich jQuery-Code bei einem "over"- und einem "out"-Status ausführen lässt (mehr darüber in der jQuery-Dokumentation). Im obigen Beispiel wird bei dem "over"-Ereignis die Hintergrundfarbe auf "rot" gesetzt, während das "out"-Ereignis (Mauszeiger verlässt Element) die Farbe wieder auf "blau" setzt. Alternativ können auch folgende Maus-Events verwendet werden:

  • Quelltext
  • $("a")
  • .mouseover(function(){
  • $(this).css("background", "red");
  • })
  • .mouseout(function(){
  • $(this).css("background", "blue");
  • });

Hier werden die beiden Events "mouseover()" und "mouseout()" aneinander gehängt (Chaining). Wichtig beim Chaining ist das Weglassen der Semikolons (hier in Zeile 4), da die Funktionen nacheinander ausgeführt werden sollen und ein Semikolon eine Anweisung beendet. Wer zudem mit verschachtelten Elementen bzw. Links arbeitet, sollte auf "mouseenter()" und "mouseleave()" zurückgreifen. Der Unterschied wird sehr gut in der offiziellen jQuery-Dokumentation erklärt.

Weiterhin lassen sich in jQuery mittels "bind()" mehrere Events an ein DOM-Objekt koppeln. Die Events müssen dann durch eine Leerstelle aufgelistet werden. Um das eben erstellte Beispiel mit der "bind()"-Funktion zu reproduzieren, könnte der Code so aussehen:

  • Quelltext
  • $("a").bind("mouseover mouseout", function(event){
  • if (event.type == "mouseover") {
  • $(this).css("background", "red");
  • } else {
  • $(this).css("background", "blue");
  • }
  • });

Das Gegenstück zu "bind()" stellt "unbind()" dar — damit lassen sich zugewiesene Events wieder von DOM-Elementen entfernen. Hier können auch Events wieder aufgehoben werden, die nicht mit der "bind()"-Funktion deklariert wurden. Das folgende Snippet vervollständigt unser kleines Beispiel mit einem "click()"-Event, das die "unbind()"-Funktion enthält:

  • Quelltext
  • $("a")
  • .mouseover(function(){
  • $(this).css("background", "red");
  • })
  • .mouseout(function(){
  • $(this).css("background", "blue");
  • })
  • .click(function(event){
  • $(this)
  • .html("Deaktiviert")
  • .css("background", "grey")
  • .unbind("mouseover mouseout");
  • event.preventDefault();
  • });

Bei einem Klick auf einen Link wird also der Text des Elements auf "Deaktiviert" gesetzt und die Hintergrundfarbe wird auf "grau" eingestellt. Durch die Verwendung von "unbind()" werden die beiden Events "mouseover" und "mouseout" folglich ignoriert.

Ein weiterer Verwendungszweck für Events stellen Eingabefelder (input) dar. Hier können beispielsweise Einfärbungen oder Überprüfungen von Eingabewerten erfolgen. Ein kleines Beispiel demonstriert Farbänderungen bei den Events "focus" und "blur", welche als Standard-Ereignisse von input-Feldern definiert sind:

  • Quelltext
  • $("input")
  • .focus(function(){
  • $(this).css("background", "yellow");
  • })
  • .blur(function(){
  • $(this).css("background", "white");
  • });

Erhält also ein input-Feld den Fokus, wird es gelb eingefärbt. Für Formulare wäre dies also eine Möglichkeit, um die Benutzerfreundlichkeit zu erhöhen (sofern der Browser die ":focus"-Pseudo-Klasse nicht unterstützt).

Schließlich bietet jQuery noch tolle Möglichkeiten zur Abfrage von Tastatur-Ereignissen. Bei diesen Events spielen die sogenannten "Keycodes" eine Rolle: Jede Taste auf der Computertastatur kann mithilfe einer definierten Zahl abgefragt werden. Eine Liste aller verfügbaren Keycodes gibt es beispielsweise auf dieser Seite. In Verbindung mit dem "keydown()"-Event können in jQuery also auch Tasten zur Bedienung einer Website verwendet werden. Hier ein Beispiel zum Testen, welches es ermöglicht, durch die input-Felder mit den beiden Pfeiltasten "nach oben" und "nach unten" zu navigieren.

  • Quelltext
  • $("input")
  • .focus(function(){
  • aktiv = $("input").index(this);
  • $(this).css("background", "yellow");
  • })
  • .blur(function(){
  • $(this).css("background", "white");
  • });
  •  
  • $(window).keydown(function(event){
  • letzterInput = $("input").length - 1;
  • switch (event.keyCode) {
  • case 40: // "Pfeil nach unten"-Taste
  • if (aktiv == letzterInput) {
  • $("input:eq(" + aktiv + ")").blur();
  • $("input:eq(0)").focus();
  • } else {
  • $("input:eq(" + aktiv + ")").blur();
  • $("input:eq(" + (aktiv + 1) + ")").focus();
  • }
  • break;
  •  
  • case 38: // "Pfeil nach oben"-Taste
  • if (aktiv == 0) {
  • $("input:eq(" + aktiv + ")").blur();
  • $("input:eq(" + letzterInput + ")").focus();
  • } else {
  • $("input:eq(" + aktiv + ")").blur();
  • $("input:eq(" + (aktiv - 1) + ")").focus();
  • }
  • break;
  • }
  • });

Die "aktiv"-Variable repräsentiert die Index-Nummer des aktiven input-Feldes. Betätigt der Benutzer eine der beiden deklarierten Tasten, wird mit dem "eq()"-Filter der Fokus auf das entsprechende Eingabefeld gelegt. Weiterhin kann man hier sehen, wie Variablen in jQuery als Selektoren verwendet werden können (Maskierung durch Anführungszeichen).

Zu guter Letzt ist noch die "trigger()"-Funktion erwähnenswert: Damit lassen sich Events untereinander verknüpfen. Sobald also ein Event bei einem DOM-Element ausgelöst wurde, kann zusätzlich die Event-Funktion eines anderen Elements ausgeführt werden. Das sieht in der Praxis etwa so aus (der Code des vorherigen Beispiels kann entfernt werden):

  • Quelltext
  • $("#link1").click(function(){
  • $("#link3").after("<span>Test1</span>");
  • });
  •  
  • $("#link2").click(function(){
  • $("#link3").after("<span style='color:red;'>Test2</span>");
  • $("#link1").trigger("click");
  • });
  •  
  • $("#link3").click(function(){
  • $("body > span").each(function(){
  • $(this).remove();
  • });
  • });
  •  
  • $("#link1, #link2, #link3").bind("click", function(event){
  • event.preventDefault();
  • });

Hier wurden nun mehrere Funktionalitäten demonstriert: Die "trigger()"-Funktion in Zeile 7 führt bei einem Klick auf den Link mit der ID "link2" das "click"-Event von "link1" aus. Somit werden die beiden span-Elemente mit "Test1" und "Test2" erzeugt.
In Zeile 11 wurde die "each()"-Funktion verwendet, die auf jedes span-Element (Kind-Element) des body-Bereichs angewendet wird und das jeweilige Element entfernt. Somit werden beim Klick auf den Link "link3" alle span-Elemente aus der DOM-Struktur gelöscht.
Zeile 16 zeigt noch einmal, dass die "bind()"-Funktion auch bei einer Aufzählung von Elementen (Grouping) funktioniert — allen drei Links wird nachträglich "preventDefault()" zugeteilt, so dass der Ankersprung unterdrückt wird.

Mit Events lassen sich also komplette Benutzeroberflächen programmieren und Interaktionen sehr genau steuern. In Verbindung mit Animationen lassen sich so optisch ansprechende Ereignisse erzielen. Mehr über Effekte gibt es im nächsten Tutorial.