jQuery :: JavaScript Funktionen für dynamisch erzeugte Inhalte

Im letzten Beitrag (jQuery :: Grundlagen Events – Was ist “$(this)”? / jq_beispiel_007.html) wurden durch einfach Mausevents dynamisch Inhalte erzeugt. Durch einen Doppelklick auf einen Absatz wurde dieser kopiert und nach dem angeklickten Absatz eingefügt. Jedoch sind die neuen Absätze nicht formatiert und verhalten sich auch nicht so, wie der ursprüngliche Absatz.

Diese Problematik taucht innerhalb von jQuery öfters auf und bereitet immer wieder Probleme.In diesem Beitrag sollen hierzu Lösungsansätze vorgestellt werden, welche bei dieser Problematik angewendet werden können.

Hierfür werden die jQuery Anweisungen in JavaScript-Funktionen gepackt und immer dann aufgerufen, wenn neue Elemente der Seite hinzugefügt werden. Auf diese Weise wird sichergestellt, dass auch die neuen Inhalte auf Events reagieren. Zusätzlich werden die Methoden .unbind() und .live() vorgestellt.

Warum funktionieren die Events nicht bei den mit append() hinzugefügten Inhalten?

Diese Frage ist berechtigt und am Anfang ist dieses Problem nicht so ohne weiteres zu verstehen. Hierfür soll vereinfacht der Ablauf dargestellt werden, wie die Seite inklusive den Events entsteht.

Als erstes existiert die reine HTML Definition der Seite. Diese Definition wird durch den Browser geladen. Die jeweiligen Absätze sind noch ohne angepasste Formatierung.

HTML Definition der Seite

Sobald die Seite vollständig geladen wird, startet jQuery mit den Anweisungen, welche in $(document).ready() definiert sind. Hierdurch werden den Absätzen Events zugewiesen und auch das Layout angepasst. Im folgenden Bild ist dies durch eine leichte Einfärbung angedeutet.

Aufruf der Anweisungen durch $(document).ready()

Wenn nun die Dateien kopiert werden, dann wird innerhalb des Funktionsaufrufes nur die HTML Definition kopiert. Die Anweisung hierfür sieht im Code so aus:

$("p").dblclick(function(){
   $(this).after("<p>"+$(this).html()+"</p>");
});

jQuery kopiert nur die HTML Definition der Elemente und nicht deren angepassten Eigenschaften.

Das was jetzt passiert ist zeigt, dass nur die HTML Definition kopiert wurde und nicht die Teile, welche am Anfang durch jQuery angepasst wurden. D.h. wenn diese kopierten Elemente auch die gleichen Eigenschaften bekommen sollen, wie deren “Eltern”, dann müssen diese Funktionen noch einmal für die neuen Absätze aufgerufen werden.

Auslagern der jQuery Anweisungen in eine Funktion

Eine Möglichkeit dieses Problem zu lösen ist es, die jeweiligen jQuery Anweisungen in eine Funktion auszulagern und diese Funktion dann aufzurufen, nachdem die neuen Elemente hinzugefügt wurden. Für dieses Beispiel wird eine Funktion mit dem Namen jqAnweisungen erzeugt.

function jqAnweisungen(){
   // Hier werden die jQuery Befehle eingefügt
}

Damit die Formatierungen nicht doppelt innerhalb des Codes auftauchen, wird auch noch der Code innerhalb von $(document).ready() angepasst. Dabei werden die jQuery Anweisungen entfernt und anstelle dafür einfach die Funktion jqAnweidungen() aufgerufen. Dieses Vorgehen hat den Vorteil, dass Definitionen nicht doppelt auftauchen. Dadurch wird die Pflege des Codes vereinfacht. Der Aufruf sieht dabei wie folgt aus:

$(document).ready(function(){
  jqAnweisungen();
});

Die Seite mit den dazugehörigen Anpassungen sieht nun wie folgt aus: jq_beispiel_008a.html

Das Auslagern hat an dieser Stelle geklappt. Die Formatierung und auch der Doppelklick über die neuen Elemente funktioniert. Jedoch kommt es auch zu unerwünschten Ergebnissen. Wenn beispielsweise immer auf das erste Element geklickt wird, werden beim ersten Hinzufügen ein Element, beim zweiten mal zwei, bei dritten mal vier und beim vierten mal acht usw. hinzugefügt.

Das liegt daran, dass jedes mal ein Event hinzugefügt wird. Wenn also mehrmals mittels dblclick() ein Event hinzugefügt wird, so werden alle nacheinander abgearbeitet. Das Beispiel wird an der Stelle kurz wie folgt abgewandelt:

// Doppelklick wird 3 mal hinzugefügt
	$("p").dblclick(function(){
		$(this).after("<p>Erstes Event: "+$(this).html()+"</p>");
	});
	$("p").dblclick(function(){
		$(this).after("<p>Zweites Event: "+$(this).html()+"</p>");
	});
	$("p").dblclick(function(){
		$(this).after("<p>Drittes Event: "+$(this).html()+"</p>");
	});

Der Aufruf des Doppelklicks erfolgt drei mal. Das Ergebnis sieht wie folgt aus: jq_beispiel_008b.html

In diesem Beispiel werden die jeweiligen Anweisungen drei mal ausgeführt.  Die jeweiligen Absätze tauchen dabei in umgekehrter Reihenfolge auf, was daran liegt, dass der jeweilige Inhalt immer direkt nach dem angeklickten Element hinzugefügt wird.

Entfernen von zugewiesenen Events mittels unbind()

Eine Möglichkeit dieses Problem zu lösen ist, dass innerhalb der Funktion zuerst einmal alle .dblclick() Events gelöscht werden, bevor neue Events den jeweiligen Elementen zugewiesen werden. Hierfür kann die jQuery Methode .unbind() verwendet werden. Wird diese Methode ohne Parameter angewendet, so werden alle Ereignisse gelöscht, jedoch lassen sich auch nur bestimmte Ereignisse löschen. Die Doppelklick Ereignisse werden also vor dem Zuweisen erst einmal entfernt:

$("p").unbind("dblclick");
$("p").dblclick(function(){
   $(this).after("<p>"+$(this).html()+"</p>");
   jqAnweisungen(this);
});

Das Ergebnis bringt an der Stelle auch den gewünschten Effekt: jq_beispiel_008_unbind.html

Jedoch ist die Lösung noch nicht ganz glücklich. Es gibt auch eine andere Möglichkeit diese Funktionalität zu programmieren. Hierfür wird anstatt von .dblclick() die Methode .live() verwendet.

Zukünftigen Elementen Ereignisse mit .live() zuweisen

Das hier dargestellte Problem taucht bei der Verwendung von jQuery regelmäßig auf. Ereignisse sollen auch dann gelten, wenn neue Elemente auf der Seite hinzukommen. Hierfür wurde von den jQuery Entwicklern auch eine Methode entwickelt, welche sich diesem Problem annimmt.

Die Methode .live() ermöglicht es Ereignisse bestimmten Elementen zuzuordnen, welche noch gar nicht auf der Seite existieren. D.h. während der Konzeption sollte man sich schon Gedanken machen, ob bestimmte Ereignisse nur für die aktuellen Elemente oder auch für ggf. zukünftige Elemente gelten sollen. Je nachdem sollte dann entweder .bind() oder .live() verwendet werden.

Innerhalb der Funktion jqAnweisungen() muss nun die Methode .dblclick() entfernt werden. Innerhalb von  $(document).ready()  muss anschließend folgendes hinzugefügt werden:

$("p").live('dblclick',function(){
   $(this).after("<p>"+$(this).html()+"</p>");
   jqAnweisungen(this);
});

Diese Anpassung bewirkt, dass innerhalb der jqAnweisungen() nur die Formatierungen aufgerufen werden. Wenn nun mit einem Doppelklick Elemente hinzugefügt werden, werden alle Elemente erneut formatiert. Da die Methode .live() verwendet wird, ist es nicht notwendig hier erneut ein Ereignis zuzuweisen.

Das Ergebnis: jq_beispiel_008_live.html

 

 

This entry was posted in Allgemein, IT, jQuery, Tutorium and tagged , , , , , . Bookmark the permalink.

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>