Matthias Apsel: JQuery parents(Selektor)

Om nah hoo pez nyeetz, alle!

Die Zeile $('code br').parents('code').addClass('block'); sollte nach meinem Verständnis

  • alle br-Elemente innerhalb von code-Elementen suchen
  • deren Vorfahren-Elementen vom Typ code die Klasse block verpassen

In diesem Forum sorgt sie als

$(document).ready(function(){  
	$('code br').parents('code').addClass('block'); //Codeblöcke hervorheben  
})

für die Hervorhebung von Codeblöcken.

Manchmal jedoch versagt der Code.

foo {  
  bar: quz;  
}

wird nicht hervorgehoben, das zugrunde liegende HTML ist

<code class="css" title="css">  
  <span class="element-selector">  
    foo  
  </span>  
  <span class="declarations">  
    {  
    <br>  
    <span class="unknown-property">  
      bar  
      <span class="property-value">  
        : quz;  
      </span>  
    </span>  
    <br>  
    }  
  </span>

</code>

Hier bekommt das span.declarations die Klasse block. (getestet JQuery 1.10.2, FF 26)

Offensichtlich ist das immer dann der Fall, wenn ein span-Element mit br noch „ältere“ Geschwister ohne br hat.

Ist das ein JQuery-Fehler?
Ist das ein Layer8-Fehler?

Matthias

--
Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Dom und Domina.

  1. Om nah hoo pez nyeetz, Matthias Apsel!

    Manchmal jedoch versagt der Code.

    foo {

    bar: quz;
    }

    
    >   
    > wird nicht hervorgehoben,  
      
    allerdings nur in der Vorschau, der abgesendete Beitrag ist in Ordnung.  
      
    Matthias
    
    -- 
    Der Unterschied zwischen Java und JavaScript ist größer als der zwischen [Zug und Zugang](http://selfhtml.apsel-mv.de/java-javascript/index.php?buchstabe=Z#zug).  
    ![](http://www.billiger-im-urlaub.de/kreis_sw.gif)  
    
    
    1. Om nah hoo pez nyeetz, Matthias Apsel!

      allerdings nur in der Vorschau, der abgesendete Beitrag ist in Ordnung.

      Der Fehler taucht auch in archivierten Beiträgen auf.

      Matthias

      --
      Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Nut und Nutella.

      1. Ich sehe das Problem auf der Archivseite, kann es aber nicht selbst nachvollziehen.

        $('code br').parents('code').addClass('block'); //Codeblöcke hervorheben

        In dem Code von archiv.js steht übrigens abweichend:

        $('code br').parent($('code')).addClass('block');

        Wenn ich auf der Konsole erstgenannten Befehl ausführe, bekomme ich die korrekten code-Elemente.

        1. Om nah hoo pez nyeetz, molily!

          $('code br').parent($('code')).addClass('block');

          Wie immer ein zielführender Hinweis. Daran lags.

          Danke.
          Matthias

          --
          Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Quark und Quarks.

  2. $(document).ready(function(){

    $('code br').parents('code').addClass('block'); //Codeblöcke hervorheben
    })

      
    Mal langsam... Du suchst nach allen br die Nachfahre von code sind. Dann suchst du alle code die Eltern von br sind und denen gibst du die Klasse block. Somit hat jeder "code" der ein br in sich trägt (egal in welcher tiefe) die Klasse block.  
      
    Vielleicht ist das zuviel für das arme jquery.  
    Versuch doch mal einen anderen Selektor. Wie wärs mit code.css. Dann kannst du dir auch das parent Zeugs sparen.  
      
    Gruß  
    Ideen lieferant  
    T-Rex
    
    1. Om nah hoo pez nyeetz, T-Rex!

      Vielleicht ist das zuviel für das arme jquery.

      Der Fehler taucht in der Vorschau und bei archivierten Beiträgen auf. In der Forumshauptdatei passt es.

      Versuch doch mal einen anderen Selektor. Wie wärs mit code.css. Dann kannst du dir auch das parent Zeugs sparen.

      Der Gedanke war, einzeilige Codeschnippsel von

      `mehrzeiligen  
      Codeschnippseln`
      

      unterscheiden zu können.

      Matthias

      --
      Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Kart und Kartoffelsalat.

      1. Mehrere Zeilen können doch auch durch einfachen Textumbruch entstehen. Dann hast du auch mehrer Zeilen aber eventuell nicht einen <br> drin.
        Deshalb würde ich bei diesem Beispiel auf die Höhe der Box gehen. Wenn diese größer als äh... sagen wir X px groß ist, handelt es sich um mehrere Zeilen. Jaja ich weiß unterschiedlicher Zoom und so weiter... ist ja nur eine Idee. Bin noch beim Brainstorming.
        Oder du guckst auf Serverseite ob mehrer <br> gesetzt sind. Irgendwie müssen die ja dahin kommen wo sie sind.

        Gruß
        Brain gestürmter
        T-Rex

        1. Hi,

          Mehrere Zeilen können doch auch durch einfachen Textumbruch entstehen. Dann hast du auch mehrer Zeilen aber eventuell nicht einen <br> drin.
          Deshalb würde ich bei diesem Beispiel auf die Höhe der Box gehen. Wenn diese größer als äh... sagen wir X px groß ist, handelt es sich um mehrere Zeilen. Jaja ich weiß unterschiedlicher Zoom und so weiter...

          das könnte man ja lösen, indem man die line-height berücksichtigt:
          Zeilenzahl ≈ height / line-height

          cu,
          Andreas

          --
          Warum nennt sich Andreas hier MudGuard?
          O o ostern ...
          Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
  3. Hi,

    Die Zeile $('code br').parents('code').addClass('block'); sollte nach meinem Verständnis

    [code lang=html]<code class="css" title="css">
      <span class="element-selector">
        foo
      </span>
      <span class="declarations">
        {
        <br>

    code ist hier nicht parent von br, sondern grandparent. parent des br ist das span.

    Bei einer Methode namens parents würde ich davon ausgehen, daß sie sich nicht um grandparents oder noch weiter zurückliegende Vorfahren kümmert.
    Gibt es eine Methode namens ancestors?

    (ich geb zu, ich hab keine Ahnung, wie jquery das handhabt ...)

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    O o ostern ...
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
    1. (ich geb zu, ich hab keine Ahnung, wie jquery das handhabt ...)

      Nene Matthias hat schon recht. Wenn das stimmt was er sagt und davon ist auszugehen, liegt ein Fehler in jQuery vor. Parents geht alle vorfahren durch und liefert die zurück auf die, der Selector passt. In dem Fall würde man erwarten das alle "code" zurück geliefert werden.

      Gruß
      w(right)u
      T-Rex

      1. Nene Matthias hat schon recht.

        Sein Problem ist doch, daß das span-Element geliefert wird, welches kein code-Element ist?!

        Parents geht alle vorfahren durch und liefert die zurück auf die, der Selector passt.

        Die direkten Eltern aller selektierten Elemente.

        1. Parents geht alle vorfahren durch und liefert die zurück auf die, der Selector passt.
          Die direkten Eltern aller selektierten Elemente.

          Hmm, hier steht es dann wieder so, als würden doch alle Elternelemente geliefert werden.
          Das hliest sich hier anders.

        2. Hi,

          Nene Matthias hat schon recht.
          Sein Problem ist doch, daß das span-Element geliefert wird, welches kein code-Element ist?!

          Dann heißt die Methode in jQuery eindeutig falsch, wenn sie ancestors liefert, aber parents heißt ...

          cu,
          Andreas

          --
          Warum nennt sich Andreas hier MudGuard?
          O o ostern ...
          Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
          1. Dann heißt die Methode in jQuery eindeutig falsch, wenn sie ancestors liefert, aber parents heißt ...

            Hmm, warum? Höchstens wegen dem s in parents. Das beziehe ich hier allerdings auf die Mehrzahl der Elemente der Ursprünglichen Selection. Also die ElterN der viele Elemente in der Selection.

            Jetzt liefert parents ja aber überhaupt nicht nur die Eltern, sondern auch die Eltern der Eltern und auch wieder deren Eltern bis hinauf zum root-Element. Hier finde ich die Bezeichnung parents falsch.
            Auch die Beschreibung ist meiner meinung nach verkehrt.
            "Get the ancestors of each element in the current set of matched elements, optionally filtered by a selector."
            Erst in der Beschreibung von parents in closest beschreibt meiner Meinung nach die Implementierung.
            "Travels up the DOM tree to the document's root element, adding each ancestor element to a temporary collection; it then filters that collection based on a selector if one is supplied "

            1. Auch die Beschreibung ist meiner meinung nach verkehrt.
              "Get the ancestors of each element in the current set of matched elements, optionally filtered by a selector."

              Was ist daran verkehrt?

              Mathias

              1. Auch die Beschreibung ist meiner meinung nach verkehrt.
                "Get the ancestors of each element in the current set of matched elements, optionally filtered by a selector."

                Was ist daran verkehrt?

                Ja, bei genauerer Betrachtung sind Vorfahren nicht direkte Vorfahren, sondern alle Vorfahren.
                Aber ein klitzekleiner Hinweis ala "traversing up" könnte trotzdem nicht schaden.

                1. Auch die Beschreibung ist meiner meinung nach verkehrt.
                  "Get the ancestors of each element in the current set of matched elements, optionally filtered by a selector."

                  Was ist daran verkehrt?
                  Ja, bei genauerer Betrachtung sind Vorfahren nicht direkte Vorfahren, sondern alle Vorfahren.
                  Aber ein klitzekleiner Hinweis ala "traversing up" könnte trotzdem nicht schaden.

                  Ach, und damit verstehe ich auch was MudGuard meinte, eigentlich das gleiche wie ich, parents sollte nur direkte Vorfahren liefern, dem Namen nach. Oder sind Großeltern auch Eltern? Hmm, eigentlich ja.

                  1. @@unknown:

                    nuqneH

                    Oder sind Großeltern auch Eltern? Hmm, eigentlich ja.

                    Sind sie?

                    Qapla'

                    --
                    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
                    1. Oder sind Großeltern auch Eltern? Hmm, eigentlich ja.

                      Sind sie?

                      Nicht? Umgangssprachlich nicht, da meint man mit Kindern immer nur die direkten und nicht die Enkel-Kinder und mit Eltern genauso. Aber umgangssprachlich meint man mit Nachkommen und Vorfahren auch immer die direkten.
                      Ob meine Ur...UrUrUrUrGroßEltern nun Adam und Eva hießen kann ich nicht sagen, aber die Wahrscheinlichkeit ist nicht klein, daß da mal ein Adam und eine Eva dabei waren.

    2. Om nah hoo pez nyeetz, MudGuard!

      Bei einer Methode namens parents würde ich davon ausgehen, daß sie sich nicht um grandparents oder noch weiter zurückliegende Vorfahren kümmert.
      Gibt es eine Methode namens ancestors?

      (ich geb zu, ich hab keine Ahnung, wie jquery das handhabt ...)

      parent() liefert die Eltern, parents() alle Vorfahren.

      Matthias

      --
      Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Pluto und Plutonium.

  4. Hallo,

    Habs mir nicht näher angesehen, aber ich denke du suchst:
    http://api.jquery.com/has-selector/

    Mathias

  5. Om nah hoo pez nyeetz, Matthias Apsel!

    Das Problem lag darin begründet, dass für Archiv, Vorschau und Forumshauptseite jeweils eigene JS-Ressourcen verwendet werden. Und bei Archiv und Vorschau habe ich vor langer Zeit parent statt parents geschrieben.

    Warum allerdings $('code br').parent($('code')) falsche Elemente liefert, erschließt sich mir nicht.

    Möglicherweise doch: $('code') liefert ein Array von Objekten und wenn das leer ist, wird daraus $('code br').parent() und das ist genau das, was wir beobachtet haben.

    Damit ist der Fehler, der jetzt erst aufgefallen ist, behoben.

    Danke an alle fürs Mitüberlegen.

    Matthias

    --
    Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Gummi und Gummibärchen.

    1. @@Matthias Apsel:

      nuqneH

      Damit ist der Fehler, der jetzt erst aufgefallen ist, behoben.

      Ich denke trotzdem, dass molily recht hat: du suchst $('code').has('br').

      Bei $('code br').parents($('code')) wird im Baum von der Wurzel zu allen code-Elementen gehangelt, von dort zu allen br-Nachfahren. Danach wird von diesen wieder zurückgehangelt zu den code-Vorfahren.

      Bei $('code').has('br') wird im Baum von der Wurzel zu allen code-Elementen gehangelt, von dort zu allen br-Nachfahren. Aus den code-Elementen werden alle gefiltert, die br-Nachfahren haben – ohne dass man im Baum wieder hochhangeln müsste.

      Beides liefert dasselbe, aber $('code').has('br') sollte dies performanter tun.

      Qapla'

      --
      „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
      1. Om nah hoo pez nyeetz, Gunnar Bittersmann!

        Beides liefert dasselbe, aber $('code').has('br') sollte dies performanter tun.

        Leuchtet ein. Es gibt sogar einen Selektor dafür
        $('code:has(br)')

        Der ist zwar kürzer aber laut doku langsamer

        „Because :has() is a jQuery extension and not part of the CSS specification,
        queries using :has() cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. For better performance in modern browsers, use $( "your-pure-css-selector" ).has( selector/DOMElement ) instead.“

        Matthias

        --
        Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Frank und Frankfurt.