Onkel Schnitzel: Problem mit Funktionsaufruf nach DOM-Manipulation

Hallihallo,

heute mal ein jQuery/JS-Problem. Ich habe eine Liste, der ich per JS Einträge anfügen oder entfernen kann. Dies funktioniert soweit auch. Allerdings vielleicht eher zufällig? Ich scheine da wieder irgendwas komisches zusammengefuscht zu haben. Denn meine globale Zählervariable, mit der ich die Anzahl der Listenelemente direkt per Klick speichern will, zeigt mir, dass offenbar was schief läuft.

Das Zufügen und Hochzählen funktioniert tadellos. Das Entfernen des Listenelements erstmal auch, aber die Zählervariable spinnt. Ich vermute, das Problem liegt darin, dass ich bei jedem Zufügen die Funktion LinkRemove aufrufe. Je öfter ich das tue, also je mehr Elemente ich zufüge, umso mehr vermindert er dann auch die Zählervariable, je nachdem das wievielte Listenelement ich entferne. Wenn ich 5 Elemente zufüge und dann das erste der fünf Elemente lösche, springt die Zählervariable sofort von 5 auf 0, obwohl ja nur 1 Element entfernt wurde.

ICh habe jetzt stundenlang rumprobiert, aber mir fällt nichts mehr ein. Ich weiß nicht mal mehr genau, warum ich LinkRemove() nach jedem DOM-Zufügen aufrufen muss, es geht aber derzeit nur so. Wahrscheinlich damit die Funktion immer Zugriff auf den aktuellen DOM-Baum hat?  Hm, ich bin gerade wieder ratlos.

Beste Grüße
Onkel Schnitzel

  
<button type="button" id="addLink">Link hinzufügen</button>  
<ul>  
  <li>  
    <button type="button" class="removeLink"></button>  
    <input name="link[]">  
    <input name="linktext[]">  
  </li>  
</ul>  

  
var LINKS_ANZAHL = 0;  
  
$(document).ready(function() {  
	LinkRemove ();  
});	  
  
// DOM-Element hinzufügen und glob. Variable +=1  
$('button#addLink').click(function() {  
	console.log('+');  
	LINKS_ANZAHL+=1;  
	// Listenelement hinzufügen .... (hier mal rausgenommen)  
	  
        // Aufruf  
	LinkRemove();  
});  
  
// DOM-Element entfernen und glob. Variable -=1	  
var LinkRemove = function () {  
	$('button.removeLink').click(function() {  
		console.log('-');  
		LINKS_ANZAHL-=1;  
		// Listenelement entfernen => funktioniert  
		$(this).parent().remove();  
	});	  
}  

  1. Hallo,

    Dies funktioniert soweit auch. Allerdings vielleicht eher zufällig?

    solche Zweifel sind manchmal ganz gut. :-)

    Ich scheine da wieder irgendwas komisches zusammengefuscht zu haben.

    Du meinst ge_p_fuscht?

    Das Zufügen und Hochzählen funktioniert tadellos.

    Das verblüfft mich, denn so wie ich deinen Code verstehe, entfernst du das neu hinzugefügte Element sofort wieder:

    // DOM-Element hinzufügen und glob. Variable +=1

    $('button#addLink').click(function() {
    console.log('+');
    LINKS_ANZAHL+=1;
    // Listenelement hinzufügen .... (hier mal rausgenommen)

    // Aufruf
    LinkRemove();
    });

      
    Was soll der Aufruf von LinkRemove() in der Funktion, die diesen Eintrag gerade "mühsam" erzeugt hat?  
      
    
    > Das Entfernen des Listenelements erstmal auch, aber die Zählervariable spinnt. Ich vermute, das Problem liegt darin, dass ich bei jedem Zufügen die Funktion LinkRemove aufrufe.  
      
    Ja, eben. Wozu? Was ist der Hintergedanke dabei?  
      
    
    > Ich weiß nicht mal mehr genau, warum ich LinkRemove() nach jedem DOM-Zufügen aufrufen muss, es geht aber derzeit nur so. Wahrscheinlich damit die Funktion immer Zugriff auf den aktuellen DOM-Baum hat?  
      
    Nee, das ist irgendwie gedanklich-logischer Murks.  
      
    
    > ~~~javascript
    
    // DOM-Element entfernen und glob. Variable -=1	  
    
    > var LinkRemove = function () {  
    > 	$('button.removeLink').click(function() {  
    > 		console.log('-');  
    > 		LINKS_ANZAHL-=1;  
    > 		// Listenelement entfernen => funktioniert  
    > 		$(this).parent().remove();  
    > 	});	  
    > }
    
    

    Ich frage mich gerade, ob 'this' in dieser Eventhandler-Funktion wirklich das ist, was du erwartest.

    Übrigens empfiehlt sich der Operator ++ oder -- anstatt +=1 oder -=1, wenn man einen Wert um genau 1 erhöhen oder veringern möchte.

    So long,
     Martin

    --
    Wenn dir jemand eine unschlagbare Abkürzung empfiehlt, gehe einen Umweg.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. Du meinst ge_p_fuscht?

      Na sicher :-)

      Das verblüfft mich, denn so wie ich deinen Code verstehe, entfernst du das neu hinzugefügte Element sofort wieder:

      // DOM-Element hinzufügen und glob. Variable +=1

      $('button#addLink').click(function() {
      console.log('+');
      LINKS_ANZAHL+=1;
      // Listenelement hinzufügen .... (hier mal rausgenommen)

      // Aufruf
      LinkRemove();
      });

      
      >   
      > Was soll der Aufruf von LinkRemove() in der Funktion, die diesen Eintrag gerade "mühsam" erzeugt hat?  
        
      Die Funktion wird da zwar aufgerufen, aber in der passiert ja erst etwas nach Klick auf den Entfernen-Button $('button.removeLink') vor dem Eintrag.  
        
      ~~~javascript
        
      var linkRemove = function () {  
      	$('button.removeLink').click(function() { .......  
      
      

      Ja, eben. Wozu? Was ist der Hintergedanke dabei?

      Wenn ich das Klick-Event nicht in die LinkRemove-Funktion packe, sondern einfach nur als anonyme Funktion per $('button.removeLink').click(function() { .... anlege, passiert beim Klick auf einen Entfernen-Button $('button.removeLink') rein gar nichts. Deswegen dachte ich mir, dass die neu eingefügten DOM-Elemente der Funktion beim Aufbau der Seite wohl einfach noch nicht bekannt sind. Daher der Aufruf der Funktion bei jedem Zufügen.

      Nee, das ist irgendwie gedanklich-logischer Murks.

      Autsch :-/

      Ich frage mich gerade, ob 'this' in dieser Eventhandler-Funktion wirklich das ist, was du erwartest.

      Das zumindest ja. Das ist genau der Button vor dem Listeneintrag, über den ich dann per parent() das Listenelement löschen kann. Ich habs gerade nochmal mit einem next('input').val() probiert, er liefert mir den zum Button gehörigen input-Wert.

      Übrigens empfiehlt sich der Operator ++ oder -- anstatt +=1 oder -=1, wenn man einen Wert um genau 1 erhöhen oder veringern möchte.

      Ich finds eigentlich auch schöner mit ++, aber ich hatte gehört, dass die +=-Schreibweise wohl für aktuelle Projekte empfohlen wird. Von wem oder warum auch immer...

      1. Om nah hoo pez nyeetz, Onkel Schnitzel!

        Wenn ich das Klick-Event nicht in die LinkRemove-Funktion packe, sondern einfach nur als anonyme Funktion per $('button.removeLink').click(function() { .... anlege, passiert beim Klick auf einen Entfernen-Button $('button.removeLink') rein gar nichts. Deswegen dachte ich mir, dass die neu eingefügten DOM-Elemente der Funktion beim Aufbau der Seite wohl einfach noch nicht bekannt sind.

        Richtig. Wiki/FAQ

        Matthias

        --
        Der Unterschied zwischen Java und JavaScript ist größer als der zwischen wir und Wirrwarr.

        1. Richtig. Wiki/FAQ

          Feine Sache! Ich habs irgendwann mal gelesen, aber nicht für so wichtig befunden. Siehste mal...

          Danke!

  2. Hi,

    LinkRemove ();

    Tipp: gib Deinen Funktionen Namen, die tatsächlich das beschreiben, was die Funktion tut. Ds trägt wesentlich zum Verständnis bei. Diese Funktion hier entfernt ja nicht den Link, sondern setzt nur das Event, dass bei Click den Link entfernen soll. Besser wäre also wohl etwas wie "AddRemoveLinkEventFkt" o.ä.

    // DOM-Element entfernen und glob. Variable -=1
    var LinkRemove = function () {
    $('button.removeLink').click(function() {
    console.log('-');
    LINKS_ANZAHL-=1;
    // Listenelement entfernen => funktioniert
    $(this).parent().remove();
    });
    }

    Stimmt es, dass sich bei jedem Deiner Links befindet sich ein button mit Class "removeLink" befindet? Bei jedem Aufruf von "RemoveLink" addes Du dann an _jeden_ Deiner Buttons eine neue Funktion an das Click-Event. Wenn Du fünf Links darstellst, hast Du an den ersten fünf Funktionen angehängt. Die auch alle ausgeführt werden und Dein globale Variable dementsprechend fünf Mal inkrementieren.

    Könnte das sein?

    Gruß
    Stefanie