schildi: IE 6 expression und hintergrundbild / background-image

ich muss den first-child selektor für den IE 6 simulieren.

für das erste kind soll unter anderem das hintergrundbild gesetzt werden (für alle weiteren nicht). dies habe ich für den IE wie folgt versucht:

background: expression(this.previousSibling==null?'url(../img/f_menu_plus_111.gif) no-repeat -4px 0px':'none');

leider jedoch funktioniert das nicht. auch wenn ich die css-eigenschaften in ihre bestandteile aufgeteilt über einzelne expressions setze, wird das hintergrundbild nicht dargestellt:

background-image: expression(this.previousSibling==null?'url(../img/f_menu_plus_111.gif)':'');

u.s.w.

viell. hat jemand eine (alternativ-)lösung für dieses problem?
eine extra-klassendefinition für jedes erste kind will ich vermeiden.

  1. @@schildi:

    nuqneH

    background: expression(this.previousSibling==null?'url(../img/f_menu_plus_111.gif) no-repeat -4px 0px':'none');
    leider jedoch funktioniert das nicht.

    Hat mich ’ne Weile gekostet, das herauszufinden: Es liegt am Vergleich. Mit Leerzeichen vor oder nach dem '=='-Operator geht es. WTF??

    Aber wozu dieser Vergleich gegen null?

    this.previousSibling ? 'none' : 'url(../img/f_menu_plus_111.gif) no-repeat -4px 0px'

    Außerdem solltest du die Expression nur einmal auswerten lassen.

    Und was ich immer noch nicht in den Artikel reingeschrieben habe: Expressions mit weiter verschachtelter Klammerung müssen als letztes im Stylesheet stehen, da Webkits nachfolgende Regeln nicht mehr beachten.

    Qapla'

    Gunnar

    --
    Bildung läßt sich nicht downloaden. (Günther Jauch)
    1. @@Gunnar Bittersmann:

      nuqneH

      Und was ich immer noch nicht in den Artikel reingeschrieben habe: Expressions mit weiter verschachtelter Klammerung müssen als letztes im Stylesheet stehen, da Webkits nachfolgende Regeln nicht mehr beachten.

      Update:

      Es sind die geschweiften Klammern, die Webkits CSS-Parser aussteigen lässt. Durch die Notation mit http://de.selfhtml.org/javascript/objekte/function.htm@title=Function-Objekt lassen die sich umgehen.

      Statt

      selector  
      {  
        property: expression( [code lang=javascript](function(element) {element.style.property = value; })(this)
      ~~~ );  
      }[/code]  
        
      schreiben  
      ~~~css
      selector  
      {  
        property: expression( [code lang=javascript](new Function("element", "element.style.property = value;"))(this)
      ~~~ );  
      }[/code]  
        
      und dann können die Expressions an beliebiger Stelle im Stylesheet stehen.  
        
      You heard it first.  
        
      Qapla'  
        
      Gunnar
      
      -- 
      Bildung läßt sich nicht downloaden. (Günther Jauch)
      
      1. noch eine frage habe ich zur vermeidung der mehrfachen ausführung:

        lässt sich das in meinem fall überhaupt bewerkstelligen? ich muss ja keine berechnung in dem sinne durchführen..

        1. @@schildi:

          nuqneH

          noch eine frage habe ich zur vermeidung der mehrfachen ausführung:
          lässt sich das in meinem fall überhaupt bewerkstelligen?

          Ja. (Es sei denn, du möchtest du dynamisch vor dem vorerst ersten Element weitere einfügen.)

          ich muss ja keine berechnung in dem sinne durchführen..

          Wenn dies dann das sonst jenes ist auch eine „berechnung in dem sinne“.

          Qapla'

          --
          Bildung lässt sich nicht downloaden. (Günther Jauch)
          1. Ja. (Es sei denn, du möchtest du dynamisch vor dem vorerst ersten Element weitere einfügen.)

            so ganz komm ich nicht auf eine funktionsfähige lösung :(. hab das hier versucht:

            padding-left: expression(function(e) {return e.previousSibling ? '0':'19px'});

            ..bloß geht das so leider nicht. könntest du bitte nochmal aushelfen?...

            1. @@schildi:

              nuqneH

              padding-left: expression(function(e) {return e.previousSibling ? '0':'19px'});

              Nein.

              Der Sinn der Lösung mit einer (anonymen) Funktion ist, dass diese den Wert der CSS-Eigenschaft im Stylesheet (welcher ja die Expression darstellt) mit einem festen Wert überschreibt (und damit die Expression nicht mehr ausgewertet wird). 'element.style.property = value;' tut genau dies.

              padding-left: expression( (new Function("element", "element.style.paddingLeft = (element.previousSibling ? '0' : '19px');"))(this) );
                                                                                       ▲
                                                                                       Vorsicht, Falle! ;-)

              Qapla'

              --
              Bildung lässt sich nicht downloaden. (Günther Jauch)
              1. padding-left: expression( (new Function("element", "element.style.paddingLeft = (element.previousSibling ? '0' : '19px');"))(this) );

                okay. mit dem ansatz hatte ich davor probiert, habe dann aber abgebrochen, weil ich dachte ich bin auf dem holzweg, und weil mir die spezielle js-schreibweise mit (...)(this) nicht wirklich bekannt ist (die du ja auch auf deiner seite verwendest).

                1. @@schildi:

                  nuqneH

                  okay. mit dem ansatz hatte ich davor probiert, habe dann aber abgebrochen, weil ich dachte ich bin auf dem holzweg, und weil mir die spezielle js-schreibweise mit (...)(this) nicht wirklich bekannt ist

                  In meinem Artikel findest du Links zu molilys Artikel: „eine anonyme Funktion, die sofort ausgefüht wird [Schäfer]“.

                  Dass sich 'this' auf das selektierte Elementobjekt bezieht, war dir ja schon im OP klar.

                  Qapla'

                  --
                  Bildung lässt sich nicht downloaden. (Günther Jauch)
                  1. In meinem Artikel findest du Links zu molilys Artikel: „eine anonyme Funktion, die sofort ausgefüht wird [Schäfer]“.

                    ok. [...](this) ist hier also der Call-Operator zum sofortigen Aufrufen der Funktion.

                    danke für die hilfe!

                    1. @@schildi:

                      nuqneH

                      ok. [...](this) ist hier also der Call-Operator

                      mit 'this' als Parameter

                      zum sofortigen Aufrufen der Funktion.

                      Dafür sorgen die anderen runden Klammern: (function (foo) { bar })(baz) bzw. ((new Function("foo", "bar"))(baz)
                                                                ▲                      ▲           ▲                           ▲
                      Qapla'

                      --
                      Bildung lässt sich nicht downloaden. (Günther Jauch)
    2. top!!

      mit leerzeichen gehts. auch unfassbar. naja, hatte die info halt auch ergoogled.

      mit dem null hast du natürlich recht. das is überflüssig.

      das mit dem "einmal auswerten" hatte ich auch schonmal überflogen gehabt auf einer seite. schau ich mir auch nochmal an.

      danke auch für den webkit-tip!

      gruß!

    3. Außerdem solltest du die Expression nur einmal auswerten lassen.

      Was ich mich frage: Wann wird eine Expression eigentlich das erste Mal ausgewertet, wie weit sind die Stylesheets zu diesem Zeitpunkt eingelesen und wie weit ist das Rendering der Seite fortgeschritten?
      Je nach Position der Expression in dem/dem Stylesheet/s und je nach Komplexität des Layouts fürchte ich immer, dass diese erste Auswertung viel zu früh stattfindet und damit die üblicherweise verwendeten JS-Eigenschaften nicht die letztendliche Box-Position wiedergeben

      Gut, ich setze die Expressions extensiv eigentlich nur für min-/max-width/-height-Geschichten ein. Die Größe des Containerelements ist dann i.d.R. in einer der vorherigen Regeln festgelegt. Insofern ist das Layouten der Box kein Problem und ich habe auch in komplexen Layouts noch nicht festgestellt, dass das einmalige Ausführen der Expression dazu geführt hat, dass sie nicht ihren Zweck erfüllt hat.

      Aber wie ist das prinzipiell? Weißt du, ob das mal jemand untersucht hat oder ist das irgendwo definiert?

      Und was ich immer noch nicht in den Artikel reingeschrieben habe: Expressions mit weiter verschachtelter Klammerung müssen als letztes im Stylesheet stehen, da Webkits nachfolgende Regeln nicht mehr beachten.

      Mit separaten Stylesheets für den IE wäre das nicht passiert™. ;-)

      Mathias

      1. Hi Mathias, hi everyone else,

        Was ich mich frage: Wann wird eine Expression eigentlich das erste Mal ausgewertet, wie weit sind die Stylesheets zu diesem Zeitpunkt eingelesen und wie weit ist das Rendering der Seite fortgeschritten?

        Wenn ich Gunnars Beispiel mit der Count-Funktion verwende, und den Selektor der "Expresion-Regel" von img auf ein Element ändere, das im Testdokument gar nicht vorkommt - dann bleibt die Anzeige des Zählerstandes schön friedlich auf 0 stehen, egal wie viel ich mit der Maus herumfahre oder sonstwelche Aktionen durchführe.

        Also werden CSS Expressions offenbar schon mal nur dann ausgewertet, wenn die Regel auch wirklich "zur Anwendung" kommt, also der Selektor auf im DOM existente Strukturen matched.

        Je nach Position der Expression in dem/dem Stylesheet/s und je nach Komplexität des Layouts fürchte ich immer, dass diese erste Auswertung viel zu früh stattfindet und damit die üblicherweise verwendeten JS-Eigenschaften nicht die letztendliche Box-Position wiedergeben

        Also bevor das Element, auf das sie angwendet werden, "existiert", wohl schon mal nicht.

        Aber ob alle computed values für CSS-Eigenschaften, die sich aus eingebundenen Stylesheets ergeben, schon in ihrer endgültigen Ausprägung vorhanden sind, lässt sich daraus natürlich ableiten.

        Aber wie ist das prinzipiell? Weißt du, ob das mal jemand untersucht hat oder ist das irgendwo definiert?

        In der MSDN habe ich auf Anhieb keinen Hinweis darauf gefunden, wann Expressions zum ersten Mal ausgewertet werden.

        Ein weiterer Test lässt mich aber vermuten, dass onload abgewartet wird:
        Ich habe in Gunnars Beispiel die count-Funktion derart verändert, dass sie nicht mehr nach einem Element mit der ID "counter", sondern "counter2" sucht. Das ist im Dokument nicht vorhanden - also bekomme ich eine JS-Fehlermeldung bei jedem Mal, wo die Expression ausgewertet wird.
        Jetzt ergänze ich das Dokument um eine onload-Funktion, die den ID-Wert des Elements mit der ID "counter" durch "counter2" ersetzt - und bekomme damit keinen JS-Fehler mehr, weil die count-Funktion jetzt wieder das Element findet, welches sie sucht.
        Wenn ich also keinen groben Denkfehler gemacht habe, bedeutet das wohl, dass Expressions erst nach dem Eintreten von onload erstmalig ausgewertet werden. (Meine Hand dafür ins Feuer legen würde ich nicht, weil ich jetzt alles, CSS-Regeln und JavaScript-Code, inline im Dokument notiert habe - und nicht mit 100%iger Sicherheit sagen kann, ob das Verhalten exakt das selbe wäre, wenn sowohl CSS und JavaScript ausgelagert wären.)

        MfG ChrisB

        --
        Light travels faster than sound - that's why most people appear bright until you hear them speak.
        1. Tja, Pustekuchen ...

          Ein weiterer Test lässt mich aber vermuten, dass onload abgewartet wird

          Das scheint doch nicht zu stimmen.

          Jetzt ergänze ich das Dokument um eine onload-Funktion, die den ID-Wert des Elements mit der ID "counter" durch "counter2" ersetzt - und bekomme damit keinen JS-Fehler mehr

          Doch, bekomme ich auch weiterhin - wenn ich bspw. während des neu Ladens des Dokumentes die Maus hinreichend hektisch bewege.

          Dieser Schluss war also wohl leider ein Trug-.

          MfG ChrisB

          --
          Light travels faster than sound - that's why most people appear bright until you hear them speak.
      2. Meine Tests haben ergeben, dass die Expression zumindest auf den DOM-Baum Zugriff hat, der vor ihm liegt und schon gerendert wurde.

        Da eingebundene Stylesheets genauso wie Scripte das Parsen des HTML-Codes verzögern, also beim Einlesen des <body> schon alle im Head eingebundenen Stylesheets geladen sind, ist es sicher, dass zumindest alle Style-Regeln dem Browser bekannt sind, wenn IE auf ein Element trifft, dessen CSS-Eigenschaftswert eine Expression beinhaltet.

        Es sind jedoch nicht notwendig alle im DOM folgende Elemente schon gerendert. Sowohl DOM-Ready, wie es jQuery misst, als auch window.onload finden später statt.

        Bei einem mittelgroßen Dokument mit sehr vielen Styles und einigen Bildern hat die Expression in meinem Test auf das gesamte DOM Zugriff. Erst wenn weitere ladeverzögernde Elemente hineinkommen (z.B. ein <script> mit sleep(10)), dann sieht die Expression bei ihrer ersten Ausführen das DOM nur bis dorthin, wo es eingelesen und gerendert wurde.

        In der Praxis dürfte eine Expression bei ihrer ersten Ausführung daher auf das gesamte, schon gerenderte Dokument Zugriff haben. Das ist natürlich nicht gleich window.onload. Wenn noch irgendwo ein Bild geladen wird, das das Layout beeinflusst, dann kann es sein, dass die Expression von falschen Werten ausgeht. Mit festen width- und height-Attributen lässt sich das natürlich umgehen.

        Bei meinem min-width-Anwendungsfall ist eigentlich jegliche Umgebung egal, weil bloß geprüft wird, wie breit das Element mit dem enthaltenen einfachen Text gerendert wird (alle Parameter dafür sind dem Browser schon beim Parsen bekannt) und ob eine Aufstockung auf die Minimalbreite notwendig ist. Auch bei max-width und max-height sehe ich keine Probleme, weil ein Vorfahrenelement die Breite vorgibt, die das betreffende Element einnehmen kann, sodass das Layouten seines Inhalts sehr determiniert verläuft.