Orlok: switch case beachtet nur letzten Wert

Beitrag lesen

Hallo Peter

Nun will ich den DIVs per Event eine Funktion zuordnen

Da ist dein erster Fehler. div-Elemente sind kein interaktiver Inhalt. Das heißt, sie können ohne Weiteres nicht mit der Tastatur bedient werden. Viele Nutzer sind aber auf Tastaturbedienbarkeit angewiesen. Das ist also schlecht. Verwende statt div-Elementen lieber buttons. Die können per Tastatur angewählt und aktiviert werden, ohne dass du zusätzlichen Aufwand betreiben musst.

var alle_DIVs = document.querySelectorAll('.my_class');

for (var i=0; i<alle_DIVs.length; i++) {
	var my_DIV = alle_DIVs[i];
	var my_DIV_id = alle_DIVs[i].id;
	my_DIV.addEventListener("click", function() {

		switch(my_DIV_id) {
		case "id_1":
		document.write("Erstes Statement");
      break;

		case "id_2":
		document.write("Zweites Statement");
    break;

// CODE

Schauen wir uns an, warum das nicht funktioniert:

Du referenzierst in der Schleife ein Element nach dem anderen und registrierst für jedes Element einen Eventhandler. Du sagst also: „Wenn auf dieses Element geklickt wird, führe diese Funktion aus.“ Dann kommt das nächste Element an die Reihe. Die Funktion, die du als Eventhandler registrierst, wird also nicht direkt ausgeführt, sondern nur hinterlegt und erst zu irgendeinem späteren Zeitpunkt aufgerufen, wenn jemand auf das entsprechende Element geklickt hat. Die Schleife ist zu diesem Zeitpunkt längst abgearbeitet.

Aus Sicht der als Eventhandler registrierten Funktionen haben die außerhalb definierten Variablen dann den Wert, der ihnen im letzten Schleifendurchlauf zugewiesen wurde.

Das liegt daran, dass der Anweisungsblock, der den Schleifenrumpf beinhaltet, für Variablen die mit var deklariert werden keinen lokalen Scope darstellt, der in einem Funktionsabschluss konserviert werden könnte. Solche Variablen werden grundsätzlich an den Ausführungskontext gebunden, in dem sie deklariert wurden. Das heißt, sie sind prinzipiell funktionsweit sichtbar, auch wenn sie innerhalb eines Blocks deklariert wurden, der zu einer bedingten Anweisung oder wie hier zu einer Schleife gehört.

Es wird in deinem Code also nicht in jedem Schleifendurchlauf eine neue Variablenbindung angelegt, sondern bloß ein und derselben Variable ein neuer Wert zugewiesen.

Es gibt in JavaScript aber auch die Möglichkeit, Konstanten und Variablen zu deklarieren, die Blockscope besitzen, die also nur innerhalb des Anweisungsblocks sichtbar sind, in dem sie deklariert wurden. Hierfür werden die Schlüsselwörter const und let verwendet. Ich würde dir empfehlen, nur solche Konstanten und Variablen zu verwenden. Konstanten, wenn nicht beabsichtigt ist nochmal einen anderen Wert zuzuweisen, andernfalls Variablen.

const buttons = document.querySelectorAll('button');


for (let i = 0; i < buttons.length; i++) {
    const button = buttons[i];

    button.addEventListener('click', function(event) {
        console.log(button.id);
    });
}

Dieses Beispiel ist so ähnlich wie deins, aber hier wird in jedem Schleifendurchlauf eine neue Bindung für die Konstante mit dem Bezeichner button angelegt, in der eine Referenz auf einen Button gespeichert wird. Wenn der registrierte Eventhandler ausgeführt wird, dann wird auf die Konstante zugegriffen, die im selben Schleifendurchlauf deklariert wurde, in dem auch die Funktion definiert wurde.

Wie dedlfix bereits sagte, ist das alles aber unnötig kompliziert. Jedem Eventhandler wird beim Aufruf ein Eventobjekt übergeben, welches über die Eigenschaften currentTarget und target verfügt. Erstgenannte Eigenschaft enthält eine Referenz auf das Element, auf dem der Eventhandler registriert wurde. Die Eigenschaft target enthält eine Referenz auf das Element, welches das Ereignis ausgelöst hat. Das muss nicht zwingend dasselbe sein, was man sich auch zunutze machen kann.

document.body.addEventListener('click', function(event) {

    if (event.target.tagName === 'BUTTON') {
        console.log(button.id);
    }

});

Statt für jedes Element einen eigenen Eventhandler zu registrieren, kannst du auch auf einem Elternelement – etwa wie im Beispiel oben dem body-Element – einen Eventhandler registrieren. Wird dann auf ein Kindelement geklickt, wird auch dieser Handler aufgerufen. Über die Eigenschaft target des Eventobjekts kannst du dann das Element referenzieren, auf das geklickt wurde und die gewünschte Aktion ausführen. Unter dem Stichwort Event Delegation wirst du mehr zu dieser Technik finden.

Viele Grüße,

Orlok