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.

Podczas projektowania strony często zdarza się tak, że niektóre jej fragmenty powtarzają się niezmiennie w paru dokumentach. Jeśli cenimy swój czas i przewidujemy możliwość edycji, nie chcemy kopiować HTML-a do każdego z nich. Najlepiej wtedy wczytać dane z pliku i wstawić je do poszczególnego dokumentu.

Można to zrobić korzystając z paru metod. Na początek warto rozgraniczyć dołączane dokumenty na dwa typy - pełne strony oraz ich wycinki. Zaletą pierwszych jest możliwość wyświetlenia poza dokumentem-matką - posiadają DOCTYPE, własne style, pliki JS i tak dalej. Zaletą drugich jest prostota w zainkludowaniu. Po prostu wklejamy zawartość pliku w jakimś miejscu.

Dokumenty pierwszego typu można dołączyć przez elementy iframe i object. Po prostym przekształceniu także przez Ajax i XInclude. Oczywiście na przekształcenia zezwalają także skrypty po stronie serwera, ale te postanowiłem wydzielić dla drugiego typu dokumentów.

W przykładach nie będę zagłębiał się w problem dostosowania wysokości dołączanego elementu dla iframe i object, istnieją do tego skrypty JS.

Iframe

Przestarzały element, obecny tylko w HTML 4.01 Transitional. Niezalecany, podobnie jak całe ramki. Chicałbym jednak opisać jak dołączamy stronę, aby wykazać jego minusy względem object.

Użycie to po prostu wstawienie <iframe src="strona.html"></iframe>. W CSS pozbędziemy się obramowania przez border: none. Jeśli chodzi o Internet Explorera należy na podlinkowanej stronie upewnić się, że zawartość nie będzie za szeroka, inaczej pojawi się brzydki poziomy scrollbar. Zrobiłem to tak:

  1. html {
  2. overflow-x: hidden;
  3. padding-right: 5%;
  4. }

Jest to typowy hack i nie działa przewidywalnie. Wygląda jednak mniej więcej dobrze: demo.

Object

Przeznaczenie tego elementu to właśnie dołączanie do dokumentu wszelkich plików - głównie multimediów, ale możemy także wykorzystać go do wstawienia pliku HTML.

Użycie to wstawienie <object type="text/html" data="strona.html"></object>. Pomiędzy możemy wstawić content, który będzie wyświetlony, jeśli przeglądarka nie poradzi sobie z pokazaniem podlinkowanego pliku. O dziwo, takie rozwiązanie działa w IE. I to działa bez classid, podejrzewam że dzięki trybowi zgodności ze standardami: demo.

Należało tylko nadać wyświetlanie blokowe object, aby uciąć tą minimalną przestrzeń dolną (znaną z obrazków bez display: block), a w IE pozbyć obramowania dla body na dołączanej stronie.

Ajax

Możemy wreszcie skorzystać z zapytania asynchronicznego ściągającego plik. Jeśli na serwerze mamy możliwość umieszczać pliki XHTML, będące prawidłowym XML-em oraz korzystamy z gotowej biblioteki, dodanie dokumentu to kwestia paru linijek kodu.

Uwielbiam jQuery i tym razem z niego skorzystałem. Opis $.ajax znajduje się w dokumentacji jQuery - ja chciałbym tylko odnieść się do fragmentu wstawiającego dane do strony. Jak widać, response od serwera znajduje się w zmiennej msg. Jest to XML, dlatego aby dostać się do żądanego kawałka strony (znajdującego się w <div id="w"></div>) musiałem pobrać z tego obiektu XML responseXML, będącym w gruncie rzeczy drzewem DOM. Dlatego później użyłem tradycyjnej metody DOM - getElementsByTagName.

A co gdybyśmy nie mieli pliku XML? Możemy ściągnąć go jako text oraz skorzystać z responseText. Przy użyciu wyrażeń regularnych możemy wyciąć fragment strony i wstawić go przez innerHTML do jakiegoś elementu.

Demo. Należy zaznaczyć, że ograniczyłem wysokość tego kontenera, aby wyglądało tak samo jak poprzednie przykłady. Lecz główną zaletą wstawiania zawartości via Ajax jest po prostu dopasowanie się kontenera do tego co w środku - nie trzeba zgadywać wysokości w JS. Ajax pozwala też w razie błędu zadecydować co pokazać użytkownikowi. Ja dodałem info o błędzie i link do ściąganego dokumentu.

XInclude

Jest jeszcze jedna fajna metoda, ale na razie tylko na kartce papieru - żadna znana mi przeglądarka tego nie obsługuje. Mowa o XInclude czyli XML Inclusion - dołączaniu dokumentów XML przez odpowiednie elementy. Cel może być parsowany jako XML albo jako tekst, podobnie jak w przykładzie z Ajaksem.

Na podstawie specyfikacji stworzyłem dokument, który powinien chyba działać na przeglądarce umiejącej XInclude - demo. Zobaczycie oczywiście Error. Ale za parę lat, kto wie…

Ta metoda jest bardzo ciekawa, pozwala korzystać z XPointer - uproszczonej metody trawersowania drzewa XML (coś jak XPath, ale prostsze) - można wyciąć sobie kawałek strony. Ma też fallback działający podobnie jak zasada zagnieżdzania object.

Serwer

Na koniec najbardziej sprawdzona metoda (dla mnie najnudniejsza :P) - wykorzystanie skryptów po stronie serwera. Nie zajmuję się tym w pracy ani na blogu, ale warto wiedzieć, że <?php include('plik.html') ?> w PHP wstawi źródło w dane miejsce strony (wcześniej też z niego możemy coś wyciąć via regexp).

Można też skorzystać z mod_include - komentarzy w HTML, które są rozpoznawane przez Apache i wykonywane.

  1. <!--#include file="strona.html" -->
  2. <!--#include virtual="/strona.html" -->

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 30 grudnia 2006 o 20:49

Kategorie: HTML & Semantyka, JavaScript & DOM, XML, XSL, XUL...

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. Osobiście korzystam tylko z dołączania plików funkcją include albo require w PHP. O niektórych sposobach nawet nie słyszałem. ;-)

    BTW. wszędzie jest odnośnik do dema, a w opisie dołączania AJAXem nie ma. Błąd jakiś?

  2. <iframe> tylko w HTML 4.01 Trans? A ja myślałem, że w XHTML 1.0 Frameset i HTML 4.01 Frameset też jest.

  3. Jak dla mnie, to z Ajaksem i X-cośtam to jest przerost formy nad treścią. Taaak, rozumiem, fajnie jest tak się bawić kodem i cuda różne robić ;) ale w praktyce to ma ZEROWE zastosowanie – wali się po prostu php-owe include() zamiast dołączać biblioteki JS, potem jeszcze trochę żeby plik się wczytał w odpowiednim momencie (jakieś addEvent czy co), i potem jeszcze zgranie tego wszystkiego żeby działało. Chyba że mówimy o jakimś shoutboksie czy innym cudeńku, wtedy wręcz wypada z Ajaksa skorzystać ;]

    Rozumiem to jako ciekawostkę techniczną, a nie jako zastosowanie na szerszą skalę.

  4. Shaitan [D4] 4 30 grudnia 2006, 21:31

    uważam tak samo jak modrzew, więc nie będę się powtarzał ;)

  5. Moje odczucia są podobne do tych powyżej. Szczególnie, że prawda jest taka, że rzadko kiedy strony są wrzucane na serwer w postaci plików – wszystko chodzi na bardziej lub mniej rozbudowanych CMS’ach.

  6. @Modrzew:
    Ja widzę:
    1. cache przeglądarki -> mniejsze obciążenie serwera
    2. serwer bez obsługi php/niedostępną dla Ciebie(jogger?)

    Zgadzam się, że Ajax jest przyrostem formy nad treścią, ale XInclude pozwoli np. stworzyć coś takiego offline(raz potrzebowałem prezentacji w html’u – wiem, że nie był to dobry pomysł ale EOT – i byłoby to jak znalazł).

    Pozdrawiam

  7. „...XInclude pozwoli…” – właśnie, POZWOLI. Nie pozwala, tylko może kiedyś tam będzie się dało to wykorzystać.
    Obecnie serwery są tak wydajne, że wygenerowanie tych parunastu kilobajtów więcej nie robi żadnej różnicy – kilka milisekund w tę czy w tę to nic (co innego w wypadku serwisów obleganych przez dużą ilość użytkowników naraz…)

  8. XInclude jest stosunkowo nowy. XHTML 2.0 pozwoli na x. Nie pozwala, tylko kiedyś tam będzie się dało go wykorzystać ;)
    Serwery są wydajne, ale nie zawsze łącza… po obu stronach.

  9. Modrzew – akurat w przypadku milisekund jakoś tak jest, że trochę tu, trochę tu i nagle pół sekundy ;) Co faktu nie zmienia, że w tym wypadku rację masz. Zresztą – i tak, i tak Uzytkowniku drogi, cache akurat tutaj nic nie da. Przeciez ajax i tak sciaga to wielokrotnie nieprawdaz? :>

  10. Uzytkownik: po stronie serwera masz zapewnione te kilka(naście) megabitów, o ile to nie jest serwer jakiejś „domowej roboty” na Neoszmacie ;) A po swojej stronie… cóż, nawet Neostrada 128 to te kilkanaście KiB/s, co wystarczy do szybkiego załadowania średniej strony. (posiadaczy modemów pomińmy milczeniem)

  11. Mi wystarczy to, że ppk ma menu na Ajax (kiedyś miał na ramkach) – podobnie jak resztę dodatkowego contentu. Poza tym na forach i w mailach często się ludzie pytają jak zrobić to co opisałem bez PHP.

    Więcej zrozumienia, mniej twardogłowych opinii. ;-) Ja staram się nie pisać o tym co wszyscy wiedzą. :)

  12. I chwała ci za to, bo komu by się chciało potem to czytać ;)

  13. (Komentarz zmodyfikowany 30.12.2006 o 22:49)

    @D4rky HTTP/1.1 304 Not Modified nie może wyskoczyć? Wyobrażam sobie przeglądarkę która korzystałaby z cache dla zapytań AJAX/XInclude. W końcu dlaczego nie (skoro pobierana strona nie została zmodyfikowana)?

    @Modrzew Znam serwer robiony na DSL’u(4 Mb/s bodajże). Po prostu nie stać ich na nic więcej a stronę, do różnych celi, muszą mieć (oprócz łącza). Jakaś dobra rada? Chętnie przekaże… (Szczegolnie, że muszę korzystać z tej strony ;) ).
    Pozatym jakoś czasami nie udaje mi się osiągać pełnych szybkości na Neo+. Mojego wyboru proszę jednak nie komętować...

  14. Jedna dobra rada – lighttpd i własny, zoptymalizowany CMS. Inaczej nie pociągnie

  15. Jeśli mam być szczery, wydaje mi się, że w chwili obecnej nie ma żadnej naprawdę dobrej i kompatybilnej metody „włączania” dokumentów w strony. A przynajmniej takiej, która na pewno działała by w najszybszej przeglądarce na świecie (mowa o Lynksie oczywiście).

  16. (Komentarz zmodyfikowany 30.12.2006 o 22:47)

    Robisz się wkurzający z tym wciskaniem wszędzie Lynksa. Telnetuj je!

  17. Wykonanie kodu po stronie serwera jest najbezpieczniejsze – mamy pewność że w każdym programie ‘przeglądarko-podobnym’ wszystko będzie działało tak jak należy.

    Druga sprawa to interpretowanie treści przez wyszukiwarki: PHP ok, ale Ajax i ramki pod tym względem odpadają. Google z Object sobie radzi (jeszcze nie testowałem – Riddle tak twierdzi, więc powinna to być prawda).

  18. @D4rky: Własny CMS już jest. Ale cache dla przeglądarki jest tutaj ważny jednak…

  19. XInclude jest przydatny, tylko może nie w XHTML-u. Co innego jakieś inne formaty (XML), gdzie np. pobranie jakichś zewnętrznych danych jest opcjonalne.

    A XInclude z XPointerem można, zdaje się, w Fx włączyć, ale przy kompilacji. :-) Znaczy to tyle, że będzie działać prawie nigdzie, póki nie będzie włączane domyślnie. A pewnie nie jest z obawy o błędy (tak se tylko strzelam).

  20. Obecnie serwery są tak wydajne, że wygenerowanie tych parunastu kilobajtów więcej nie robi żadnej różnicy – kilka milisekund w tę czy w tę to nic (co innego w wypadku serwisów obleganych przez dużą ilość użytkowników naraz…)

    Akurat tutaj się nie zgodzę. Wygenerowanie strony w dużych systemach jest nawet kilkaset razy wolniejsze niż serwowanie strony statycznej. I wtedy jeżeli treść jest stosunkowo rzadko zmieniana należy użyć cachowania treści.

  21. Tak jeszcze pół serio mówiąc: można złapać jakiegoś niedoświadczonego użytkownika za pomocą includowania po stronie serwera – pomyśli sobie, że w pocie czoła kleiliśmy każdą podstronę :) Jeszcze jak użyć mod_rewrite i index.php?id=bum zamienić na bum.html, to już szok totalny ^^

  22. mod_rewrite to armata na to, lepiej w .htaccess dodać: AddType application/x-httpd-php .html :-)

  23. Wtedy parser będzie mielić także pliki .html, co wydłuży ich wczytywanie i pozwoli zapomnieć o cache ;>

  24. Modrzew: ale przecież to chciałeś osiągnąć, nie? :-)

  25. Ta, ale takie osoby jak „Uzytkownik” nie byłyby zbytnio zadowolone ;p

  26. A może po prostu po stronie serwera generowany kod zapisać do plików i użytkownikom serwować gotowe pliki HTML? Do tego zdarzenia, które dodają stronę do kolejki regeneracji w momencie zmiany i daemon, który będzie odpowiednio strony te regenerował? q-;

  27. @Michał Górny:
    Cachowanie po stronie serwera?
    Słyszałem o czymś takim dla php (zarówno całej jak i części) – a zapewne jest dla wielu innych języków…

    PS.
    XInclude chyba może być przetwarzany po stronie serwera ;)
    Dlaczego w końcu nie… (a mogłoby być to przetwarzanie ‘w piaskownicy’.

  28. Ja akurat miałem na myśli cachowanie bez konieczności wywoływania interpretera języków. Tak pół żartem, ale czasem naprawdę byłoby to dobre rozwiązanie.

  29. @Michał Górny: Źle się wyraziłem. Dla php a nie w php (tzn. żeby nie wywoływał skryptu/całego skryptu za każdym razem).

  30. Uzytkownik – mozna napisac b. prosty kod, ktory by wykrywal czy przegladarka obsluguje XInclude (po wersjach przegladarek) i jesli nie to <?php include(); ?>, ale to nie o to chodzi ;)

  31. @D4rky: Kolejny brzydki hack(wykrywanie po przeglądarce a nie po możliwościach). Już lepiej jest chyba poinformować...

  32. Wiesz, w PHP jest taka bajerancka funkcja get_browser. Cytując manuala:
    bq. get_browser() attempts to determine the capabilities of the user’s browser. This is done by looking up the browser’s information in the browscap.ini file.
    By default, the value of HTTP User-Agent header is used; however, you can alter this (i.e., look up another browser’s info) by passing the optional user_agent parameter to get_browser(). You can bypass user_agent parameter with NULL value.

  33. Tak, tak, a potem tysiące wywołań skryptów, przetwarzających na setki sposobów parametry żądania i debatujące nad n opcjami dostarczenia wyniku. Nie ma to jak przemyślane rozwiązania…

  34. Peres – nie zapominaj o tonie kodu JS, ktory bedzie robil dokladnie to samo po stronie usera ;)

  35. AJAX jest przyszłością! Możemy nie tylko wstawić kawałek strony, ale także zmodyfikować to, co zamierzamy wstawiać.
    Na przykład, poprzez AJAX pobieramy dwa dokumenty: tabelka_z_danymi.xml i wyglad_wiersza_danych.xml. Nastepnie, zgodnie z kryteriamy filtrujemy i sortujemy dane, po to, zeby wyswietlic je w szablonie. Metoda ta jest o tyle cool, ze nie wymusza wykonywania kolejnych requestow, gdy chcemy zmienic kryteria filtrowania lub sortowania. Warto looknac tez na projekt:
    http://code.google.com/p/jstemplate/
    Jest to lekka alternatywa dla XSLT. Swietnie sie sprawdza w polaczeniu z ADVAjax.

  36. JAAAA EEEEEJ, NO NIEMOŻLIWE...
    Ameryki żeś tu nie odkrył...

    Ajax przyszłością? Fajnie, ten zlepek technologii istnieje od 1999 roku – w informatyce to szmat czasu, a nie „przyszłość”. Pewnie dalej byłby zapomniany, gdyby Google go nie zaczęło stosować na skalę masową.

  37. Modrzew, cicho, AJAX jest spoko. Dzięki temu wreszcie mam ssh na komórce ;)

  38. (Komentarz zmodyfikowany 27.02.2007 o 04:55)

    W kodzie PHP zapomniałeś o średniku…
    A w paragrafie Iframe masz: „Chicałbym”.

  39. hmm.. A ja testowałem tą opcję z <object/> i niestetu musze stwierdzić, że na IE nie da się w ten sposób wstawić strony z innego serwera, bo nie jest po prostu wyświatlana (albo mi się po prostu to nie udało)

  40. Hę? Przecież <object> == <iframe>. Efekt jest identyczny, wady te same, tylko walidator nie potrafi nad tym rozpaczać.

  41. Nie wiem czy to to samo, nie wydaje mi się. Efekt jest identyczny, ale tak jak mówiłem, używając <iframe> da się wstawić plik html z innego serwera, a za pomocą <object> nie, przynajmniej u mnie. i jeszcze raz podkreślam, że tylko w Interent Explorerze, bo reszta działa ok.

  42. Aha, no i jeszcze nie kumam gdzie tu problem z cache…

    <?php header("Cache-control: max-age=10000"); ?>

    nie tak trudno wrzucić, a już bardzo pomaga. Przy używaniu SSI (.shtml) Apacz sam zajmuje się obsługą cache, więc nie ma się o co martwić.

    Co do prędkości przetwarzania, to samo include to pestka i w ogóle nie powinno to być brane pod uwagę. Owszem, gigantyczne zawiłe systemy template‘ów mogą być wolne, ale hackami po stronie klienta i tak się tego nie odtworzy (z lepszą prędkością).

    Mimo swej wielkiej fajności i nietypowości, AJAX/iframe/object/xinclude też generują żadania do serwera, takie same jak zwykłe nudne pobrania strony.

    No i pamięta ktoś jeszcze o URLach? (i tym jakie stają się bezużyteczne przez takie protezy?)

    Parafrazując Flandersa: Nie myl mogę z powinienem. Tak, możesz użyć xinclude i ajax, ale czy powinieneś?

  43. is nice. i like it :)

    jQuery rules…. rzadko mamy do czynienia z czyms tak intuicyjnym
    odliczam dni do 14. stycznia…...Ty tez Riddle? :-)

    z frameworkow php polecam Code Igniter (tez intuicyjny…..oczywiscie jesli sie przetrawilo filozofię MVC :)

    osobiście nie uważam zeby AJAX był tylko cool i nic wiecej
    wszedzie trzeba miec zdrowe podejscie zarowno robienie stron firmowych we flashu jak i w oparciu o ajax (mam na mysli np ladowanie podstron) jest nonsensowne…...

    ale w web-apps az sie prosi o ajax (bo na XUL i Laszlo nie ma co na razie liczyc)..........zupelnie inne odczucia w korzystaniu z aplikacji (wg mnie nic bardziej nie wkurza niz przeladowywanie strony i ten moment kiedy sie nie widzi ani starej ani nowej tresci…)

    pozdrowienia i wszystkiego najlepszego w 2k7.

  44. A no ba, 14 stycznia to ja chyba taniec szczęścia odtańczę. 10-20x szybsze selektory, OMFG. :D

    Dzięki za życzenia, nawzajem. :-)

  45. Ja tutaj poznałem jQuery i… ta biblioteka jest wspaniała…

  46. Dużo komentarzy, więc będę wspominał pobieżnie:

    ad. Lynksa
    A co będziesz serwował wyszukiwarkom? Może sobie JavaScript włączą? :P
    Poza tym, jest jeszcze pewien odsetek ludzi, który korzysta z Lynksa albo przeglądarek, które mają zwyczajne problemy z AJAX-em.

    Przy SSI (mod_include) to jest o tyle lepiej, że w statycznych dokumentach nie jest dodatkowo PHP maltretowane. Nie wiem, co ma większy priorytet (SSI vs. PHP), więc ciężko mi powiedzieć, czy jest sens wciskania <!—#include…—> pomiędzy kod PHP czy lepiej via require/include.

  47. Tom Sieron 47 07 lutego 2007, 13:04

    a’propos krytyki AJAX’u (i XML Include): chyba przegapiliście moment kiedy w internecie zaczely smigac aplikacje webowe, a swoje wypowiedzi opieracie na zastosowaniu HTMLa do wyrzucania z bazy do przegladarki danych + obrazki i troche statycznej treści. Dajcie spokój, to nie rok 1999, nalezaloby poszerzyc horyzonty (szczegolnie gdy sie chce uchodzic za webdevelopera/designer/webwhatever).

  48. robię stronkę opartą na diva’ch i css, pliki dołaczane po klikaniu w menu są w innym divie za pomocą include, i tu pojawia się problem, bo o ile na głównej stronie jest ok, to jak klikne na link, który jest w załadowanej do diva jakiejś podstronce, to ładuje się on już zastępując całość, a nie nadal w tej ramce…tzn. tym divie

    czy jest jakiś sposób na ominięcie tego??

  49. To problem architektury Twojej strony, musisz po prostu ładować każdą stronę z kodem wstawiającym w odpowiednie miejsce sidebar/menu – bo jak rozumiem include to przez PHP robisz?

    No ale nie znam się za bardzo na PHP, więc może to nie to.

  50. przygotowujemy sobie stronę np. w tabelkach, w miejscu w którym mają być widoczne zmiany wstawiamy kod :
    php:
    <? include („frame.php”); ?>

    - tworzymy w katalogu z plikiem index.php, plik frame.php i zapisujemy w nim :
    php:
    <? switch ($_GET[‘id’]) { case („news”): include („plik1.html”); break;

    case („download”): include („plik2.html”); break; case („pomoc”): include („plik3.html”); break; case („inne”): include („plik4.html”); break; //( ... ) default: include („witaj.html”); } ?>

    pliki ładuję na takiej zasadzie j.w.
    z menu jest ok. ale każdy odnośnik, na jakiejkolwiek podstronie załadownej, otwiera nową stronę...

    ciężkobyłoby wpisać kilkadziesiąt podstron i nadać im jakieś id, żeby było jak z case’a ładować...
    i tu powtarzam pytanie??
    czy znasz jakiś sposób??

  51. przerost formy nad treścią? buhahaha:P Dzięki ajaxowi można zaoszczędzić sporo transeru – bo nie trzeba przeładowywać całej strony dla wczytania nowej podstrony, a jedynie po cichu wczytywanie.

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ę.