Nico R.: Funktioniert click() nur einmal?

Hallo zusammen,

hier mal runtergebrochen mein Problem mit der JS click()-Methode...

button1.addEventlistener("click", function() {
    funktion1();
}
button2.addEventlistener("click", function() {
    funktion2();
}

function funktion1 () { 
    button2.click(event); 
} 

function funktion2 () { 
    // Ausgabe
} 

Klicke ich button1 per Maus an, bekomme ich die Ausgabe aus Funktion2. Stoße ich button1 im Script mit button1.click() an, bekomme ich keine Ausgabe.

Ausgelöst wird button2.click() in beiden Fällen, event liefert jeweils ein Ergebnis. Allerdings mit unterschiedlichen targets: (einmal parent, einmal child). Auch die Eigenschaft details: unterscheidet sich (einmal 0, einmal 1). Ansonsten scheint alles gleich.

Anscheinend kommen sich ja die beiden clicks() irgendwie in die Quere. Hat eventuell jemand eine Idee?

Schöne Grüße

Nico

  1. @@Nico R.

    button1.addEventlistener("click", function() {
        funktion1();
    }
    

    Es gibt keine Methode addEventlistener(). Und die schließende Klammer ) fehlt.

    Eine anonyme Funktion brauchst du da auch nicht. Du kannst als 2. Parameter gleich das Funktionsobjekt nehmen:

    button1.addEventListener("click", funktion1);
    

    Ich habe das mal in einem Codepen nachgestellt. Das nächste Mal machst du das bitte selbt.

    Klicke ich button1 per Maus an, bekomme ich die Ausgabe aus Funktion2. Stoße ich button1 im Script mit button1.click() an, bekomme ich keine Ausgabe.

    Ausgelöst wird button2.click() in beiden Fällen, event liefert jeweils ein Ergebnis. Allerdings mit unterschiedlichen targets: (einmal parent, einmal child). Auch die Eigenschaft details: unterscheidet sich (einmal 0, einmal 1). Ansonsten scheint alles gleich.

    Anscheinend kommen sich ja die beiden clicks() irgendwie in die Quere. Hat eventuell jemand eine Idee?

    Ich kann dein Problem nicht nachvollziehen.

    🖖 Живіть довго і процвітайте

    --
    „Ukončete, prosím, výstup a nástup, dveře se zavírají.“
    1. Hallo Gunnar,

      das war wohl alles etwas vorschnell hingekliert. Ich habs jetzt selbst nochmal in Codepen getestet, hätte ich natürlich auch vorher machen können.

      Mehrere verschachtelte Aufrufe per .click() funktionieren auf jeden Fall prinzipiell. Das Problem scheint in meinem spziellen Code zu stecken.

      Danke erstmal soweit

      Nico

  2. Hallo Nico,

    ich kann's auch nicht nachvollziehen. Ich weiß, dass bestimmte Dinge in JavaScript nur funktionieren, wenn das Script unmittelbar durch eine Benutzeraktion gestartet wurde (also z.B. als click-Eventhandler). Das Laden der Seite und das Ausführen von Scripten während dieser Zeit ist keine direkte Benutzeraktion. Aber der Aufruf von click() auf einem Button-Element funktioniert auch ohne Benutzerinteraktion.

    Es gibt aber Unterschiede: In dem PointerEvent-Objekt, das nach dem click-Aufruf in Funktion1 ankommt, ist die Eigenschaft isTrusted auf false gesetzt. Klickt man mit der Maus auf Button 1, steht die Eigenschaft auf true.

    Frage wäre also:

    • An welcher Stelle ist dein button1.click() Aufruf? Wird der überhaupt ausgeführt? Ist button1 an dieser Stelle überhaupt definiert und mit einem Wert gefüllt?

    Um das herauszufinden, stellen sich diese weiteren Fragen:

    • Hast Du die Entwicklerwerkzeuge geöffnet?
    • Steht in der Konsole eine Fehlermeldung?

    Grundsätzlich gilt noch: Es ist so, dass zu Urzeiten eine globale Variable event gesetzt wurde, wenn ein Event behandelt wird. Damals war das nötig, denn anders konnte man in einem onclick-Attribut nicht auf die Event-Daten zugreifen.

    Aber wenn man einen EventListener nach der neuen Methode mit addEventListener registriert, dann bekommt die Listener-Funktion das Event-Objekt als Parameter übergeben. Um mal bei deinem Code zu bleiben:

    button1.addEventlistener("click", function(event) {
        funktion1(event);
    });
    

    Und wie Gunnar sagte: so einen Durchlauferhitzer braucht man nicht. Eine Funktion, die das Klick-Event annehmen kann, hast Du schon. Auch die Funktionen, die mit dem function Statement definiert wurden, sind ganz normale Funktionsobjekte und können als Parameter übergeben werden. Deswegen reicht

    button1.addEventlistener("click", funktion1);
    button2.addEventlistener("click", funktion2);
    

    Wichtig ist dann nur, dass Du in funktion1 das Event-Objekt auch entgegennimmst. Und am besten benennst Du den Parameter auch gleich möglichst lesbar:

    function funktion1 (clickEvent) { 
        button2.click(clickEvent); 
    } 
    

    Und wieso hab ich das jetzt trotzdem rot angepinselt? Weil es nicht funktioniert. Die click-Methode erwartet keinen Parameter. Du kannst das click-Event aus dem ersten Klick nicht an den zweiten Eventhandler übergeben. Der Browser generiert ein neues Event-Objekt (und zwar eins mit isTrusted==false) und ruft funktion2 damit auf.

    Es gibt aber eine Alternative: dispatchEvent. Damit kann man ein beliebiges Event-Objekt auf ein HTML Element „loslassen“:

    function funktion1 (clickEvent) { 
        button2.dispatchEvent(clickEvent); 
    } 
    

    Äh, ja. Leider immer noch rot. Weil das Eventobjekt, das in clickEvent steht, bereits dispatched (verteilt) wird und nicht neu in den Dispatch-Prozess eingetütet werden kann.

    Du musst ein neues Eventobjekt erzeugen. Und zwar ein PointerEvent (selbst dann, wenn der Button mit der ENTER Taste ausgelöst wurde):

    function funktion1 (clickEvent) { 
        const newEvent = new PointerEvent("click", {
            details: clickEvent.detail,
        });
        button2.dispatchEvent(newEvent); 
    } 
    

    Die Eigenschaften von Eventobjekten sind readonly, deshalb kannst Du den Wert von details nicht einfach zuweisen. Du musst die Eigenschaften, die Du auf einen bestimmten Wert setzen willst, über ein Optionsobjekt an den Konstruktor übergeben. Da die Eigenschaften auf dem Optionsobjekt aber genau so heißen wie die Eigenschaften im Eventobjekt, kannst Du auch einfach das clickEvent-Objekt als Optionsobjekt übergeben und damit das Objekt sozusagen klonen:

    function funktion1 (clickEvent) { 
        const newEvent = new PointerEvent("click", clickEvent);
        button2.dispatchEvent(newEvent); 
    } 
    

    Und dann geht's. ABER: im Eventhandler von button2 kommt immer ein Eventobjekt an, dem nicht vertraut wird (isTrusted steht auf false). Du verlierst bei diesem Übergang also etwas an Möglichkeiten, wie eingangs erwähnt.

    Die wichtigste Frage wäre also die, die auch die Rumpelwichte an Ronja Räubertochter gestellt haben.

    Wiesu tut sie er su?

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      vielen Dank für deine Erklärungen.

      • An welcher Stelle ist dein button1.click() Aufruf? Wird der überhaupt ausgeführt? Ist button1 an dieser Stelle überhaupt definiert und mit einem Wert gefüllt?

      Ja, alle Elemente existieren, die lasse ich mir ebenso in der Konsole anzeigen wie das event-Objekt.

      Ich bin nicht sicher, ob ich alles komplett verstanden habe, aber ich habe die Variante mit dispatchEvent jetzt mal eingebaut. Damit funktionierts genauso wie mit click(), allerdings hab ich auch das gleiche Problem. Das ist vielleicht gar keins des Event-Handlings, sondern eins der Kapselung der Funktionen (???).

      Nochmal kurz zusammengefasst, was offenbar passiert bzw. was ich will. Vielleicht kapier ichs dann auch besser. Ich hab in meinem "Hauptscript", das ich über src im <head> einbinde:

      <html>	
          <script src="inc/main.js"></script>
      </head>
      

      Dort wir an die <th>s ein click-Event anhängt und dann die Tabelle über die Funktion sortTabelle() umsortiert:

      var sortSpalten = tbl.querySelectorAll("[data-sortierung]");
      for(i=0; i < sortSpalten.length; i++) {
          sortSpalten[i].addEventListener("click", sortTabelle);
      }
      

      Das funktioniert für alle Tabellen auf allen Seiten. Auf einer Seite hab ich nun ein weiteres Script, das spezielle Sachen macht. Unter anderem wird über einen "button" eine Funktion "funktion1" aufgerufen, in der zum Schluss automatisch auch die Tabelle umsortiert wird. Statt mit der Maus auf ein <th> zu klicken, löse ich das über eine id per click() aus.

      <th id="th"></th>
      
      button.addEventListener("click", funktion1);
      
      function funktion1() {
          ...
          th.click();
      }
      

      Das funktioniert auch, solange ich direkt auf den button klicke. Der an th angebundene event-Handler sortiert dann die Tabelle um. Wenn ich allerdings button.click() anwende, wird sortTabelle() nicht mehr aufgerufen. das th-event wird aber abgefeuert, wenn ich das richtig sehe. Zumindest mit Rolfs dispatchEvent kommt hier ein true.

      const newEvent = new PointerEvent("click", event);
      var autosort = th.dispatchEvent(newEvent); 
      console.log(autosort);
      
      

      Die Funktion sortTabelle wird aber nicht aufgerufen... Vielleicht habt ihr ja Spaß dran, mitzutüfteln. Wenn nicht, auch nicht schlimm. Notfalls verzichte ich auf diese Komfortfunktion.

      Eigentlich ists zum Erklären auch zu kompliziert. Ich werde mal beizeiten versuchen, das in codepen nachzubauen und mich dann nochmal melden.

      Schöne Grüße

      Nico

      1. Hallo nochmal,

        ich habs in Codepen nachgebaut. Dort funktioniert das, was ich möchte. Hier ist der Link: Codepen

        Per Klick auf button1 ist verfärbt sich die Tabelle grün. Wenn ihr Zeile 11 auskommentiert, verfärbt sich die Tabelle beim Laden automatisch grün.

        Das ist genau das, was bei mir auch passieren soll, es aber nicht tut. Na mal gucken, was ich noch heraus finde...

        Achso. Hier der Vollständigkeit halber noch das externe JS:

        var tabelle = document.getElementById("tabelle");
        var ths = tabelle.querySelectorAll("th");
        
        for(i=0; i < ths.length; i++) {
        	ths[i].addEventListener("click", test)
        }
        
        function test() {
        	tabelle.setAttribute("style", "background: green");
        }
        
        console.log("tabelle:"+tabelle);
        

        Schöne Grüße Nico

        1. @@Nico R.

          var tabelle = document.getElementById("tabelle");
          var ths = tabelle.querySelectorAll("th");
          
          for(i=0; i < ths.length; i++) {
          	ths[i].addEventListener("click", test)
          }
          

          Fehler: th sind keine interaktiven Elemente, d.h. man kan sie nicht clicken. Einige Nutzer (Mausnutzer) können das, andere Nutzer (Tastaturnutzer) können das nicht.

          Wenn du Interaktionen ausführen lassen willst, musst du buttons in die ths tun. Dann kannst du die Eventhandler für die Buttons regiestrieren – oder wenn du Event-Delegation nutzen willst, einen einzigen Eventhandlerweiter oben (table), und per event.target ermittelst du den jeweils geclickten Button.

          🖖 Живіть довго і процвітайте

          --
          „Ukončete, prosím, výstup a nástup, dveře se zavírají.“
          1. Hallo,

            Wenn du Interaktionen ausführen lassen willst, musst du buttons in die ths tun. Dann kannst du die Eventhandler für die Buttons regiestrieren – …

            so, wie es im Tabellensortierer beschrieben ist.

            Gruß
            Jürgen

        2. Hallo Nico R.,

          Hier der Vollständigkeit halber noch das externe JS

          Ja, das hab ich dann auch entdeckt 😉

          Findet sich der Problemcode ebenfalls auf der FSV-Seite?

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Hallo Rolf,

            Findet sich der Problemcode ebenfalls auf der FSV-Seite?

            Jetzt ja. Codepen war mir bei der Aktualisierung zu träge. Daher hier der neue Nachbau, der Einfachheit halber ohne button in der th 😉

            https://www.fsv-optik.de/tests/test1.html

            Mit Klick auf den button1, der th.click() auslöst und damit tableSort() aus der externen JS aufruft. Bzw. auch noch einem button2, der wiederum button1.click() auslöst. Auch da wird die tableSort() aufgerufen.

            Was nach wie vor nicht funktioniert, ist das hier:

            https://www.fsv-optik.de/tests/test2.html

            Also der automatische Aufruf von button1.click() beim Seitenaufruf. Die Funktion funktion1() wird zwar noch aufgerufen, aber das th.click() darin nicht mehr.

            Die Frage ist, warum das Beispiel auf Codepen funktioniert und hier nicht. Hat das eventuell mit der Reihenfolge der Scriptverarbeitung zu tun? Wie schafft es denn codepen, dass im externen JS-Script document.getElementByID("tabelle") bei der Ausführung zur Verfügung steht? Ich brauche dafür das DOMContentLoaded, sonst meckert der feine Herr Browser. Mannmannmann, soviel zu beachten...

            Schöne Grüße

            Nico

            1. @@Nico R.

              der Einfachheit halber ohne button in der th 😉

              Bullshit.

              https://www.fsv-optik.de/tests/test1.html

              Not found.

              Was nach wie vor nicht funktioniert, ist das hier:

              https://www.fsv-optik.de/tests/test2.html

              Ohne Buttons kann das nicht funktionieren.

              Wie schafft es denn codepen, dass im externen JS-Script document.getElementByID("tabelle") bei der Ausführung zur Verfügung steht?

              Ein Blick in den Quelltext verrät, dass das Script am Ende des bodys eingebunden wird.

              🖖 Живіть довго і процвітайте

              --
              „Ukončete, prosím, výstup a nástup, dveře se zavírají.“
              1. Hallo Gunnar,

                upps, https://www.fsv-optik.de/tests/test.html ist der korrekte Link.

                Ohne Buttons kann das nicht funktionieren.

                Ich hab jetzt mal role="button" ergänzt. Das Ergebnis ist erwartungsgemäß das gleiche.

                Ein Blick in den Quelltext verrät, dass das Script am Ende des bodys eingebunden wird.

                Gut, daaaa hätt ich natürlich mal nachgucken können. Wenn ich meine test.js ebenfalls am Ende des Scripts einbinde, funktionierts.

                https://www.fsv-optik.de/tests/test3.html

                Auch das hätte ich natürlich längst mal versuchen können. Also liegts ja wohl an der Reihenfolge der Scripts bzw. eventuell daran, dass die test.js durch das DOMContentLoaded erst nach dem Seitenscript zur Verfügung steht?

                Hm, dann muss ich wohl nochmal überlegen, wann ich was wie einbinde. Ich würde das Script mit der Sortierfunktion gerne extern halten und über die index.php einbinden, weil das auf mehreren Seiten gebraucht wird. Und das spezielle Script würde ich gerne weiter direkt in der Seite einbinden, bzw. muss es, weil das auch auf PHP-Variablen zugreift.

                Wie schaffe ichs denn, dass die Reihenfolge ist: DOMContentLoaded -> main.js -> html-js. Wie macht man denn sowas? Bis jetzt hatte ich wohl eher immer Glück, dass alles funktioniert hatte wie es sollte.

                Schöne Grüße

                Nico

                1. Hallo Nico R.,

                  ja, genau ist das Problem. Durch deine docReady-Funktion wird die Zuweisung der EventListener an die th Elemente auf den nächsten Tick verschoben, und das ist erst nach dem Aufruf von button1.click().

                  Wenn Du Abhängigkeiten zwischen Modulen hast, brauchst Du typischerweise ein System zum Management von Modulen.

                  Die einfachste Möglichkeit ist es natürlich, test1.js am Ende des Body zu laden, so dass Du gar nicht darauf warten musst, ob das DOM fertig ist.

                  Übrigens lädst Du test1.js synchron. Das bedeutet, dass das DOM niemals auf "complete" oder "interactive" steht und immer der DOMContentLoaded Eventhandler genutzt wird.

                  Die zweite Möglichkeit, die mit dem Tod des Internet Explorer als allgemeingültig betrachtet werden kann, ist das defer-Attribut. Setze es an beiden Scripten. Sie werden dann in der Reihenfolge, in der die script-Elemente angetroffen wurden, ausgeführt, und zwar NACH dem Ende des DOM Parsers (also nach allen synchronen inline-Scripten) und VOR dem Werfen des DOMContentLoaded Events.

                  Die dritte Möglichkeit ist, wie gesagt, ein Modulmanagementsystem.

                  Good News: Dein Browser hat schon eins. Gib deinem inline-Script einfach das Attribut type="module" und lade das test-Script darin mit import. Damit kennt der Browser die Abhängigkeit und sorgt dafür, dass ein Script erst losläuft, wenn die Scripte bereit sind, mit von denen es abhängt.

                  <script type="module">
                     import "./test.js";
                     
                     const button1 = document.getElementById("button1");
                     const th = document.getElementById("th");
                     ... etc
                  </script>
                  

                  Das ./ vor test.js ist für ECMAScript-Module im Browser unbedingt nötig.

                  Damit erreichst Du dies:

                  • Inline-Script und test.js sind keine regulären Scripte mehr, sondern ECMAScript-Module.
                  • Module werden grundsätzlich im strict-mode ausgeführt und grundsätzlich so behandelt, als wäre das defer-Attribut gesetzt
                  • import wartet, bis test.js geladen ist und macht erst dann weiter

                  Allerdings kannst Du in einem Modul keine globalen Variablen mehr setzen, die andere Scripte dann verwenden. Das ist aber kein Fehler, sondern eine Gute Sache™️. Wenn ein Modul Code oder Daten bereitstellen soll, muss es sie exportieren. Ich würde Dich dafür gern auf unser Wiki verweisen, aber ich glaube, da ist noch ein klaffendes ToDo...

                  Zur Verringerung von Wartezeit kannst Du das inline-Modul in den head setzen. Dann lädt der Browser schonmal die Abhängigkeiten, während das DOM aufgebaut wird. Gestartet wird das Modul erst, wenn das DOM fertig ist.

                  Rolf

                  --
                  sumpsi - posui - obstruxi
                  1. Oooh, vielen Dank Rolf. Ich werd mir das in den nächsten Tagen nochmal in Ruhe zu Gemüte führen und versuchen, das umzusetzen. Notfalls würde ich nochmal nachfragen ;-)

                    Ich hatte mich zwischenzeitlich gerade einer anderen Sache gewidmet und hänge schon wieder. Liegt das am Wetter?

                    Schöne Grüße Nico

                    1. Hallo Nico,

                      Liegt das am Wetter?

                      im Zweifelsfall ja. Das wehrt sich am wenigsten. 🤪

                      Einen schönen Tag noch
                       Martin

                      --
                      Wo wir sind, ist das Chaos. Aber wir können leider nicht überall sein.
                2. Hallo Nico R.,

                  Ich hab jetzt mal role="button" ergänzt.

                  Die ARIA-Rolle legt nicht das Verhalten fest. Die Rolle legt lediglich fest, wie das Element von Assistenztechniken präsentiert wird. Äh. Würde. Wenn man nämlich überhaupt herankäme. Nicht sehende Personen verwenden typischerweise kein Zeigegerät. Weil sie nicht sehen, wohin es zeigt – duh.

                  Statt dessen verwenden sie eine Sprachsteuerung oder ein Gerät mit Tasten und ggf. Braille-Zeile (ob das eine Standardtastatur ist, würde ich eher nicht annehmen). Und mit solchen Eingabegeräten ist dein th Element nicht erreichbar. Dafür müsste es auch noch ein tabindex-Attribut bekommen, damit die Tab-Taste es anspringt. Und einen keydown-Handler, damit die ENTER Taste wie ein Klick behandelt wird.

                  Am Ende hast Du einen Button nachgebaut. Und vermutlich irgendwas vergessen. Dein Browser kann das besser, darum ist es sinnvoll, in das th-Element einen Button zu setzen.

                  Du kannst diesen Button so stylen, dass er das th Element ausfüllt und nicht wie ein doofer Standardbutton aussieht. Und schon ist Gunnar zufr weniger unzufrieden. Und deine Besucherinnen und Besucher auch.

                  Rolf

                  --
                  sumpsi - posui - obstruxi
                  1. Und schon ist Gunnar zufr weniger unzufrieden.

                    😀 Okay, da hab ich das mit dem role-Attribut falsch verstanden. Dann wohl doch überall einen Button einbauen :-(

                    Gruß Nico

                3. @@Nico R.

                  Ich hab jetzt mal role="button" ergänzt.

                  Am th-Element? Aua! Nicht machen! Damit ist das th-Element keine Tabellenkopfzelle mehr.

                  Außerdem darf role="button" nur an Elemente vergeben werden, die sich auch wie Buttons verhalten. Du müsstest also selbst implementieren, dass Buttons auch per Keyboard clickbar sind: per [return] bei keydown und per [space] bei keyup. Und nicht vergessen zu implementieren, dass Buttons auch per Sprachsteuerung clickbar sind …

                  Die gute Nachricht ist: Du musst das alles nicht selbst implementieren, denn das steckt alles schon in Browsern drin. Du musst nur das richtige HTML-Element verwenden: button.

                  An <th><button></button></th> führt kein Weg vorbei (jedenfalls kein guter).

                  🖖 Живіть довго і процвітайте

                  --
                  „Ukončete, prosím, výstup a nástup, dveře se zavírají.“
  3. Hallo nochmal zusammen,

    danke erstmal für eure bisherige Hilfe.

    @Rolf: Deine Vorschläge zur Einbindung habe ich versucht umzusetzen bzw. das externe Script auch von Hand ans Ende der Datei gesetzt. Aber offenbar ist das Problem doch noch ein anderes. Ich versteh es immer noch nicht so ganz. Hier nochmal der betreffende Teil des externen JS:

    if(tbl) { 
    	const sortSpalten = tbl.querySelectorAll("[data-sortierung]");
    
    	console.log("vor CLICK");
    	for(let i=0; i < sortSpalten.length; i++) {
    		console.log(sortSpalten[i]);
    		sortSpalten[i].addEventListener("click", function() {		
    				console.log("CLICK");
    		});
    	}
    	console.log("nach CLICK");
    }
    

    Alle Konsolenausgaben werden angezeigt, nur nicht "CLICK". Auch die th-Elemente werden angezeigt, es wird offenbar nur kein EventListener angebunden. In welchen Fällen kann das denn so sein?

    Schöne Grüße

    Nico

    1. Lieber Nico,

      nicht alle Deine Programmteile werden der Reihe nach ausgeführt. Hier die tatsächliche Reihenfolge:

      1. sortSpalten wird mit einer NodeList befüllt (alle th-Elemente).
      2. Konsole sagt „vor CLICK“
      3. Schleife geht die sortSpalten der Reihe nach durch
      4. Konsole sagt jeweils welches Obekt sortSpalten[i] gerade hat
      5. sortSpalten[i] bekommt einen EventListener registriert
      6. Schleife ist fertig
      7. Konsole sagt „nach CLICK“

      Jetzt müsstest Du nur noch die jeweilige EventListener-Funktion dadurch auslösen, dass Du auf das jeweilige th-Element klickst. Dann sollte die Konsole daraufhin brav „CLICK“ sagen.

      Liebe Grüße

      Felix Riesterer

    2. Hallo Nico R.,

      du hast also immer noch keine Buttons drin - aber das ist ein anderes Thema und hat mit dem Timing hier nichts zu tun.

      Was hast Du umgesetzt? Module mit import?

      Du erwartest die CLICK Ausgabe als Reaktion auf einen Aufruf der click-Methode auf einem th Element? Oder hast Du schon Buttons drin, registrierst die click-Handler auf den Buttons und rufst click() auf th auf? Das wäre … ungeschickt.

      Hast Du vor/hinter diesem click-Aufruf auch ein Logging gemacht, damit Du die Reihenfolge von Listener-Registrierung und Event-Auslösung sichtbar hast?

      Wenn Du das Timing im Griff und die Buttons eingebaut hast, müssten wir auch mal über Eventbubbling reden, womit Du nur einen click-Handler auf der Table brauchst und nicht einen pro Spalte.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Hallo Rolf, hallo Felix,

        entschuldigt bitte die Nichtreaktion. Ich hatte schlagartig keine Zeit mehr, mich darum zu kümmern. Ich habe die Funktion daher erstmal komplett gestrichen. Trotzdem danke für die Mühe. Eventuell komm ich nochmal drauf zurück, wenn ich mich etwas geordnet habe ;-)

        Schönen Abend

        Nico