znoerk: Existenz eines 'dynamisch' erzeugten Elements ermitteln

Hallo erstmal an alle Forumsmitglieder,

ich bin in der Firma rausgedeutet worden eine Webanwendung mittels Javascript zu manipulieren und ziemlicher Neuling.

Mit Funktionen, Schleifen usw. habe ich keine Probleme, wegen einiger Erfahrungen in anderen Sprachen.

Jedenfalls, auf die von der 'Fremdfima' bereits mitgelieferten, integrierten Javascripts habe ich keinen Einfluss.

Jetzt zu meiner eigentlichen Verständnisfrage:

Beim Klick auf ein bestimmtes Element fügt das 'Fremdjavascript' neue Elemente in die Seite ein. Eben gerade die, die ich manipulieren möchte/soll. Wie kann ich feststellen, ob die dynamisch erzeugten Elemente vorhanden sind ?

So wie ich das verstehe bzw. eben vielleicht nicht, kann ich ja auf ein (noch) nicht vorhandenes Element keinen EventListener setzen.

Wie bekomme ich es hin, trotzdem einen Event zu bekommen, der mir sagt, dass ich jetzt mit der Maipulation der 'neuen' Elemente loslegen kann ?

Verschwurbelter Gedanke:

Ich könnte ja auf das angeklickte/anzuklickende Element, das das Hinzufügen auslöst, einen EventListener('click') setzen. Aber der EventListener würde ja sofort feuern und es ist ja nicht gesagt, dass die 'neuen' Elemente da bereits ins DOM eingebaut worden sind, oder doch ?

Evtl. ist das ganz banal und ich stelle mich hier als Pfeifenaugust heraus ...

DOMContentLoaded ist da von den 'Fremdjavascripten' schon längst vorbei und außerdem gab's zu dem Zeitpunkt die 'neuen 'Elemente' ja eben auch noch gar nicht.

Bin leicht verwirrt. Vielleicht kann mich ja jemand der erfahrenen Spezialisten hier aus meiner Verwirrung befreien ?

Das wäre natürlich knorke ;-)

Vg achim

PS: Da fällt mir gerade noch was zu einer anderen Baustelle ein. Im Javascriptdebugger sehe ich, dass 'mein' Javascript nach Änderungen nicht neu geladen wurde/wird. Geänderte CSS-Dateien aber schon (wenn ich Firefox Strg+Shift+R mache um den Cache zu leeren). Woran liegt denn das ? Bzw. was mache ich da um meine Javascriptänderungen neu zu laden ?

  1. Moin znoerk,

    ich bin in der Firma rausgedeutet worden eine Webanwendung mittels Javascript zu manipulieren und ziemlicher Neuling.

    wo sagt man denn „rausgedeutet“?

    Wie kann ich feststellen, ob die dynamisch erzeugten Elemente vorhanden sind ?

    const e1 = document.querySelector('…');
    if (e !== null) {
        // (mindestens ein) Element existiert
    }
    
    const es = document.querySelectorAll('…');
    if (es.length > 0) {
        // (mindestens ein) Element existiert
    }
    

    So wie ich das verstehe bzw. eben vielleicht nicht, kann ich ja auf ein (noch) nicht vorhandenes Element keinen EventListener setzen.

    Und vor allem: Was für ein Event möchtest Du denn beobachten?

    Ich könnte ja auf das angeklickte/anzuklickende Element, das das Hinzufügen auslöst, einen EventListener('click') setzen. Aber der EventListener würde ja sofort feuern und es ist ja nicht gesagt, dass die 'neuen' Elemente da bereits ins DOM eingebaut worden sind, oder doch ?

    Auch wenn es auf unserer Wikiseite über mehrere Eventlistener nicht steht, werden die entsprechend der Reihenfolge des Hinzufügens abgearbeitet. Dein Eventhandler wird also nach dem des fremden Skripts ausgeführt. Sofern der fremde Eventhandler nicht asynchron läuft, müssten die gewünschten DOM-Knoten bereits vorhanden sein, wenn Deiner ausgeführt wird.

    Im Javascriptdebugger sehe ich, dass 'mein' Javascript nach Änderungen nicht neu geladen wurde/wird. Geänderte CSS-Dateien aber schon (wenn ich Firefox Strg+Shift+R mache um den Cache zu leeren). Woran liegt denn das ? Bzw. was mache ich da um meine Javascriptänderungen neu zu laden?

    Verwendest Du spezielle Caching-Header? Ansonsten wechsel einmal in den Netzwerk-Tab in den Browser-Developer-Tools und deaktivere den Cache. Dann wird beim Neuladen wirklich alles noch einmal neu geladen.

    Viele Grüße
    Robert

    1. Hi,

      danke erstmal für die Antwort.

      'Rausgedeutet' ist halt wenn der Scheffe auf eien dutet und sagt 'Sie machen das !'

      Das mit Zeugs mit QuerySelector/getElement(s)ByDings usw. ist klar.

      Das, was mir Kopfzerbrechen bereitet hat, ist wie ich herausfinde wann/ob die neune Elemente im DOM vorhanden sind.

      Wenn ich dich richtig verstanden habe, will du mir Folgeneds sagen:

      Wenn die Fremdjavascripte bei dem Klick einen Event erzeugen, in dessen Folge dann die 'neuen' Elemente' erzeugt/eingefügt werden und ICH dann auf das selbe Element noch mal einen Klick-EventListener setze, dann sollten in der Zwischenzeit die 'neuen' Element im DOM vorhanden sein, da MEIN Klick später kommt, als der ursprüngliche 'Fremdklick'.

      Richtig oder falsch verstanden ?

      Auf jeden Fall probiere ich das mal aus auch das PS mit dem Neuladen. Möglicherweise nerv ich dann nochmal ;-)

      Vielen Dank erstmal und schöne Grüße Achim

      1. Moin Achim,

        'Rausgedeutet' ist halt wenn der Scheffe auf eien dutet und sagt 'Sie machen das !'

        aus welcher Region stammt das denn?

        Wenn ich dich richtig verstanden habe, will du mir Folgeneds sagen:

        Wenn die Fremdjavascripte bei dem Klick einen Event erzeugen, in dessen Folge dann die 'neuen' Elemente' erzeugt/eingefügt werden und ICH dann auf das selbe Element noch mal einen Klick-EventListener setze, dann sollten in der Zwischenzeit die 'neuen' Element im DOM vorhanden sein, da MEIN Klick später kommt, als der ursprüngliche 'Fremdklick'.

        Korrekt.

        Viele Grüße
        Robert

        1. Klingt doch gediegen, finde ich. harhar

          Aber eigentlich bin ich gebürtiger Mittelfranke, da wos fast keine haddn T wie Dheodor oder P wie Baula gibd...

          1. Moin Achim,

            in anderen Teilen Deutschlands würde man „rausdeuten“ vermutlich mehr als Befehl ansehen 😀

            Ich finde Sprache interessant, vielen Dank für die Erläuterung!

            Viele Grüße
            Robert

            1. Naja, wenn der Scheffe auf eine deutet und das sagt, ist das doch meistens wie ein Befehl aufzufassen ? In meiner fast 40 jährigen Laufbahn in der Firma habe ich auf keinen Fall alle seine Befehle befolgt, manche sind offensichtlicher Käse, andere so gestrickt, dass er morgen wieder vergessen hat, dass er das mal haben wollte uswusw.

              Aber das hat mich jetzt halt interessiert und was neues zu lernen ist auch mit 65 immer noch nicht verkehrt. Schützt evtl. vor Altersdemenz ;-)

              Wobei das Thema nicht wirklich witzig ist, wie ich an meiner Mutter feststellen durfte.

              Aber ich fang an zu faseln.

              Übrigens, weiß nicht, ob du mitliest, aber ich habe dem Rolf geantwortet und das bezeiht sich teilweise auf deinen Ansatz.

              Ezt dud der Frange mal weiderforschen...

              1. Hallo znoerk,

                Ezt dud der Frange mal weiderforschen...

                Da dachte ich doch aus alter Karl May Erfahrung, dass diese Konsonantenaufweichung dybisch sägsisch wäre…

                Darfst Du uns verraten, welche Lib du da zähmen willst? Bzw. ob die Seite online erreichbar ist?

                Rolf

                --
                sumpsi - posui - obstruxi
                1. KARL MAY !!!!!! Was erlaube Rolf B. !!!! Wo doch Winneduu wie Flasche leer und auch noch verboten ist !!!!

                  Als Kind alle karlmayische Bücher gelesen. Hab mal vor zig Jahren einige davon wieder zu lesen angefangen. Ist ja ein derartig unglaublicher Schmarrn, dass ich das schnell zu den Akten gelegt habe. Muss ich mich ja fast aufregen, was für ein Quark das ist.

                  Ne, ist online nicht erreichbar. Ist eine Webanwendung für Buchhaltung/Finanzwesen/Controlling usw.

                  Deswegen kann ich euch auch deren Libs usw. nicht geben/zeigen. Ist urheberrechtlich geschützt.

                  achim

                  1. Hallo znoerk,

                    KARL MAY !!!!!! Was erlaube Rolf B. !!!! Wo doch Winneduu wie Flasche leer und auch noch verboten ist !!!!

                    Also dieses Verbot gehört verboten!!!

                    Muss ich mich ja fast aufregen, was für ein Quark das ist.

                    Hat keiner behauptet, dass Karl Mays Wildwest hochgeistige Literatur ist. Nach heutigen Maßstäben PC kann er eh nicht sein, da ist alles von white savior bis hin zu Antisemitismus drin. Zeitgeistkompatibel halt. War ja auch eh alles nur der Vorlauf zum Spätwerk, worin er uns den Edelmenschen erklären will. Nach 3 Seiten bin ich eingeschlafen…

                    Aber wenn Du die Reiseerzählungen für Schmarrn hältst, dann probiere besser nicht die Münchmeyer-Kolportagen (Originaltexte, Waldröschen bis Weg zum Glück), das ist so richtig wild. Unsittlicher Schund, hieß es damals 😂

                    Rolf

                    --
                    sumpsi - posui - obstruxi
                    1. Hihihi,

                      dass du das kennst ! 😃

                      'Die Liebe des Ulanen' (wenn ich mich recht erinnere) und 'Waldröschen' hab ich auch gelesen damals, in altdeutscher Schrift. An den Rest kann ich mich nicht mehr erinnern. War glaub ich vom Olms-Verlag in Hildesheim oder so. Die hatten damals so ne Auflage der Originaltexte. Und ja, die hatten die 'Schweinereien' auch drin. Tsssssss...so was auch...

                      achim

      2. Hallo znoerk,

        ob neue Elemente hinzugefügt werden, bekommst Du mit einem MutationObserver heraus.

        Aber das ist mühselig, und zumeist kann man das mit Event-Delegation (a.k.a. bubbling) einfacher lösen. Die Frage nach dem Event, das zu fangen ist, wird hier relevant. Die meisten Events "blubbern", d.h. sie werden nicht nur auf dem Element selbst signalisiert, sondern auch auf den Elternelementen.

        <body>
           <main>
              <button id="foo">CLOCK</button>
           </main>
        </body>
        

        Um einen Klick auf diesen Button zu verarbeiten, kannst Du den click-Handler auf dem Button, auf dem main-Element oder auf dem body-Element registrieren. Solange nicht irgendein Mistvieh event.stopPropagation() aufruft, blubbert das Event vom Button bis ganz nach oben und kann überall behandelt werden.

        Also beispielsweise:

        document.body.addEventListener("click", pfeifenAugust);
        
        function pfeifenAugust(clickEvent) {
           ...
        }
        

        Du musst dann lediglich herausfinden, ob das click-Event auf einem Element gefeuert wurde, das Dich interessiert. Dafür dient die target-Eigenschaft des Eventobjekts, das der Pfeifenaugust übergeben bekommt. Darin steht, auf welchem Element das Event ausgelöst wurde.

        Das ist etwas tricky. Wenn Du auf Buttons reagieren willst, dann KÖNNTEST du testen, ob event.target instanceof HTMLButtonElement erfüllt ist. Oder event.target.tagName == "BUTTON". Es gibt aber auch fancy buttons, die HTML enthalten. Klickt man nun auf ein HTML-Element im Button, dann ist dieses Element das event.target. Deshalb muss man erstmal den Button suchen:

        function pfeifenAugust(clickEvent) {
           const button = clickEvent.target.closest("button");
           if (!button)      /* das war kein Button */
              return;
        
           if (/* ist das ein relevanter button */) {
               /* verarbeiten */
           }
        }
        

        Auf diese Weise ist es Dir komplett wurscht, ob drei oder drölf Buttons ergänzt wurden, du fängst sie alle.

        Es sei denn, du möchtest aktiv werden, bevor der Handler von der Lib aktiv wird. Oder das eingangs erwähnte Mistvieh hat das Bubbling gestoppt. Dann könnte es hilfreich sein, nicht in die Bubbling-Phase einzugreifen, sondern in die Capture-Phase. Guck dafür mal im Grundlagenartikel zur Ereignisverarbeitung im Abschnitt über Bubbling und Capturing nach.

        Rolf

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

          das mit target und currentTarget und das bubbling habe ich soweit gelesen und auch verstanden. Ein Vertändnisproblem hatte ich bei der Capture-Phase.

          Aber das Problem ist tatsächglich ein zeitliches, wie ich gerade festgestellt habe:

          Habe das mal nach der Anweisung von Robert B. (erste Antwort) gemacht. Und für den auslösenden Button noch einen addEventListener('click', event => neuesElementManipulieren) draufgesetzt.

          Und im Debugger dann einen Breakpunkt in neuesElementManipulieren(){...} auf das getElementById('id-neu-erzeugtes-div') gesetzt.

          Wenn ich nun auf dem Breakpoint ein paar Sekunden warte, bekomme ich das neue DIV zurück, wenn ich das Script OHNE Breakpoint laufen lasse, kommt 'null' zurück.

          D. h. für mich, in meiner Ahnungslosigkeit, dass das Erzeugen des neuen Elements länger dauert, da bin ich schon vorher längst in meinem eventListener und frage nach einem Element, das sozusagen gerade erst im Entstehen ist.

          Da kommt der Laie dann auf so komische Ideen halt einfach einen setInterval zu versuchen bis beim getElementById nicht mehr 'null' zurückkommt. Aber das klingt für mich selber jetzt nach absoluter Spaghettiprogrammierung...

          Hmmmm, grübelgrübel, mal weiterforschen...

          Vielen Dank erstmal für die Antwort

          Vg achim

          1. Hallo znoerk,

            Beim Klick auf ein bestimmtes Element fügt das 'Fremdjavascript' neue Elemente in die Seite ein. Eben gerade die, die ich manipulieren möchte/soll. Wie kann ich feststellen, ob die dynamisch erzeugten Elemente vorhanden sind ?

            Vielleicht habe ich das ja nicht richtig verstanden. Das Fremdscript fügt ein, und nach dem Einfügen möchtest Du diese Elemente „nachbearbeiten“?

            Es wäre dann die Frage, ob das Fremdscript vielleicht asynchron arbeitet. Es könnte zum Beispiel einen Serverzugriff machen, bevor es seine Elemente einfügt. Das sieht man im Netzwerktrace. Es könnte auch einfach stumpf einen Mikrotask absetzen, oder per setTimeout einen Makrotask, um möglichst schnell die Eventloop wieder freizugeben. Dann nützt es Dir nichts, auf den gleichen click zu lauern wie das Fremdscript.

            In diesem Fall wäre ein MutationObserver vermutlich die einzige Möglichkeit. Oder halt der dicke Daumen - ein Serverzugriff dauert so und so lange, und dann einfach mal loslegen. Kannst Du die neuen Elemente erkennen, wenn sie da sind? Und dann ggf. mit einer Klasse oder einem data-Attribut markieren, dass Du sie schon „behandelt“ hast?

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Ja, WENN sie da sind kann ich dran herumpfuschen. Aber im normalen Ablauf (ohne Breakpunkt) sind sie eben noch nicht da...

              Mit deinen Ausführungen hast mich jetzt in die auf dem falschen Fuss erwischt. Bin ja eigentlich Anfänger.

              Serverzugriff, Mikrotask, SetTimeout und Makrotask... So weit bin ich vermutlich noch lange nicht. Da müsste ich mir erst mal die Grundlagen aneignen um herauszufinden, was die 'Fremdscripte' da eigentlich so alles treiben.

              achim

  2. Lieber znoerk,

    Beim Klick auf ein bestimmtes Element fügt das 'Fremdjavascript' neue Elemente in die Seite ein. Eben gerade die, die ich manipulieren möchte/soll.

    inwiefern willst Du sie „manipulieren“? Was genau willst Du denn mit ihnen erreichen?

    Wie kann ich feststellen, ob die dynamisch erzeugten Elemente vorhanden sind ?

    Nur mit dem MutationObserver kannst Du sicher bestimmen, welche Elemente verändert (oder neu eingefügt) wurden. Dann kannst Du sie manipulieren. Das geschieht übrigens so ähnlich in unserem AntiTerrorBanner-Script-Artikel.

    Liebe Grüße

    Felix Riesterer