JQuery Kochbuch (German Edition)
Argumente ändern zu können. Und wir benötigen ein Event, das ausgelöst wird, nachdem die Funktion lief, um die zurückzugebenden Daten auslesen und bei Bedarf auch ändern zu können.
Lassen Sie uns schauen, wie man dies als Plugin programmieren kann. Ich werde Ihnen jeden Schritt zeigen.
Diskussion
Die gewünschte Methode überladen
Zuerst erstellen wir eine Funktion, die die jQuery-Methoden durch unsere eigene Funktion ersetzt. Ich werde sie
jQuery.broadcast()
nennen, Sie können den Namen natürlich anpassen:
(function($){
$.broadcast = function(name){
// ursprüngliche Methode sichern
var old = $.fn[name];
$.fn[name] = function(){
// Broadcast
};
};
})(jQuery);
name
muss der Methodenname sein, den wir überschreiben wollen, zum Beispiel:
jQuery.broadcast('addClass');
Ein Event vor der Ausführung auslösen
Nachdem wir unsere eigene Funktion als jQuery-Methode etabliert haben, wollen wir uns anschauen, wie wir ein Event auslösen, mit dem wir die übergebenen Argumente ändern können:
// Ein Event-Objekt erstellen
var e = $.Event('before-'+name);
// Argumente im Objekt sichern
e.args = $.makeArray(arguments);
// Das Event auslösen
this.trigger(e);
Wenn wir
addClass()
»verbreiten« wollen, können wir Folgendes tun:
jQuery('body').bind('before-addClass',function(e){
e.args[0]; // Die CSS-Klasse
});
Die ursprüngliche Methode ausführen
Jetzt wird ein Event ausgelöst, aber wir müssen immer noch die alte
addClass()
aufrufen. Wir werden auch die zurückgegebenen Daten im Event-Objekt speichern, so dass wir sie später bereitstellen können, wenn wir das andere Event auslösen.
e.ret = old.apply(this, e.args);
Wie Sie sehen können, übergeben wir nicht das ursprüngliche Array
arguments
, sondern wir nutzen die Version, die wir bereitgestellt haben, falls es schon irgendwie verändert wurde.
Ein Event nach der Ausführung auslösen
Wir haben jetzt die zurückgegebenen Daten in unserem Event-Objekt gespeichert. Nun können wir das abschließende Event auslösen und damit die externe Veränderung der zurückgegebenen Daten ermöglichen.
Wir werden das gleiche Event-Objekt verwenden, aber den Namen des Events ändern.
e.type = 'after-'+name;
this.trigger(e);
Das Ergebnis zurückgeben
Jetzt bleibt uns nur noch, die Ergebnisse zurückzugeben und mit der normalen Ausführung fortzufahren. Wir werden das zurückgeben, was wir in
e.ret
gesichert haben und was eventuell durch einen Eventhandler verändert wurde:
return e.ret;
Alles zusammen
Dies ist der vollständige Code:
(function($){
$.broadcast = function(name){
var old = $.fn[name];
$.fn[name] = function(){
var e = $.Event('before-'+name);
e.args = $.makeArray(arguments);
this.trigger(e);
e.ret = old.apply(this, e.args);
e.type = 'after-'+name;
this.trigger(e);
return e.ret;
};
};
})(jQuery);
Was kann man noch machen?
Ich habe versucht, das Beispiel kurz zu halten, um die Idee deutlich zu machen. Es gibt ein paar Dinge, die noch verbessert werden können – hier ein paar Ideen:
Nutzen Sie
triggerHandler()
anstatt
trigger()
: Müssen die Events nicht aufsteigen, dann können Sie einfach
triggerHandler()
verwenden. Dadurch läuft der gesamte Prozess schneller ab. Beachten Sie allerdings, dass
triggerHandler()
nur das Event für das erste Element der Collection auslöst.
Lassen Sie den Prozess für jedes Element getrennt ablaufen. Im vorigen Beispiel wird
trigger()
für die gesamte Collection auf einmal aufgerufen. Das ist in den meisten Fällen in Ordnung, kann aber zu unerwarteten Ergebnissen führen, wenn man dies für Collections mit mehreren Elementen nutzt.
Sie können das, was wir in die Funktion gesteckt haben, mit einem Aufruf von
map()
einpacken. Damit sollte der Code einmal pro Element ausgeführt werden.
Der Nachteil ist der, dass die Performance etwas niedriger ist und zudem durch den Aufruf von
map()
ein (unerwarteter) Eintrag auf dem Stack entsteht (
pushStack()
).
Erlauben Sie es externem Code, die normale Ausführung zu verhindern. Nutzen Sie jQuery 1.3 oder höher, können Sie auf die Methoden für
jQuery.Event
zurückgreifen.
Sie können das Event-Objekt »fragen«, ob jemand seine Methode
preventDefault()
aufgerufen hat. Dazu müssen Sie nur
e.isDefaultPrevented()
abfragen.
Gibt diese Methode
true
zurück, dann rufen Sie die ursprüngliche Funktion einfach nicht auf.
Vermeiden Sie mehrfaches Überladen dergleichen jQuery-Methode. Dies lässt sich leicht kontrollieren –
Weitere Kostenlose Bücher