Perfection or Vanity

Project: Terminated

Blog nie jest już dalej prowadzony ani aktualizowany. Mimo tego, wpisy i komentarze są dalej dostępne. Możesz przeczytać pożegnalny wpis albo przejść do archiwum.

Popraw CSS w IE

Expressions są rozszerzeniem Internet Explorera, dzięki któremu można wykonywać skrypty JS na zbiorze elementów. Ich działanie porównuje się do funkcji z Excela - gdy zawartość komórek się zmieni, formuła zwróci nowe dane. Microsoft zachwalał je jako przyjazne skryptowanie stron dla webmasterów, ale ja chciałym przybliżyć ich składnię i możliwości.

Teoretycznie można je dodawać do dokumentu zarówno w JS i CSS, ale tylko ten drugi sposób jest warty opisania. Tak bowiem aplikuję bardziej skomplikowane haki z poziomu arkusza stylów IE, kiedy wszystko inne zawodzi. Musimy jednak uważać na to co i jak robimy, bo expressions są w stanie łatwo zawiesić przeglądarkę.

Składnia i użycie w CSS

  1. selektor {
  2. właściwość: expression(…pseudokod JS…);
  3. }

Parę zastrzeżeń do powyższego zapisu. Użytą właściwością CSS może być np.: left albo width (do których finalnie przypiszemy obliczoną wartość), ale wcale nie musi. W praktyce okazuje się, że wystarczy stworzyć dowolną nową i podpiąć w niej kod. Prawidłowy okaże się poniższy przykład:

  1. p {
  2. width: expression(…);
  3. xp: expression(…);
  4. xp2: expression(…);
  5. }

Gdybyśmy byli zmuszeni wrzucić expressions do zwykłego arkusza CSS, polecam poprzedzić właściwość -ie - tak oznacza się rozszerzenia CSS (-moz, -o).

Z doświadczenia wiem, że nie należy eksperymentować z istniejącymi właściwościami CSS, jeśli po prostu musimy odpalić jakiś niezwiązany z nimi kod. Przykładowo tak wygląda w drzewie DOM przykład z góry:

Odzwierciedlenie expressions w DOM

Expression a JavaScript

Napisałem wyżej pseudokod JS - uczyniłem tak, ponieważ podczas pisania expressions jesteśmy ograniczeni zasadami składni CSS. Dodatkowo możemy wykorzystywać uproszczenia IE i dodatki MS. Oto te, które wychwyciłem:

  • Nie możemy używać nawiasów klamrowych, możemy normalnych. Można korzystać z łamania linii oraz innych białych znaków w celu zwiększenia czytelności.
    • Jest wyjątek od tej reguły, ale o tym później.
  • Nie możemy stawiać średników, zamiast tego należy wykorzystać przecinki.
  • Zmienne deklarujemy bez var
  • Możemy odwoływać się do elementów z danym id jak do zmiennych (a.innerHTML = 'coś' jeśli w DOM istnieje <div id="a"></div>)

Obiekty i metody

W expression często będziemy używać słowa kluczowego this. Zwraca ono referencję do aktualnie przetwarzanego elementu DOM. Przykładowo:

  1. #sidebar a {
  2. width: expression(this.parentNode.offsetWidth - 100 + 'px');
  3. }

Metody pozwalające na spacerowanie po drzewie dokumentu:

  • parentNode - rodzic elementu
  • firstChild - pierwszy potomek elementu
  • childNodes - zbiór potomków elementu, childNodes[3] zwróci czwarty
  • previousSibling - element poprzedzający (w IE spacje i tabulatory między tagami są wliczane do childNodes, więc trzeba uważać co się pobiera)
  • nextSibling - element następny (j/w)
  • Bardziej szczegółowy opis sposobów odnajdywania elementów w DOM wraz z grafami - zerknij, jeśli masz małe pojęcie o czym mówię.

A teraz przykład z expression. Jak widać można też zmienić styl za pomocą takiej konstrukcji:

  1. #nav li {
  2. -ie-xp: expression(this.parentNode.firstChild.style.color = '#13AEBB');
  3. }

Wykonywanie

Jakiekolwiek zdarzenie na dowolnym elemencie na stronie powoduje wykonanie expressions. Jest to bardzo przydatne - jeśli zamierzamy pobierać szerokość layoutu i sprawdzać go z predefiniowaną wartością, emulując min/max-width. Jest także dość szybkie, ze względu na wbudowanie IE w Windows zapewne. ;-)

Jednak z pewnością będziemy na pewnym etapie chcieć wykorzystać standardowe metody DOM, aby zrobić pseudo GC. Napisanie kawałka skryptu bez sprawdzania, czy dla danego elementu został już wykonany to śmierć IE. Modyfikacja dokumentu uruchamia ponowne parsowanie CSS - do DOM zostaje dodanych kilkadziesiąt kolejnych bloczków. Nieskończona pętla.

Zapętlenie się expression

Zabezpieczyć się przed takim scenariuszem jest dość łatwo - dodajmy fikcyjny atrybut parsed (nazwa nie ma znaczenia) i sprawdzajmy jego wartość. Zwykłe warunki if w expressions nie działają - pozostaje skorzystać z wersji liniowej.

  1. -ie-xp: expression(
  2. this.parsed ? 0 : (
  3. ……,
  4. this.parsed = 1
  5. )
  6. )

Po polsku - czy atrybut parsed aktualnie przetwarzanego elementu (this) ma wartość zero? Jeśli tak, to wykonaj kod w nawiasie po dwukropku. W którym to ustawiamy parsed na 1, aby nie powielić znowu tego samego.

Ok - jako, że wiemy już dość dużo, pokuśmy się o dodanie diva clearującego na końcu każdego postu na blogu.

  1. div.entry {
  2. -ie-xp: expression(
  3. this.parsed ? 0 : (
  4. clearer = document.createElement('div'),
  5. clearer.style.clear = 'both',
  6. this.appendChild(clearer),
  7. this.parsed = 1
  8. )
  9. );
  10. }

Mogliśmy także ustawić odpowiedni className i pozbyć się w ten sposób stylów liniowych (powiedzmy zgrupować z nowoczesnym div.entry::after), ale to tylko przykład.

Ograniczenia składni a eval

For, if, { }, ; ?

Na początku postu pisałem, że w expressions nie możemy używać nawiasów klamrowych i średników. Przez takie ograniczenia odpadają wszelkie konstrukcje wspomagające kodowanie - złożone warunki, pętle, bloki try. Niedawno jednak spróbowałem skorzystać z funkcji eval wykonującej kod JS zawarty w dowolnym ciągu tekstowym. A te już mogą zawierać niedozwolone znaki! :-)

Jedyne o czym trzeba pamiętać to skasowanie deklaracji zmiennych var. Możemy je umieścić przed eval. A tak wygląda pętla drukująca w akapicie cyfry od 0 do 9:

  1. p {
  2. -ie-xp: expression(
  3. this.parsed ? 0 : (
  4. i = 0,
  5. eval('for (i = 0; i < 10; i++) { this.appendChild(document.createTextNode(i)) }'),
  6. this.parsed = 1
  7. )
  8. );
  9. }

Po co nam 10 cyfr? Nie wiem, ale to tylko przykład jak potężne potrafią być expressions. Dzięki nim można roszerzyć implementację CSS Explorera i naprawić dziesiątki błędów - o czym przekonamy się w następnym poście. Tymczasem powodzenia w hakowaniu misia. ;-)

Przykładowe expressions

Informacje i hiperłącza

Blog o projektowaniu zgodnych ze standardami stron internetowych.

Praktyczne przykłady, sztuczki CSS, sposoby obchodzenia błędów przeglądarek, lekki i nieinwazyjny JavaScript, użyteczny design, dostępność i skrypty użytkownika.

RSS

Informacje o wpisie

Napisał riddle 12 stycznia 2007 o 04:24

Kategorie: CSS, Internet Explorer, JavaScript & DOM

Dodaj do:

Wpisy archiwalne

Archiwum miesięczne

Dzięki!

Dodaj bloga do Technorati Favorites Dodaj bloga do Del.icio.us Blog należy do sieci 10przykazań.com

  1. (Komentarz zmodyfikowany 12.01.2007 o 11:35)

    Trochę rozwalasz wygląd planety Opery tym wpisem. A także w Operze ta strona się jakoś dziwnie wyświetla ;)

  2. Świetnie! Mam tylko pytanie: „-ie-xp: expr(...)” – czy to „ie-xp” ma jakiś związek z systemem?

    Frapuje mnie też jeszcze inna srpawa. Używając znanego csshover.htc piszemy w *.css behavior: url(csshover.htc); – ten behavior to również jakieś egzotyczne polecenie IE?

  3. Potwierdzam adasa – pod moją Operą 9 nie da się czytać.

    Tak sobie czekałem aż coś napiszesz na ten temat, więc wielkie dzięki.

  4. Michał Górny 4 12 stycznia 2007, 09:07

    (Komentarz zmodyfikowany 12.01.2007 o 11:35)

    Odnośnie problemów pod Operą — patrz: walidator HTML.

  5. heh, a ja myślałem po tytule, że będzie o programach z linii Microsoft Expression Cośtam ;-)

  6. czy to „ie-xp” ma jakiś związek z systemem?

    Napisałem, że nie. Poza tym -ie-xp.

    myślałem po tytule, że będzie o programach z linii Microsoft Expression Cośtam ;-)

    No chyba żart :]

    Trochę rozwalasz wygląd planety Opery tym wpisem

    Unintended… jak się pisze post na 9k znaków to czasem się czegoś zapomni.

  7. Dwie sprawy: *eval należy unikać – polecam anonimowe funkcje:
    (function(){ /* kod */})() *Twój sposób na jednorazowe wykonanie kodu, jest imho trochę brudny. Lepiej byłoby dobrać się do arkusza stylów poprzez styleSheets i wywalić użyte już expressions.

    pozdrawiam

  8. misia

    Genialne ^^ .

  9. eval należy unikać

    Eval pozwala przemycić { do expression. :-) Twój kod nie zadziała.

    Sposób z styleSheets wydaje się okej, ale mój mimo że brudny jest diablo szybki.

  10. Bardzo cenny tip z tym evale’m, czasami brakowało mi właśnie pętli w expression’ach.. nie mniej zawsze w końcu jakoś sobie radziłem bez nich :)

  11. Riddle, testowałeś ten swój tip z eval’em? Wygląda na to, że owszem eval działa.. ale nie da rady w nim skorzystać z jakichkolwiek klamer czy innych składni jak pętle.. te same ograniczenia co bez evala (tyle, że średniki działają) :/ więc w sumie eval nam nic nie daje.

    Testowałem nawet Twój powyższy przykład – nie działa.

  12. Oczywiście, że testowałem i oczywiście, że działa. Chcesz screena, czy jak? :-)

  13. Screen’a? Daj link do działającego przykładu.. :)

  14. Snippet z wpisu > Ctrl+C, Ctrl+V. Działa. Męcz się. ;)

  15. Taak.. działa.. zwracam honor :)
    Za bardzo namieszałem w swoim systemie..długo by tłumaczyć, CSS idzie u mnie przez php.. i ostatecznie przy takim fiu bździu w stylach IE dostawał php’owski komunikat o błędzie zamiast css’a.. dziwie się, że wcześniej tego nie wyłapałem.

  16. Pod IE5.5 bardziej skomplikowane wyrażenia wewnątrz „eval” (np. pętle) nie działają. Działają natomiast pod IE5, IE6 i IE7.

  17. P.S. Dodanie tu komentarza z wyłączonym javascriptem jest niemożliwe… i nie wyskakuje nawet żadna informacja…

  18. Dodaję komentarz bez JS.

    Edit: Jak widać się da.

  19. Ok, poprawka. Dodanie tu komentarza z wyłączonym javascriptem jest niemożliwe, jeżeli używa się Opery… (używam 9.24)

  20. ... i ma sie dodatkowo oprocz javascriptu wylaczona jave i/lub flasha.

  21. Dziwne rzeczy prawisz. Ten formularz nie jest uajaksowiony, nie ma w nim ani grama JS i działa nawet na lynksie, więc nie rozumiem o co chodzi. Jedyne co Ci może nie działać, to przewinięcie do podglądu bo to jest już w JS. Sprawdź proszę swoje ustawienia, najpewniej to kwestia wyłączonych ciastek. Na pewno nie JS.

  22. Jeszcze jedna poprawka. Prawdopodobnie jest to jakiś problem z cookies + javascript. Jeśli ma się wyłączony javascript przy pierwszym wejściu na tą stronę, to nie da się dodać komentarza. Jeśli zaś się włączy javascript i doda komentarz, to kolejne przechodzą nawet przy wyłączonym javascripcie. Pozdrawiam :-)

Dodaj komentarz

Do formatowania komentarzy używaj Textile (HTML nie działa). Szczególnie jeśli wklejasz większe fragmenty kodu. W razie niepewności użyj podglądu komentarza.

Wypowiedzi obraźliwe, infantylne oraz nie na temat będą moderowane – pisząc postaraj się zwiększyć wartość dyskusji.

Komentarze nie służą do wysyłania wiadomości albo informowania o błędach, itd. Chcesz coś mi napisać – skontaktuj się.