ebody: jQuery - Element mit Klasse zuvor finden

Hallo,

ich probiere gerade verschiedene Sachen, um Elemente zu selektieren. Ich möchte z.B. ein Element mit einer Klasse vor dem Element finden, durch welches die Funktion ausgelöst wurde. In dem Beispiel ein Button.

https://codepen.io/ebody/pen/NWqMqbQ?editors=1010

Das vorherige ul oder form Element zu finden funktioniert.

// console.log($(this).parents('ul'));
// console.log($(this).parents('form'));

Aber möchte ich ein li Element mit der Klasse .test finden, funktioniert es nicht. Weiß jemand warum das nicht funktioniert? console.log($(this).parents('li.test'));

Gruß ebody

  1. @@ebody

    Aber möchte ich ein li Element mit der Klasse .test finden, funktioniert es nicht. Weiß jemand warum das nicht funktioniert? console.log($(this).parents('li.test'));

    Wie so oft dürfte es helfen, sich $(this) ausgeben zu lassen.

    Hat dieses Element einen li-Vorfahren der Klasse test?

    LLAP 🖖

    --
    Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
  2. Hallo ebody,

    https://codepen.io/ebody/pen/NWqMqbQ?editors=1010

    Aber möchte ich ein li Element mit der Klasse .test finden, funktioniert es nicht. Weiß jemand warum das nicht funktioniert? console.log($(this).parents('li.test'));

    Dieses li ist kein Vorfahr des button.

    Bis demnächst
    Matthias

    --
    Du kannst das Projekt SELFHTML unterstützen,
    indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
  3. Du suchst das vorhergehende Geschwister (sibling).

    https://api.jquery.com/prev/

    In Deinem Codepen funktioniert also:

    $( document ).ready(function() {
      function getValues(event){
        $(this).parents('li').prev().css('background', 'red');
      }
      $('button').click(getValues);
      
    });
    

    https://codepen.io/ebody/pen/NWqMqbQ?editors=1010

    1. @@Raketensuchmaschinenbediener

      Du suchst das vorhergehende Geschwister (sibling).

      https://api.jquery.com/prev/

      Nein.

      Sie/er sucht ein (oder alle?) vorige(s) Geschwister einer bestimmten Klasse.

      LLAP 🖖

      --
      Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
      1. Achso. Naja. Da hab ich ihn falsch interpretiert.

  4. So scheint es zu funktionieren:

    console.log($(this).parents().find('li.test'));
    

    Egal wie tief verschachtelt das auslösende Element (this) ist, es wird jedes li Element mit der Klasse .test zuvor gefunden.

    console.log($(this).parents().find('.test'));
    

    Damit würde jedes Element mit der Klasse .test zuvor gefunden werden.

    Gruß ebody

    1. Hallo ebody,

      das würde ich spezifscher machen, mit .closest('ul') statt .parents() oder .parents('ul'). Du hast doch eigentlich eine sehr konkrete Vorstellung, wo Du hinnavigieren wilst. Und dann solltest Du das auch zielgenau tun. Denn

      $(this).parents().find('li.test').remove();
      

      ist letztlich nur eine verkappte Variante von:

      $('li.test').remove();
      

      und könnte auf einer größeren Seite zu ärgerlichen Ergebnissen führen.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. @@Rolf B

        $('li.test').remove();
        

        und könnte auf einer größeren Seite zu ärgerlichen Ergebnissen führen.

        Wenn man an ein bestimmtes Element ranwill, sollte man dem eine ID geben und darüber selektieren.

        LLAP 🖖

        --
        Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
        1. Hallo Gunnar,

          Jein. Das kann man oft tun, aber nicht immer.

          Wenn ich auf einer Webseite mehrere Listen habe, in denen ein Button ist und dieser Button bei Klick ein Element in dieser Liste suchen und damit etwas tun soll (es gibt sicherlich auch andere und bessere Fälle für sich wiederholende Muster auf Webseiten), dann muss ich entweder den Handler mit der ID parametrieren, oder ich schreibe ihn so, dass er mit relativer Navigation arbeitet und keine ID braucht. Ohne ID ist mMn besser wiederverwendbar.

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Eine ID könnte ich nur einmal vergeben. Was ist, wenn ich z.B. 3 Formulare habe, aber nur aus dem Formular ein Element mit der Klasse .test finden möchte, dessen Button geklickt wurde?

            Ich habe bisher nur diese Möglichkeit gefunden und es funktioniert: $(this).parents('form').find('li.test').remove();

            Gruß ebody

            1. Hallo ebody,

              einverstanden, das ul Element ist nicht der beste Referenzpunkt. Ein Button als Teil einer Liste ist auch merkwürdig.

              Trotzdem solltest Du nicht parents nehmen - das rennt die vollständige Elternkette durch und filtert auf <form> Elemente. Logisch ist das ok, weil Forms nicht geschachtelt werden dürfen, aber die Suche rennt unnötig weit. Daher mein Vorschlag mit closest, der hört beim ersten Form auf und drückt damit das aus, was Du tatsächlich willst.

              Das ist eine Grundsatz-Sache. Code, der voraussetzt, dass bestimmte Dinge in den Daten vorkommen (oder nicht vorkommen), damit er korrekt funktioniert, ist schlechter als solcher Code, der davon nicht abhängt. Natürlich gibt es immer Grundvoraussetzungen, die die Daten erfüllen müssen damit Code sie verarbeiten kann, aber je weniger man voraussetzen muss, um so besser.

              Rolf

              --
              sumpsi - posui - obstruxi
              1. @@Rolf B

                Trotzdem solltest Du nicht parents nehmen

                Richtig, aber …

                Daher mein Vorschlag mit closest, der hört beim ersten Form

                … eins ist so unsinnig wie das andere.

                Heute mal anstatt Mathematik zum Wochenende eine Runde DOM zum Wochenende? 😏

                LLAP 🖖

                --
                Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
                1. Hallo Gunnar,

                  reitest Du noch auf deiner #id herum? Du hat die Gegenargumente gelesen?

                  Rolf

                  --
                  sumpsi - posui - obstruxi
                  1. @@Rolf B

                    reitest Du noch auf deiner #id herum?

                    Nein.

                    Du hat die Gegenargumente gelesen?

                    Ja.

                    Dazu: It depends.

                    LLAP 🖖

                    --
                    Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
                2. @@Gunnar Bittersmann

                  Heute mal anstatt Mathematik zum Wochenende eine Runde DOM zum Wochenende? 😏

                  Auflösung des Rätsels

                  LLAP 🖖

                  --
                  Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
            2. @@ebody

              Was ist, wenn ich z.B. 3 Formulare habe

              Dann kannst du event delegation nutzen: Du registriert einen Eventhandler für ein Element oben im DOM:

              document.body.addEventListener('click', event => {});
              

              Darin fragst du ab, ob das click-Event durch einen Button ausgelöst wurde:

              document.body.addEventListener('click', event => {
                if (event.target.nodeName === 'BUTTON') {}
              });
              

              Wenn du noch andere Buttons mit anderen Funktionen auf der Seite hast, musst du die Bedingung natürlich spezifischer machen, bspw. über eine Klasse der Buttons.

              Wenn der click nun durch einen Button ausglöst wurde, soll der gerade an anderer Stelle gezeigte Code ausgeführt werden:

              document.body.addEventListener('click', event => {
                if (event.target.nodeName === 'BUTTON') {
                  const testElement = event.target.form.querySelector('.test');
                  testElement.parentNode.removeChild(testElement);
                }
              });
              

              Fertig.

              Event delegation geht übrigens auch mit jQuery. Aber man braucht jQuery heutzutage i.A. nicht mehr.

              LLAP 🖖

              --
              Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
              1. Vielen Dank an alle für die vielen Infos!

                Ich habe hier eine Javascript Variante verwendet und den empfohlenen Code verwendet. Etwas abgeändert, aber es ist wie gesagt auch, um verschiedene Dinge auszuprobieren und Notizen zu machen.

                Anderen die hier mitlesen, helfen die auskommentierten Sachen evtl. auch etwas.

                Gruß ebody

              2. Hallo,

                hat es einen bestimmten Grund, dass du "nodeName" verwendet hast und nicht z.B. "type" oder "tagName"?

                if (event.target.nodeName === 'BUTTON') {}

                if (event.target.type === 'button') {}

                if (event.target.tagName === 'BUTTON') {}

                Oder wären die anderen beiden Varianten auch ok und hätten keine Vor- oder Nachteile?

                Gruß ebody

                1. Hallo ebody

                  if (event.target.nodeName === 'BUTTON') {}

                  if (event.target.type === 'button') {}

                  if (event.target.tagName === 'BUTTON') {}

                  Oder wären die anderen beiden Varianten auch ok und hätten keine Vor- oder Nachteile?

                  Die Eigenschaften nodeName und tagName sind gleichwertig. Letztere ist nur für Elemente definiert und somit spezieller. Die Verwendung von tagName macht den Code also ein klein wenig ausdrucksstärker.

                  Die Eigenschaft type reflektiert das entsprechende Attribut des button-Elements. Während deine Bedingungen mit nodeName und tagName für alle Buttons true ergeben, passiert das bei der Prüfung mit type nur dann, wenn der Button auch tatsächlich den Typ button hat.

                  Wenn du wissen willst, ob die Eigenschaft target einen Button referenziert, kannst du das auch mit dem Operator instanceof prüfen:

                  if (event.target instanceof HTMLButtonElement) {}
                  

                  Viele Grüße

        2. Hello @Gunnar Bittersmann,

          $('li.test').remove();
          

          und könnte auf einer größeren Seite zu ärgerlichen Ergebnissen führen.

          Wenn man an ein bestimmtes Element ranwill, sollte man dem eine ID geben und darüber selektieren.

          Du kannst nicht voraussetzen, dass das HTML und das JavaScript oder CSS immer ausschließlich zusammengehören. Wenn man universell verwendbare Scripte oder Stylesheets erstellen will, ist die "relative Methode" der Selektierung sicherlich besser.

          Die feste Koppelung an eine ID ist ungefähr genauso unpraktisch, wie die Verwendung von globalen Variablen für Funktionen in der imperativen Programmierung.

          Glück Auf
          Tom vom Berg

          --
          Es gibt nichts Gutes, außer man tut es!
          Das Leben selbst ist der Sinn.
  5. @@ebody

    Gibt es einen triftigen Grund, warum du jQuery verwendest und nich Vanilla-JavaScript?

    LLAP 🖖

    --
    Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
    1. Hi there,

      @@ebody

      Gibt es einen triftigen Grund, warum du jQuery verwendest und nich Vanilla-JavaScript?

      Das wollte ich ebody auch schon fragen. Abgesehen davon, daß jQuery ohnehin weitgehend überflüssig ist verstellt es gerade bei den von ebody beschriebenen Sachverhalten nur die Sicht auf die Dinge. Afaik hat er "Problem" mit dem DOM, nicht mit jQuery, wie er offenbar glaubt...

      1. Hallo klawischnigg,

        mit DOM Navigation haben viele Leute Probleme, da hilft jQuery nicht, das stimmt.

        Er darf nur zur Vanillesauce die Polystreusel nicht vergessen, sonst schmeckt sie nicht, wenn man sie auf die IE-Pampe gießt.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Was bedeutet "Problem mit dem DOM"? Ich glaube nicht, dass ich damit wirklich ein Problem habe und nicht verstehe, wie man selektiert.

          Aber dennoch gibt es manchmal Fälle, wo man erstmal die richtigen Befehle für finden muss, obwohl man genau weiß, was man selektieren möchte.

          Warum nicht jQuery? Ich habe zur Zeit damit einfach mehr Übung als mit Vanilla-JavaScript.

          Gruß ebody

          1. Hi there,

            Warum nicht jQuery? Ich habe zur Zeit damit einfach mehr Übung als mit Vanilla-JavaScript.

            Weil es die Ladezeiten unnötig aufbläht, weil es den Programmablauf unter Umständen dramatisch verlangsamt und weil es die Sicht auf die Probleme die mit dem Programmieren zusammenhängen komplett verstellen kann. Gerade für letzteres ist Dein Problem ein gutes Beispiel: Du suchst irgendwelche "jQuery-Befehle" anstelle einfach einen Blick in das Node-Objekt zu werfen.

            Versteh' mich bitte nicht falsch, das ist kein Vorwurf, es ist aus meiner Sicht halt einfach schlechter Stil, einfach noch eine zusätzliche "Schicht" zwischen Maschine und Programmiersprache einzuziehen, auch und besonders, weil der einstmals große Vorteil von jQuery, nämlich die Überwindung von Browserinkompatibilitäten, mittlerweile weggefallen ist...

            1. @@klawischnigg

              Ich stimme in fast allem mit dir überein, außer:

              es ist aus meiner Sicht halt einfach schlechter Stil, einfach noch eine zusätzliche "Schicht" zwischen Maschine und Programmiersprache einzuziehen

              Die zusätzliche Schicht ist eher zwischen Programmiersprache und Anwendung, oder?

              Ich hatte mal an einer 3D-Grafik-Anwendung mitgewirkt und war heilfroh, dass da zwischen OpenGL und der Anwendung mit OpenSG noch eine zusätzliche Schicht war.

              Aufs Web übertragen: Man will sicher auch nicht mit WebGL hantieren, sondern eine zusätzliche Schicht wie Three.js nutzen.

              LLAP 🖖

              --
              Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
              1. Hi there,

                Ich stimme in fast allem mit dir überein, außer:

                es ist aus meiner Sicht halt einfach schlechter Stil, einfach noch eine zusätzliche "Schicht" zwischen Maschine und Programmiersprache einzuziehen

                Die zusätzliche Schicht ist eher zwischen Programmiersprache und Anwendung, oder?

                Stimmt, es geht in die andere Richtung...

              2. Hallo,

                Ich hatte mal an einer 3D-Grafik-Anwendung mitgewirkt und war heilfroh, dass da zwischen OpenGL und der Anwendung mit OpenSG noch eine zusätzliche Schicht war.

                das ist natürlich von Fall zu Fall unterschiedlich. Als ich noch regelmäßig Windows-Anwendungen geschrieben habe (das ist rund 10 Jahre her), da habe ich immer bevorzugt ohne eine zusätzliche Schicht zwischen der Applikation und dem Windows-API gearbeitet. Meine Erfahrung war, dass die die Angelegenheit meistens eher verkomplizieren als vereinfachen.

                Aufs Web übertragen: Man will sicher auch nicht mit WebGL hantieren, sondern eine zusätzliche Schicht wie Three.js nutzen.

                Möglich. Kann ich nicht beurteilen.

                Ciao,
                 Martin

                --
                Ich stamme aus Ironien, einem Land am sarkastischen Ozean.
                1. @@Der Martin

                  Aufs Web übertragen: Man will sicher auch nicht mit WebGL hantieren, sondern eine zusätzliche Schicht wie Three.js nutzen.

                  Möglich. Kann ich nicht beurteilen.

                  Ich hatte erst den Ansporn, was mit WebGL zu machen. Nachdem ich mir das etwa eine Stunde reingezogen habe und einen Einblick hatte, wie umständlich das ist, war ich bei Three.js.

                  Damit geht’s dann recht fix, beim Jupiter!

                  ⬅️/➡️ zoomt rein/raus
                  ⬆️/⬇️ bewegt die Kamera aus der Äquatorebene

                  Jupiter und Mondbahnen sind im selben Maßstab, die Monde sind zweifach vergrößert, damit sie zu sehen sind.
                  Rotation und Umlaufzeiten 20fach gerafft

                  LLAP 🖖

                  --
                  Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
                  1. Hallo Gunnar Bittersmann,

                    Damit geht’s dann recht fix, beim Jupiter!

                    Cool.

                    ⬅️/➡️ zoomt rein/raus
                    ⬆️/⬇️ bewegt die Kamera aus der Äquatorebene

                    Und am Handy?

                    Bis demnächst
                    Matthias

                    --
                    Du kannst das Projekt SELFHTML unterstützen,
                    indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
                    1. @@Matthias Apsel

                      ⬅️/➡️ zoomt rein/raus
                      ⬆️/⬇️ bewegt die Kamera aus der Äquatorebene

                      Und am Handy?

                      Sowas gab’s damals noch nicht. 😉

                      Aber das wäre in der Tat eine nette Spielerei, da noch Touchgesten einzubauen.

                      LLAP 🖖

                      --
                      Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
                  2. Hallo Gunnar Bittersmann,

                    ⬆️/⬇️ bewegt die Kamera aus der Äquatorebene

                    Ohne dass sich der Blick auf den Jupiter ändert⁉️

                    Bis demnächst
                    Matthias

                    --
                    Du kannst das Projekt SELFHTML unterstützen,
                    indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
                    1. Hi there,

                      ⬆️/⬇️ bewegt die Kamera aus der Äquatorebene

                      Ohne dass sich der Blick auf den Jupiter ändert⁉️

                      Kann ich nicht nachvollziehen, bei mir verschiebt sich auch die Jupiter-Textur...

                    2. Hallo Matthias Apsel,

                      Ohne dass sich der Blick auf den Jupiter ändert⁉️

                      Stimmt ja gar nicht! Ich hab nur schief geguckt.

                      Bis demnächst
                      Matthias

                      --
                      Du kannst das Projekt SELFHTML unterstützen,
                      indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
                  3. @@Gunnar Bittersmann

                    Rotation und Umlaufzeiten 20fach gerafft

                    Dafür kommt mir die Simulation aber zu schnell vor.

                    Mal nachgemessen: es ist etwa 8000fach, d.h. eine Sekunde in der Simulation entspricht etwas über 2 Stunden in der Realität.

                    LLAP 🖖

                    --
                    Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
          2. @@ebody

            Warum nicht jQuery?

            Zusätzlich zu dem, was @klawischnigg sagte: Weil jQuery dazu verleitet, Unsinn zu machen.

            Wenn du von einem Button aus das zugehörige Formular haben willst, brauchst du dich nicht durchs DOM nach oben hangeln. Das gibt es nämlich bereits in der form-Eigenschaft des Buttons (HTMLButtonElement).

            Wenn event.target im Eventhandler (dazu an anderer Stelle mehr) der geclickte Button ist, dann ist event.target.form das zugehörige Formular.

            Darin kann man nun das erste Element der Klasse 'test' selektieren: event.target.form.querySelector('.test')

            Damit kannst du dann machen, was du willst, z.B. es entfernen:

            const testElement = event.target.form.querySelector('.test');
            testElement.parentNode.removeChild(testElement);
            

            LLAP 🖖

            --
            Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
            1. Hallo Gunnar

              Damit kannst du dann machen, was du willst, z.B. es entfernen:

              const testElement = event.target.form.querySelector('.test');
              testElement.parentNode.removeChild(testElement);
              

              So, oder ohne Umweg über den Elternknoten mit der Methode remove direkt auf dem Element, das entfernt werden soll.

              event.target.form.querySelector('.test').remove();
              

              Viele Grüße

              1. @@Shadow of the Vampire

                So, oder ohne Umweg über den Elternknoten mit der Methode remove direkt auf dem Element, das entfernt werden soll.

                Ah ja, danke. War mir doch so, dass man das jetzt auch direkt machen kann (in modernen Browsern; nicht im IE).

                Aber im IE funktioniert mein ganzer gezeigter Code mit const und Pfeilfunktionen sowieso nicht; der müsste transpiliert werden. (Hiel nicht r und l velwechsern).

                MDN listet einen Polyfill, der dann auch wieder über parentNode.removeChild() geht.

                LLAP 🖖

                --
                Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.