jQuery - Element mit Klasse zuvor finden
ebody
- jquery
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
@@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 🖖
Hallo 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'));
Dieses li ist kein Vorfahr des button.
Bis demnächst
Matthias
Du suchst das vorhergehende Geschwister (sibling).
In Deinem Codepen funktioniert also:
$( document ).ready(function() {
function getValues(event){
$(this).parents('li').prev().css('background', 'red');
}
$('button').click(getValues);
});
@@Raketensuchmaschinenbediener
Du suchst das vorhergehende Geschwister (sibling).
Nein.
Sie/er sucht ein (oder alle?) vorige(s) Geschwister einer bestimmten Klasse.
LLAP 🖖
Achso. Naja. Da hab ich ihn falsch interpretiert.
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
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
@@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 🖖
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
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
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
@@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 🖖
Hallo Gunnar,
reitest Du noch auf deiner #id herum? Du hat die Gegenargumente gelesen?
Rolf
@@Rolf B
reitest Du noch auf deiner #id herum?
Nein.
Du hat die Gegenargumente gelesen?
Ja.
Dazu: It depends.
LLAP 🖖
@@Gunnar Bittersmann
Heute mal anstatt Mathematik zum Wochenende eine Runde DOM zum Wochenende? 😏
LLAP 🖖
@@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 🖖
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
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
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
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
@@ebody
Gibt es einen triftigen Grund, warum du jQuery verwendest und nich Vanilla-JavaScript?
LLAP 🖖
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...
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
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
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...
@@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 🖖
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...
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
@@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 🖖
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
@@Matthias Apsel
⬅️/➡️ zoomt rein/raus
⬆️/⬇️ bewegt die Kamera aus der ÄquatorebeneUnd am Handy?
Sowas gab’s damals noch nicht. 😉
Aber das wäre in der Tat eine nette Spielerei, da noch Touchgesten einzubauen.
LLAP 🖖
Hallo Gunnar Bittersmann,
⬆️/⬇️ bewegt die Kamera aus der Äquatorebene
Ohne dass sich der Blick auf den Jupiter ändert⁉️
Bis demnächst
Matthias
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...
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
@@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 🖖
@@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 🖖
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
@@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 🖖