Eventhandler stellen benötigte Daten bereit

Problem

Sie wollen, dass andere Plugins (oder einfach irgendwelcher jQuery-Code) aufgerufen werden können und bestimmte Variablen verändern, bevor Sie die eigentliche Aufgabe angehen.

Lösung

Nutzen Sie Events, um andere Skripten über die Aktion zu informieren, die durchgeführt werden soll.

Es ist möglich, Daten von den »aufgerufenen« Eventhandlern zu erhalten.

Wenn keine angegeben werden, können Sie eigene Standard-Optionen angeben.

Der Weg zur Lösung ist abhängig von der verwendeten jQuery-Version.

Diskussion

Wie kann man das mit jQuery 1.3 und höher machen?

Seit jQuery 1.3 lässt sich dies durch jQuery.Event leichter erledigen. Der alte Weg funktioniert immer noch für triggerHandler(), aber nicht für jQuery.trigger().

Für den folgenden Code müssen wir ein jQuery.Event erzeugen:

var e = jQuery.Event('updateName');

Um jetzt die Handler aufzurufen und den Wert zu erhalten, übergeben wir das Event-Objekt an trigger() und holen uns danach die Daten:

jQuery('#element').trigger(e);
 alert( e.result ); // Charles

Wie schon zu Beginn gesagt funktioniert das nicht so toll, wenn man viele Handler gebunden hat – dann ist das Ganze oft etwas unzuverlässig und fragil.

Wie können wir also zwischen den Eventhandlern und der auslösenden Funktion kommunizieren?

Nun, über das Event-Objekt, das wir übergeben.

Das an trigger() übergebene Objekt jQuery.Event ist das gleiche, das jeder Handler als erstes Argument erhält.

Wir können also wie folgt vorgehen:

jQuery('#name').bind('updateName', function(e){
    e.name = this.value;
 });

 var e = jQuery.Event('updateName');
 jQuery('#name').trigger(e);
 alert( e.name );

Das Beispiel unterscheidet sich nicht sehr von einer einfachen Zuweisung an e.result, aber was ist bei mehreren Eventhandlern, die mit dem gleichen Event-Objekt arbeiten?

jQuery('#first').bind('update', function(e){
    e.firstName = this.value;
 });
 jQuery('#last').bind('update', function(e){
    e.lastName = this.value;
 });

 var e = jQuery.Event('update');
 jQuery('#first, #last').trigger(e);
 alert( e.firstName );
 alert( e.lastName );

Wir haben also eine Möglichkeit, eine beliebige Zahl von Eventhandlern zu nutzen, um die erforderlichen Informationen für eine Funktion zusammenzustellen. Sie können natürlich trigger() mehrfach aufrufen und dabei immer das gleiche Event-Objekt mitgeben.

Wie schon gesagt ist es sinnvoll, das Event-Objekt mit Standardwerten vorzubelegen (wenn es passende gibt). Ihr Code sollte sich nicht darauf verlassen, dass andere sich für ein bestimmtes Event registriert haben.

Können keine Standardwerte genutzt werden, dann können Sie immer noch den Aufruf abbrechen oder einen Fehler werfen.

Vorgehen vor jQuery 1.3

Bei älteren Versionen von jQuery konnte der Anwender nur einen einzelnen Wert erhalten, der beim Aufruf von jQuery.trigger() und/oder triggerHandler() zurückgegeben wurde.

Das ganze sah dann in etwa so aus:

jQuery('#element').bind('updateName', function(){
    return 'Charles';
 });

 var name = jQuery('#element').triggerHandler('updateName');
 alert( name ); // Charles

Das war ausreichend, wenn Sie nicht mehr als einen Eventhandler hatten, der Daten zurückgab. Bei mehreren Handlern entschied der letzte der aufgerufenen Handler, welche Daten zurückgegeben wurden.

Eventhandler können Aktionen verhindern

Dies ist noch eine Spezialisierung dessen, was wir schon gesehen haben. Event-Objekte haben immer eine Methode namens preventDefault() . Diese Methode wird für die eingebauten Events genutzt, um die normalen Aktionen zu unterbinden, wie zum Beispiel beim Klicken auf einen Link. Bei eigenen Events gibt es aber hierfür keine sinnvolle Anwendung.

Wir können daraus einen Vorteil ziehen und diese Methode nutzen, um es anderen Skripten zu erlauben, Aktionen zu verhinden, die ausgeführt werden sollten.

Ich werde Ihnen ein Beispiel dafür zeigen und das in Das globale Auslösen von Events beschleunigen vorgestellte Mini-Plugin nutzen, was für die Anwendung dieser Methode allerdings keine Voraussetzung ist:

var remote = jQuery.listener({
     request:function( url, callback ){
        jQuery.ajax({ url:url, success:callback });
     }
 });

 // Anforderung abschicken
 remote.request('contact.html', function( html ){
     alert( html );
 });

Stellen Sie sich jetzt vor, dass wir es einem externen Skript erlauben wollen, bestimmte Anforderungen bei Bedarf abbrechen zu können. Dazu müssen wir remote.request wie folgt anpassen:

var remote = jQuery.listener({
     request:function( url, callback ){
        var e = jQuery.Event('beforeRequest');
        e.url = url;
        this.trigger(e);

        if( !e.isDefaultPrevented() )
            jQuery.ajax({ url:url, success:callback });
     }
 });

e.isDefaultPrevented() gibt zurück, ob e.preventDefault() für dieses Objekt aufgerufen wurde.

Ein externes Skript kann nun Folgendes tun:

remote.bind('beforeRequest', function(e){
    if( e.url == 'contact.html' )
        e.preventDefault();
 });

Durch die Rückgabe von false (innerhalb der Funktion) erzielt man nahezu den gleichen Effekt wie beim Aufruf von e.preventDefault(). Auch damit wird die Weiterverteilung des Events abgebrochen, was durchaus erwünscht sein kann.

In solchen Situationen kann man natürlich auch ein Anpassen der URL (oder der Post-Daten, wenn es welche gibt) durch Handler zulassen.

JQuery Kochbuch
titlepage.xhtml
part0000.html
part0001.html
part0002_split_000.html
part0002_split_001.html
part0002_split_002.html
part0003_split_000.html
part0003_split_001.html
part0003_split_002.html
part0003_split_003.html
part0003_split_004.html
part0003_split_005.html
part0003_split_006.html
part0003_split_007.html
part0004_split_000.html
part0004_split_001.html
part0004_split_002.html
part0004_split_003.html
part0004_split_004.html
part0004_split_005.html
part0004_split_006.html
part0004_split_007.html
part0004_split_008.html
part0004_split_009.html
part0004_split_010.html
part0004_split_011.html
part0004_split_012.html
part0004_split_013.html
part0004_split_014.html
part0004_split_015.html
part0004_split_016.html
part0004_split_017.html
part0004_split_018.html
part0005_split_000.html
part0005_split_001.html
part0005_split_002.html
part0005_split_003.html
part0005_split_004.html
part0005_split_005.html
part0005_split_006.html
part0005_split_007.html
part0005_split_008.html
part0005_split_009.html
part0005_split_010.html
part0005_split_011.html
part0005_split_012.html
part0005_split_013.html
part0006_split_000.html
part0006_split_001.html
part0006_split_002.html
part0006_split_003.html
part0006_split_004.html
part0006_split_005.html
part0006_split_006.html
part0006_split_007.html
part0006_split_008.html
part0006_split_009.html
part0006_split_010.html
part0007_split_000.html
part0007_split_001.html
part0007_split_002.html
part0007_split_003.html
part0007_split_004.html
part0007_split_005.html
part0007_split_006.html
part0007_split_007.html
part0007_split_008.html
part0007_split_009.html
part0007_split_010.html
part0007_split_011.html
part0008_split_000.html
part0008_split_001.html
part0008_split_002.html
part0008_split_003.html
part0008_split_004.html
part0008_split_005.html
part0008_split_006.html
part0008_split_007.html
part0008_split_008.html
part0008_split_009.html
part0008_split_010.html
part0008_split_011.html
part0008_split_012.html
part0008_split_013.html
part0008_split_014.html
part0008_split_015.html
part0008_split_016.html
part0008_split_017.html
part0008_split_018.html
part0008_split_019.html
part0008_split_020.html
part0008_split_021.html
part0008_split_022.html
part0009_split_000.html
part0009_split_001.html
part0009_split_002.html
part0009_split_003.html
part0009_split_004.html
part0009_split_005.html
part0009_split_006.html
part0009_split_007.html
part0009_split_008.html
part0009_split_009.html
part0009_split_010.html
part0010_split_000.html
part0010_split_001.html
part0010_split_002.html
part0010_split_003.html
part0010_split_004.html
part0010_split_005.html
part0010_split_006.html
part0010_split_007.html
part0010_split_008.html
part0010_split_009.html
part0010_split_010.html
part0010_split_011.html
part0011_split_000.html
part0011_split_001.html
part0011_split_002.html
part0011_split_003.html
part0011_split_004.html
part0011_split_005.html
part0011_split_006.html
part0011_split_007.html
part0011_split_008.html
part0011_split_009.html
part0011_split_010.html
part0011_split_011.html
part0012_split_000.html
part0012_split_001.html
part0012_split_002.html
part0012_split_003.html
part0012_split_004.html
part0012_split_005.html
part0012_split_006.html
part0012_split_007.html
part0012_split_008.html
part0013_split_000.html
part0013_split_001.html
part0013_split_002.html
part0013_split_003.html
part0013_split_004.html
part0013_split_005.html
part0013_split_006.html
part0013_split_007.html
part0013_split_008.html
part0013_split_009.html
part0013_split_010.html
part0013_split_011.html
part0013_split_012.html
part0014_split_000.html
part0014_split_001.html
part0014_split_002.html
part0014_split_003.html
part0014_split_004.html
part0014_split_005.html
part0014_split_006.html
part0014_split_007.html
part0014_split_008.html
part0014_split_009.html
part0014_split_010.html
part0014_split_011.html
part0015_split_000.html
part0015_split_001.html
part0015_split_002.html
part0015_split_003.html
part0015_split_004.html
part0015_split_005.html
part0015_split_006.html
part0015_split_007.html
part0015_split_008.html
part0015_split_009.html
part0015_split_010.html
part0016_split_000.html
part0016_split_001.html
part0016_split_002.html
part0016_split_003.html
part0016_split_004.html
part0016_split_005.html
part0016_split_006.html
part0016_split_007.html
part0016_split_008.html
part0016_split_009.html
part0017_split_000.html
part0017_split_001.html
part0017_split_002.html
part0017_split_003.html
part0017_split_004.html
part0017_split_005.html
part0017_split_006.html
part0017_split_007.html
part0017_split_008.html
part0017_split_009.html
part0017_split_010.html
part0017_split_011.html
part0018_split_000.html
part0018_split_001.html
part0018_split_002.html
part0018_split_003.html
part0018_split_004.html
part0018_split_005.html
part0018_split_006.html
part0019_split_000.html
part0019_split_001.html
part0019_split_002.html
part0019_split_003.html
part0019_split_004.html
part0019_split_005.html
part0019_split_006.html
part0019_split_007.html
part0019_split_008.html
part0019_split_009.html
part0019_split_010.html
part0020_split_000.html
part0020_split_001.html
part0020_split_002.html
part0020_split_003.html
part0020_split_004.html
part0020_split_005.html
part0020_split_006.html
part0020_split_007.html
part0020_split_008.html
part0021_split_000.html
part0021_split_001.html
part0021_split_002.html
part0021_split_003.html
part0021_split_004.html
part0021_split_005.html
part0021_split_006.html
part0021_split_007.html
part0021_split_008.html
part0021_split_009.html
part0022.html
part0023.html
part0024.html
part0025.html