Nach ersetzen eines Abschnitts, werden JS-Funktionen nicht mehr ausgeführt

Hallo allerseits.
Erst einmal die Ausgangssituation:
Ich arbeite mit ZF2 und habe eine Maske, in der ich durch eine Dropdown-Box einen Wert (eine Person) auswählen kann. Beim ersten Laden der Seite, werden Informationen zu allen Personen angezeigt. (es werden bis zu 10 Informationen angezeigt)
Die einzelnen Informationen kann man nun zu/aufklappen.

Sobald eine Person ausgewählt wurde, aktualisiert sich er Informationsbereich und es werden nur noch Infos zu einer Person angezeigt.

Die Struktur in meiner HTML ist:
[XML]









[/XML]

Problem ist nun, dass sobald ich eine Person selektiere und die Personenbezogenen Infos geladen wurden, funktioniert das auf/zuklappen nicht mehr.
Sprich: In den neu eingefügten Bereichen, funktioniert das Javascript, welches im Header der Seite eingebunden ist nicht mehr.

Weiß jemand warum das nicht mehr funktioniert?

Nachfolgend der Code, der die Änderung in der Dropdownbox erkennt und den Bereich ersetzt.
Ich habe schon mehrfach geprüft, dass die Struktur vor dem ersetzen und nach dem ersetzen identisch ist.


$(document).ready(function() {
	$("#person_combobox").change(function() {
		searchInfos();
	});	
});

function searchInfos() {
	var person = $("#person_combobox").val();
	var myData = {PERSON:person};
	$.ajax({
		type: "POST",
		url: "Ansicht/sucheDaten",
		data:myData,
		beforeSend: function() {
			var html = '<div id="centerInformation"><img width="300" height="30" src="loader.gif" alt="lade"></div>';
			document.getElementById("container").innerHTML = html;
		},
		success: function(data){
			document.getElementById("container").innerHTML = data;
		},
		failure: function(){
			alert("Failure!!");
		}
	});
}

Habe keine Ahnung was ZF2 ist, aber dein Problem ist vermutlich folgendes:
Wenn du per JQuery Events nach dem Schema $('<selector>').click(...); bindest scannt jQuery den DOM und hängt an alle Objekte die dem selector matchen den Clicklistener an. Tauschst du dann im Laufe der Zeit Objekte im Dom aus, bekommen die keine Clicklistener.
Dafür gibt es in jQuery die on() Methode, damit werden auch Komponenten “gefunden” die erst später in den DOM kommen.

ZF2 = ZendFramework 2

mir fällt gerade auf, dass ich ein wenig Quellcode noch hätte dazu schreiben sollen.

Nachfolgend noch meine auf-/zuklapp-Methode:


$(document).ready(function () {
	$('.PersonInfoBox').on('click', '.showhide', function(){
		toggleItem($(this), 'toggle');
    });
});

function toggleItem(item, option) {
	var box = item.parent('.PersonInfoBox');
	var infos = box.children(".infos");
	var speed = 'slow';
	if (option === 'toggle') {
		infos.slideToggle(speed);
	} else if (option === 'down') {
		infos.slideDown(speed);
	} else if (option === 'up') {
		infos.slideUp(speed);	
	}
}

Wie hier zu sehen ist, verwende ich bereits die .on() Methode.

Weitere Ideen?

Habe gerade noch etwas bemerkt.

Vorher aber kurz noch eine Erläuterung:

Meine Seite ist aufgebaut in Kopf und Positionen.
Im Kopf sind die Selektionsmöglichkeiten und auch ein Schalter um alle Positionen auf-/zuzuklappen.

Die einzelnen Positionen (PersonInfoBox) haben auch wieder einen Schalter, um genau diese eine Position auf-/zuklappen zu können.

Wenn ich nun meine Positionen durch AJAX aktualisiere, funktionieren nur die Schalter innerhalb der Position nicht mehr. Der Schalter im Kopf (der sich ja auch nicht neu geladen hat) kann immernoch alle Positionen ansprechen.
Also werden die Objekte schon noch richtig gefunden, nur reagiert das .on(‘click’…) nicht mehr.

im Zweifel lieber mal nachgefragt, auch wenn falsch weil ich es nicht gut genug kenne:
container enthält am Anfang 10x PersonInfoBox mit jeweils Infos,

löscht du diese 10 nicht wenn du document.getElementById("container").innerHTML = html; austauschst?

ist danach nicht alles weg, was aufzuklappen wäre?


edit:


$(document).ready(function () {
	$('.PersonInfoBox').on('click', '.showhide', function(){
		toggleItem($(this), 'toggle');
    });
});

klingt nach einer Funktion, die am Anfang 1x ausgeführt wird,
zu diesem Zeitpunkt werden alle PersonInfoBox gesucht und mit Funktion ausgestattet,

führe diese oder vergleichbare Aktion auch wieder aus, wenn (falls?) du neue PersonInfoBox hinzufügst,
evtl. weitere sonstige neue Tags/ Objekte/ Elemente was auch immer?

löscht du diese 10 nicht wenn du document.getElementById(„container“).innerHTML = html; austauschst?

Ja, aber es kommen ja bis zu 10 neue PersonInfoBox dabei, die dann wieder auf-/zugeklappt werden können

klingt nach einer Funktion, die am Anfang 1x ausgeführt wird,
zu diesem Zeitpunkt werden alle PersonInfoBox gesucht und mit Funktion ausgestattet,

führe diese oder vergleichbare Aktion auch wieder aus, wenn (falls?) du neue PersonInfoBox hinzufügst,
evtl. weitere sonstige neue Tags/ Objekte/ Elemente was auch immer?

Danke danke danke danke :smiley:
Das war nun der Stein des anstoßes, den ich gebraucht hatte.

Wie ich nun herausgefunden habe, ist es nämlich so, dass

$(document).ready

nur ausgeführt wird, wenn die komplette Seite neu geladen wurde. Ich war bisher der Ansicht (und dachte auch, dass ich das an anderer Stelle schonmal so verwendet hätte) das auch bei Ajax aufrufen diese Methode wieder angestoßen wird. Dem ist aber allem Anschein nach nicht so.

Nach kurzer Recherche bin ich dann auf

$(document).ajaxComplete

gestoßen. Diese Methode wird dann (wie der Name schon sagt) ausgeführt, wenn ein Ajax Call abgeschlossen wurde.

Also habe ich das ganze nun folgendermaßen programmiert:


function registerToggleClick() {
	'use strict';
	$('.PersonInfoBox').on('click', '.showhide', function(){
		toggleItem($(this), 'toggle');
    });
}

$(document).ready(function () {
	'use strict';
	registerToggleClick();
});

$(document).ajaxComplete(function () {
	'use strict';
	registerToggleClick();
});

Dadurch wird sowohl beim neuladen der Seite, als auch beim absetzen eines AJAX calls, die Funktion „registerToggleClick“ neu aufgerufen und die PersonInfoBox’en können auf- und zugeklappt werden :slight_smile:

Die einzige Frage, die mir bei so „neuem“ dann immer im Kopf rum geistert ist: „Ist das so Ok“, „Kann/Darf/Soll man das so machen“, „gibt es bessere Alternativen“?