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.
Event-gesteuerte Plugins erstellen
Problem
Sie wollen Ihr Plugin von außen steuern können. Der Anwender sollte jederzeit dazu in der Lage sein, dem Plugin mitzuteilen, dass es etwas tun soll. Es kann viele Instanzen eines Plugins geben, aber unsere Aktion sollte im von uns gelieferten Kontext ausgeführt werden.
Lösung
Man kann dieses Problem unter anderem durch Events lösen.
Wenn ein Plugin aufgerufen wird, bindet es Funktionen an jedes gefundene Element, die einmal aufgerufen die gewünschten Aktionen ausführen.
Eine optionale Möglichkeit wäre auch, bei jedem Aufruf des Plugins nicht die Kette abzuarbeiten, sondern ein Objekt zurückzugeben, das die Bindings enthält und das von außen bearbeitet werden kann (zum Beispiel das Plugin aus Das globale Auslösen von Events beschleunigen ).
Damit können Sie das Plugin viele Male für das gleiche Element aufrufen, ohne sich mit Events vollzumüllen.
Diskussion
Ein Beispiel
Wir werden jetzt ein einfaches Slideshow-Plugin erstellen. Ich werde dieses Plugin auf einem bestehenden Plugin von mir namens
jQuery.SerialScroll
aufbauen. [ 19 ] Ich habe beim Schreiben des Codes für dieses Plugin als erstes an diesen Ansatz gedacht und es funktioniert ausgesprochen gut.
Wir werden unser Plugin
slideshow
nennen. Es wird ein
-Element und ein Array mit URLs erhalten und dann zyklisch durch die Bilder laufen. Zudem wird man damit zum vorherigen und nächsten Bild, aber auch zu einem bestimmten Bild springen können.
Fangen wir mit den Grundlagen an:
(function( $ ){
$.fn.slideshow = function(options){
return this.each(function(){
var $img = $(this),
current = 0;
// Slideshow-Verhalten hinzufügen ...
});
};
})( jQuery );
Jetzt werden wir ein paar lokale Funktionen hinzufügen, mit denen wir zu unterschiedlichen Bildern (URLs) in der Collection springen können:
function show( index ){
var total = options.images.length;
while( index < 0 )
index += total;
while( index >= total )
index −= total;
current = index;
$img.attr('src', options.images[index]);
}
function prev(){
show( current − 1 );
}
function next(){
show( current + 1 );
}
Nun können wir diese Funktionalität über Events nach außen bringen:
$img.bind('prev', prev).bind('next', next).bind('goto',function(e, index){
show( index );
});
Wie ist es mit dem automatischen zyklischen Anzeigen? Ergänzen wir ein paar weitere Funktionen:
var auto = false, id;
function start(){
stop();
auto = true;
id = setTimeout(next, options.interval || 2000);
}
function stop(){
auto = false;
clearTimeout(id);
}
und die dazugehörigen Events:
$img.bind('start', start).bind('stop', stop);
Jetzt brauchen wir noch ein paar weitere Code-Zeilen bei
show()
, um das automatische Anzeigen zu aktivieren:
function show( index ){
// Wie zuvor ...
if( auto )
start();
}
Das ist alles! Wir haben jetzt eine vollständige Slideshow mit
prev
,
next
und einem automatischen Anzeigen des nächsten Bildes.
Um das Beispiel verständlicher zu machen, wurde dieses Plugin so aufgezogen, dass es komplett von den Einstellungen von außen abhängt.
Hier eine Modell-Implementierung:
...
(function( $ ){
var $image = $('#slideshow');
$image.slideshow({
images: ['1.jpg', '2.jpg', '3.jpg', '4.jpg'],
interval: 3000
});
$('#prev').click(function(){