Skip navigation

OK2RKB | ENG · GER · RUS · FRA · POL · HUN | Main · IE+ · IE- · Prn · Pda · CSSoff

OK2PPK » Info » Popis stránek » Podrobnosti o stránkách | ---

Detailní informace o stránkách

Vzhled stránek

Rozložení

Uspořádání stránek je řešeno jako jednosloupcové, sloupec je dále svisle rozdělen na hlavičku, navigaci, vlastní obsah a patičku. Nad sloupcem mimo jeho obsah je ještě jednoduše stylovaný řádek s pomocnou navigací, která má umožnit přepnout vzhled na jiný, pokud by výchozí sada stylů způsobila totální rozhození zobrazení stránky v prohlížeči. Šířka sloupce se nastavuje dynamicky podle aktuální šířky okna, ale pouze v určitém rozsahu, tak aby text nebyl příliš roztažený nebo příliš moc úzký. Rozložení základních bloků na stránkách je řešeno bez použití rámců nebo tabulek.

Koncepce rozložení stránek. (foto PPK)

Koncepce rozbalovacího menu. (foto PPK)

Koncepce obrázků. (foto PPK)

Hlavní navigace je vytvořena obyčejným nečíslovaným seznamem položek, který je stylován tak, aby se jeho první úroveň zobrazila trvale vodorovně jako záložky těsně nad blokem se samotným obsahem stránky, druhá úroveň se rozbalovala po najetí kurzoru svisle pod odpovídající záložku, a třetí úroveň se rozbalovala opět svisle napravo od odpovídající položky 2. úrovně. Šířka jednotlivých bloků položek menu není pevně daná, ale plynule se přizpůsobuje skutečné potřebě dle délky textu.

Obrázky jsou do stránek vkládány jednotnou formou, která zahrnuje vytvoření rámečku kolem obrázku, připojení popisného textu pod obrázek, obtékání obrázku textem a případné propojení více obrázků do jednoho bloku na řádku.

Styly

Obsah stránek je silně oddělen od nastavení vzhledu, stránky lze použít i s úplně vypnutým zpracováním stylových předpisů. V základním nastavení se linkují tři sady stylů - pro medium SCREEN a PROJECTION, pro PRINT a pro HANDHELD. Celé stránky používají unifikovaný a dopředu vybraný seznam prvků, které na ně bude možné umisťovat, a pro tyto prvky byl jednotně nastaven vzhled pomocí společných stylových předpisů.

Sjednocení zobrazení v různých prohlížečích je řešeno konzervativně směrem k možnostem jejich starších verzí, IE se přepne do quirk módu a popř. do emulace IE7, ostatní prohlížeče se nastaví do standardního módu. Použití hacků bylo minimalizováno a spíše jsem hledal cesty jak problém se zobrazením vyřešit čistěji. Pro IE byly využity podmíněné komentáře, které zavádějí specifickou sadu stylů, kterou se zkoriguje hlavní načtená sada, a dále se používá korekční javascript, který upraví načtený dokument tak, aby ho IE zobrazil stejně jako jiné prohlížeče - korigují se chybějící pseudotřídy :hover a :after, odlišné chování prvků s více třídami, speciálně pro IE5.0 problémy na 2. a 3. úrovni rozbalovacího menu navigace, a odlišné vracení hodnot z prvku button ve formulářích.

Stylové předpisy a korekční javascript byly před umístěním na web zkompreseny pomocným programem, který z nich odstranil komentáře a část prázdných znaků. Tím se snížil jejich objem zhruba na polovinu.

Jaké styly se budou v záhlaví linkovat lze uživatelsky ovlivnit speciálním parametrem zaslaným v dotazu sestavovači stránek.

Původně navržený web byl v roce 2007 proháněn i validátory značkování a CSS především kvůli nalezení případných chyb, které mi unikly. Po jejich vychytání se validátoru nelíbil už jen výraz expression v nastavení dynamického layoutu pro IE. Současně používaná sada stylů pak už validována nebyla, vznikla postupným doplňováním původní sady, kde asi největší změnou bylo doplnění třetí úrovně navigace a jiný způsob vkládání obrázků s popisky.

Grafika

Grafika na webu byla úmyslně minimalizována, úplná základní sada obrázků (myšleno bez vkládaných obrázků do stránek, s nimi to pak samozřejmě objemově letí nahoru) pro stránku má asi 17kB. Mělo by to umožnit lepší přístup na stránky i těm, kdo mají pomalejší připojení.

Základní barevné řešení webu je zvoleno se světlým pozadím a tmavým písmem, a k tomu obráceně provedená hlavička a část hlavní navigace, barvy jsou vesměs bílá, černá a odstíny modré a šedé, a pro zvýraznění vybraných prvků odstín červené. Pro fotogalerii byl použit inverzní vzhled s tmavým pozadím a světlým písmem, který původně vzniknul prostou negací všech barev, nicméně nakonec byla část barev vyměněna za jiné a byla ponechána např. původní hlavička, barvy jsou opět hlavně černá, bílá, odstíny modré a červená na zvýraznění, ale navíc pozadí pod stránkou je v hnědé a písmo na něm v odstínu žluté.

Programový kód stránek

Programový kód stránek pracuje jako poloredakční systém, kdy na jedné straně sestavovač poskytuje stránkám značnou podporu, takže pro obyčejnou stránku, která obsahuje pouze texty, není potřeba na ni umisťovat žádný další programový kód, a o vše ostatní se postará sestavovač, ale na druhé straně jsou stránky uloženy jen jako php soubory a nikoliv v databázi, a pro jejich přidání je potřebná znalost programového kódu sestavovače a musí se doplnit další údaje o stránce ručně přímo do odpovídajících datových struktur.

Stránky mají jediný vstupní bod a výběr konkrétní stránky se provádí v dotazu pomocí parametru pg. Další parametry jako např. st, menu, sel, list, gal, img, isize, gsize apod. slouží k dalšímu ovládání sestavovače stránek nebo jednotlivých stránek. Použití "pěkných adres" v dotazu v podobě virtuální struktury adresářů bez parametrů bylo z konečné podoby stránek odstraněno.

Sestavovač stránek

Sestavovač stránek zajišťuje zkompletování stránky do podoby, v jaké má být odeslána uživateli, a zároveň za všechny stránky řeší centrálně veškeré často potřebné úkony.

Koncepce sestavovače stránek. (foto PPK)

Převážná část sestavovače stránek je napsaná s použitím objektově orientovaného programování, pouze kód související s jeho rozeběhnutím a podpůrný modul se tomuto vymykají.

Vstupním bodem sestavovače je soubor index.php v kořenu webu. Nejprve provede nastavení některých základních parametrů (např. charset, čas), a potom předá řízení podpůrnému modulu. Po návratu z podpůrného modulu se vytvoří hlavní objekt celé aplikace sestavovače (jeho třída se načte již zavaděčem v podpůrném modulu), v jeho konstruktoru se připraví všechny podklady potřebné pro sestavení stránky, a následně se voláním patřičné metody tohoto objektu sestaví stránka a odešle uživateli. Objekt aplikace sestavovače slouží zároveň jako hlavní přístupový a vzájemný komunikační bod pro všechny části webu.

Modul podpory zajišťuje pro sestavovač základní úkoly jako je načtení konfigurace celého systému, obsluha chyb, podpora ladění a autozavádění knihoven tříd.

Konstruktor aplikace sestavovače postupně vytvoří instance několika dalších objektů, které obsluhují jednotlivé ucelené bloky údajů o stránkách, a inicializuje je. Nejprve se nastaví seznam všech stránek s jejich parametry a obdobně seznam položek menu. Připraví se podpora pro přístup k DB a zpracují se údaje o relaci ze session a připraví podle nich údaje o uživateli. Následně se zpracuje údaj o stránce, kterou uživatel požadoval, a po prověření v seznamu stránek se nastaví kompletní sada údajů o tom, která stránka a s jakými výchozími parametry se bude sestavovat. V dalším kroku se zpracují údaje o případné změně požadovaného vzhledu. Inicializují se zavaděče seznamů odkazů a seznamů obrázků, a nakonec se připraví pozice pro objekt, který bude zajišťovat renderování jednotlivých prvků stránek do výstupu pro uživatele.

Sestavovač používá šablony, pomocí kterých se na závěr kompletuje finální podoba celé stránky. Samotná stránka, šablona i parametry nastavené v sestavovači se navzájem mohou silně ovlivňovat a některé změny, které jsem chtěl, aby byly možné, nelze provést v jednom kroku, např. stránka chce modifikovat svůj vzhled a zároveň by se měla vypsat, ale aby se mohla s modifikovaným vzhledem vypsat musí napřed vyměnit šablonu, ale šablona se může vyměnit teprve až to stránka řekne sestavovači. Proto šablonu i stránku lze rozdělit na dva samostatné soubory, první nemůže vytvořit žádný přímý výstup směrem k uživateli, ale může vypočítat a modifikovat různé parametry sestavovače anebo připravit podklady pro výstup, a druhý realizuje už konkrétní výstup směrem k uživateli. U samotné stránky pak nakonec byla použita varianta s rozdělením až na tři části, kdy první dvě neprovádí přímý výstup, a to, zda se bude zavádět druhá část a jaký to bude soubor, lze nastavit v její první části. První dvě části jsou nepovinné, třetí, která zajišťuje výstup, musí vždy existovat.

Metoda, která zajišťuje u objektu sestavovače celé vytvoření stránky, pracuje následovně. Pokud existuje, tak zavede první část stránky. Pokud první část stránky o to požádala, tak následně zavede i druhou část stránky. Po tomto kroku je už neměnitelně nastaveno, která stránka bude generovat výstup směrem k uživateli a jak má výstup vypadat. Následně se tedy může započítat přístup a připraví se údaje o šabloně, která se bude používat. Zavede se první část šablony, která nastaví správný render prvků na stránkách. V případě potřeby se modifikuje hlavička HTTP a potom se zapne zachytávání výstupu. Do tohoto okamžiku, pokud nedošlo k fatální chybě, nebylo uživateli nic odesláno. Nyní se načte třetí část stránky, která vygeneruje vlastní obsah. Po vytvoření obsahu se ukončí možnost ukládání údajů do session, zastaví se zachytávání výstupu, a uzavře se připojení k DB. Nyní se načte druhá část šablony, která pomocí volání prvků renderu sestaví celou stránku a jako vlastní obsah stránky vloží dříve zachycený výstup. Výstup je odeslán k uživateli a práce sestavovače tím končí.

Poměrně složitou částí sestavovače jsou rutiny renderu, které ze seznamu položek menu, seznamu stránek a s použitím údajů o oprávnění uživatele a o aktuálně sestavované stránce skládají hlavní navigaci, mapu stránek a drobečkovou navigaci.

Údaje o stránkách, položkách menu, skupinách odkazů a skupinách obrázků jsou uloženy ve formě xml dat. Jejich zpracování zajišťuje univerzální zavaděč, který obdrží požadovaný datový objekt k naplnění a pole s popisem údajů, a zajistí parsování xml dat a jejich převod do vlastností dotyčného objektu.

Práce s obrázky je řešena dynamicky, sestavovač nenačítá dopředu žádné informace o obrázcích. Teprve při jejich použití na konkrétní stránce se požádá zavaděč skupin obrázků o dodání informací o skupině nebo obrázku, a pokud je ještě nemá načtené z xml dat na základě jiného požadavku, tak zajistí jejich zavedení do paměti. Vlastní vložení obrázku do stránky provádí pak jedna z k tomu určených rutin renderu prvků stránek. Nad tímto řešením je pak postavena i třída obsluhující fotogalerii.

Pro podporu výstupů, kde je potřeba údaje stránkovat, je vytvořena jedna společná třída obecně obsluhující všechny potřebné úkony, a tato je pak ještě rozšířená ve druhé podpůrné třídě, která umožňuje vypisovat jednodušší tabulky z databáze.

Doplňující moduly

Základní kód stránek pak kromě sestavovače tvoří ještě několik modulů, které slouží pro údržbu webu, jako je editor aktualit, editor vzkazů, nástroje pro nastavení některých základních konfiguračních údajů v databázích, zálohovač dat, specializované moduly určené k inicializaci databáze a zpětnému nahrání záloh apod.

Poslední součástí celého systému je několik základních stránek, které zajišťují výpis aktualit, zobrazení mapy stránek a statistik přístupů, uživatelské vkládání vzkazů a jejich zobrazení a stránky ovládající přihlášení a odhlášení uživatele.

Cookies

Tento odstavec je určen těm, kterým leží na srdci ochrana svého soukromí. Tyto stránky používají dočasné cookies. Na straně uživatele se ukládá pouze identifikátor relace, ostatní údaje jsou uloženy na straně serveru. Po vypršení relace (tj. během asi 20 minut nečinnosti) se údaje na serveru zneplatní a obslužné rutiny na serveru je následně během zpracování dalších požadavků na práci se session navždy smažou. Na straně u uživatele je použitím dočasných cookies přednastaveno, aby je prohlížeč při svém uzavření také smazal. U běžných stránek určených jen k prohlížení se uložené údaje o relaci používají pouze k získání orientačních statistických údajů o intenzitě provozu na webu kvůli možnosti odlišit prostý počet přístupů na stránky od počtu jednotlivých návštěvníků. U některých stránek se dále používají jako paměť uživatelem předvoleného režimu prohlížení stránky (např. u fotogalerie pro paměť směru procházení obrázky). U stránek, kde uživatel požaduje uložení svých informací do nich, jsou pak údaje o relaci používány pro ochranu stránek a mohou být zalogovány do databáze. Uložené údaje neslouží ke sledování pohybu návštěvníků a nejsou nikomu jinému dále předávány. Většinu stránek je tedy možné používat i s vypnutými dočasnými cookies, ale někde si tím sami sobě omezíte možnosti.

Různá řešení

Při vývoji stránek jsem se potkal s množstvím různých problémů, a protože některé z nich mě stály dost času, tak jsem si občas udělal i nějaké poznámky k jejich řešení. Zde je pár z nich shromážděno. Třeba se to bude hodit i někomu jinému. Ale mnohé z těch věcí pocházejí někdy z roku 2007 a 2008, takže s postupujícím časem a modernějšími prohlížeči už budou překonané a jsou poplatné tehdejší době.

CSS - Fuzzy Specificity Hack

Tento hack jsem si sám pro sebe pracovně pojmenoval "bláznivá logika". Měl jsem problém, kdy jsem potřeboval odlišit Operu 7 od ostatních prohlížečů. Proč? Prostě se chovala v některé klíčové vlastnosti odlišně od ostatních prohlížečů. Odlišit ve stylopisech Operu není žádná sranda, obzvláště když máte problém jen s některou její verzí. Vývoj Opery je rychlý, a tak použití hacků, které obvykle využívají něco, co prohlížeč z CSS neumí k tomu, aby ho ohnuly, aby něco jiného udělal jinak než obvykle, narazí na to, že zneužitá neznalost Opery je zacelena výrobcem dříve než se autor takového pravidla s hackem naděje.

Řešení jsem hledal velmi dlouho a usilovně, protože na něm visela funkčnost hlavní navigace v této verzi Opery. Nakonec jsem objevil článek Fuzzy Specificity Hack. Pokud chcete pochopit jak to funguje, tak se nejprve podívejte jak se počítá váha selektorů, pokud jste o jejich váze ještě nic neslyšeli. Velmi stručně by se dalo říci, že váha se počítá způsobem * = 0, tag = 1, třída a atribut = 10, id =100. Ohodnotí se všechny části selektoru a součet všech vah je váhou celého selektoru. Pokud pro daný prvek je více pravidel, tak se použije to, jehož selektor má vyšší váhu. Pokud mají stejnou váhu, tak se použije to, které je uvedeno jako poslední (neuvažuji alternativu vnucení pomocí !important).

Opera 7 a její starší verze, a také Internet Explorer, se ale chovají jinak. Když dva selektory pravidel mají stejnou váhu, tak se nepoužije pravidlo, které je uvedeno jako poslední, ale porovná se váha jen poslední části obou selektorů a použije se to pravidlo, jehož váha poslední části selektoru je větší. Reálné využití je následující. Vyrobí se dvě pravidla se selektorem, jehož celková váha je stejná. Do pravidla, které je v předpisech uvedeno jako první, se vloží vlastnosti, kterými se má řídit pouze Opera 7 a její starší kolegyně. Do následujícího pravidla se pak dají vlastnosti pro ostatní prohlížeče (IE se samozřejmě pak zkoriguje nějakou další cestičkou, v mém případě pomocí podmíněných komentářů). Selektor prvního pravidla se napíše tak, aby jeho poslední člen měl větší váhu než poslední člen selektoru ve druhém pravidlu.

Když jsem to zkoušel, tak mi to nefungovalo. Poslední člen selektoru pravidla pro Operu 7 měl tvar TAG.TRIDA, tj. váhu 11, poslední člen selektoru v pravidlu pro ostatní měl tvar TAG, tj. váhu 1, a přesto Opera 7 brala pravidlo s váhou posledního členu 1. Řešení jsem našel metodou pokusů a omylů. Poslední člen selektoru pravidla pro ostatní prohlížeče se změnil na .TRIDA, tj. váha 10, a už to běhalo jak má.

Tento hack je na stránkách skutečně použit, podívejte se na pravidla #nav ul.navul a div#nav .navul v předpisu pro obrazovku. Zde se tímto koriguje fakt, že pro Operu 7 se musela u hlavního navigačního menu nastavit šířka na 100%, jinak se menu nezobrazovalo dobře, ale ostatní prohlížeče tam potřebovaly naopak hodnotu auto.

CSS - Velikost písma v prvcích formulářů

Pokud se prvkům formulářů vůbec nenastaví vlastnost font-size, tak nereagují na změnu velikosti písma uživatelem v prohlížeči (IE, FF). Když se jim teda nastaví (na relativní hodnotu), tak je problém u IE, že různé druhy prvků mají různou velikost, ikdyž ve stylopisu je nastavena stejná hodnota. Pro IE se tak musí velikost písma některých druhů prvků formuláře nastavit individuálně, pokud je požadován jejich stejný vzhled.

HTML a CSS - 2. úroveň menu a mezery mezi položkami v IE

Pokud je menu řešeno tak, jako naše, tj. nemá žádné rozměry určeny pevně, a celé se volně přizpůsobuje velikosti písma a skutečné délce textu v položkách, tak se v IE projeví chyba, kdy mezi položkami 2. úrovně dělá mezery. A to v případě, že jednotlivé položky uzavřené mezi tagy LI máte v souboru s HTML kódem každou zvlášť na svém řádku. Chybu zobrazení způsobují právě "bílé" znaky mezi jednotlivými položkami (tj. mezery a odřádkování). Buď musíte položky sesypat na jeden řádek za sebe a bez mezer mezi nimi, nebo to lze obejít následovně. Tagy A se v položkách obalí tagem DIV.

CSS - IE, media a expression

Když použijete v IE ve stylopisu pro jedno medium vlastnost vypočítanou pomocí expression, a po jiné medium ji nastavíte normálně na pevnou hodnotu, tak se vždy použije ta vypočítaná, nezávisle na aktuálním médiu. Lze to přebít jen tak, že pro druhé medium vlastnost nastavíte se zdůrazněním pomocí !important.

CSS - zdvojený okraj plovoucích prvků v IE

IE plovoucím (float: left/right) prvkům zdvojuje levý (pravý) okraj. Lze to obejít, když se takovému prvku pro IE nastaví display:inline.

PHP - pořadí zpracování výrazů

PHP zpracovává výrazy zleva doprava. Můžete na to snadno narazit, např. při použití operátoru podmínky. Např. jakou hodnotu si myslíte, že vrátí výraz TRUE ? 'A' : FALSE ? 'B' : 'C' ? Říkáte, že vrátí A ? Člověk intuitivně vyhodnocuje výraz jako TRUE ? 'A' : ( FALSE ? 'B' : 'C'), ale PHP ho zpracovává ve skutečnosti jako (TRUE ? 'A' : FALSE ) ? 'B' : 'C', takže skutečná hodnota kterou obdržíte je B. Tj. pokud potřebujete jiné pořadí zpracování než implicitně použije PHP, tak si ho stanovte vhodným rozmístěním závorek.

JS - problém s češtinou u starší Opery

Nejprve podmínky vzniku problému. Opera 8.01 a starší (ve verzi 8.54 se problém již neprojevoval). Opera má zapnuté automatické rozpoznávání jazykové stránky. Máme HTML kód, kde je v hlavičce nastaveno kódování na win1250. A linkuje se externí javascriptový kód, který též obsahuje texty v kódování win1250. Tyto texty se pomocí document.writeln() vkládají JS kódem do dokumentu. Některé takto vložené znaky, jako např. "č", se zobrazí ve špatném kódování, ačkoliv stejné znaky přímo obsažené v dokumentu se zobrazují správně.

Jedno řešení je přesvědčit uživatele, aby si v Opeře přepnul kódování z automatiky na win1250, nebo aby si upgradoval Operu na novější verzi.

Druhé řešení je do tagu <script>, kterým se linkuje externí soubor s javascriptovým kódem, přidat atribut charset = "windows-1250".

Apache - Modul Rewrite

Při implementaci přesměrovávání stránek pomocí modulu rewrite, jsem narazil na dva zásadní problémy. Oba se projevovaly jak na platformě Linux, tak i na Windows, takže neměly souvislost s operačním systémem, a nesouvisely s konfigurací Apache. Řešení se mi nakonec podařilo nalézt prostudováním zdrojových kódů od Apache 2.0.54 při současném rozboru logu od modulu rewrite. U prvního problému jsem nakonec objevil zmínku o možnosti testování dále uvedené proměnné i na Internetu, která potvrzovala moji domněnku, od druhého problému jsem na Internetu našel pouze zmínku, že někdo narazil na stejné chování.

Vnitřní přesměrování

První problém souvisí s faktem, že zpracování pravidel ze souboru .htaccess probíhá v režimu per-directory a nikoliv per-server. Pokud zpracování celého seznamu pravidel nevede buď na výsledek s flagem proxy, forbidden nebo gone, nebo výsledkem není absolutní vzdálená nebo absolutní lokální adresa, nebo výsledek převodu není shodný se vstupní hodnotou, tak se provede na konci vždy vnitřní přesměrování, kde vstupem je aktuálně přeložená adresa, a celé zpracování se provede ještě jednou s touto novou hodnotou. To se projeví tak, že se nám pravidla jakoby zacyklí a vykonají dvakráte po sobě. Od tohoto stavu je ale potřeba odlišit ta nechtěná zacyklení, která vzniknou skutečně špatně napsanou sadou pravidel.

Ve zdrojovém kódu Apache 2.0.54, v adresáři modules/mappers v souboru mod_rewrite.c ve funkci hook_fixup() lze vysledovat, za kterých podmínek se zpracování přímo ukončí, a za kterých bude spuštěno interní přesměrování. Při interním přesměrování lze najít v souboru http_request.c v adresáři modules/http místo, kde se nastavuje proměnná prostředí REDIRECT_STATUS. A právě testováním této proměnné v RewriteCond lze zabránit vzniku nechtěné smyčky.

Když do souboru .htaccess na začátek bloku přesměrovávacích pravidel vložíme např. následující pravidlo

RewriteCond %{ENV:REDIRECT_STATUS} !^$
RewriteRule .* - [L]

tak pokud dojde k vnitřnímu přesměrování, tak se zpracování ihned ukončí beze změny adresy a k opakovanému volání nedojde.

Zdvojení konce adresy u virtuálních adresářů

Druhý problém se projevuje za těchto podmínek. V souboru .htaccess je seznam pravidel, který způsobí, že na adresu se aplikují postupně dvě nebo více pravidel. A dále, že adresa zadaná v http požadavku, se prvotně ještě před použitím pravidel ze souboru .htaccess převede na takovou fyzickou adresu, která je virtuální a ve skutečnosti neexistuje. Např. na webu, kde ve skutečnosti používám dynamické adresy, chci použít statické adresy, ve kterých jsou parametry nahrazeny virtuální strukturou adresářů.

Pak dojde k chování, kdy při překladu v modulu rewrite jsou adresy nahrazovány chybně. V adrese dojde ke zdvojování její poslední části začínající tím, co obsahuje virtuální adresář nejvyšší úrovně. Tj. např. pokud přeložení URL adresy obsažené v http požadavku vytvoří fyzickou adresu c:/www/a/b/index.htm, kde adresář b je virtuální a fyzicky neexistuje, tak při vstupu do zpracování druhého pravidla v pořadí se bude pracovat s chybnou fyzickou adresou c:/www/a/b/index.htm/index.htm. Nebo pokud je fyzická adresa c:/www/a/b/c/index.htm a opět adresář b je již virtuální, tak se bude pracovat s chybnou adresou c:/www/a/b/c/index.htm/c/index.htm. Pro úplnost je ještě potřeba uvést, že pro tento příklad je RewriteBase nastaveno na /a a DocumentRoot na c:/www. A jsme v režimu per-directory, kdy se zpracovává obsah .htaccess, a nikoliv v režimu per-server a zpracování httpd.conf.

Odpověď se dá nalézt ve zdrojovém kódu souboru mod_rewrite.c v adresáři modules/mappers ve funkci apply_rewrite_rule() v práci s postfixem. Konkrétně se jedná o práci s proměnnými uri, r->path_info a r->filename. V našem případě s variantou požadované fyzické adresy c:/www/a/b/index.htm bude při prvním volání funkce apply_rewrite_rule()

uri = r->filename = c:/www/a/b
r->path_info = /index.htm
perdir = c:/www/a

Protože path_info je nenulové, tak se nejprve provede doplnění adresy uri o hodnotu v path_info. Potom se z uri odstraní úvodní část shodná s perdir, takže uri = b/index.htm. Položme předpoklad, že pravidlo nezpůsobí žádnou změnu, a výsledkem má být stejná hodnota (např. skutečnou odvedenou prací je zpracování parametrů v podmínce a nastavení proměnné prostředí). Potom bude newuri = uri = b/index.htm. Jenže následně se nastaví r->filename na hodnotu newuri, která je vlastně jiná, než hodnota na vstupu, ačkoliv k žádné změně adresy nemělo dojít. Následně se r->filename doplní o prefix perdir a bude mít hodnotu c:/www/a/b/index.htm. Zdánlivě vpořádku, toto pravidlo vrátí správný výsledek. Problém nastane, když se vzápětí začne zpracovávat druhé pravidlo ve fázi doplnění o postfix. Nyní je na vstupu funkce apply_rewrite_rule()

uri = r->filename = c:/www/a/b/index.htm
r->path_info = /index.htm
perdir = c:/www/a

Výsledná vstupní uri vzniklá sloučením uri a postfixu r->path_info je c:/www/a/b/index.htm/index.htm. Od tohoto bodu je v uri chybná adresa.

Jediný způsob, jak toto chování eliminovat je, když proměnná r->path_info bude na vstupu do funkce apply_rewrite_rule() prázdná. A jediný způsob, jakým se mi toho podařilo dosáhnout bylo, že struktura virtuálních adresářů musí fyzicky existovat.

Rekapitulace jak problém vyřešit - buď přesměrování napsat tak, aby se aplikovalo maximálně jediné pravidlo, nebo virtuální adresáře vytvořit i fyzicky.

Pokud by to někdo chtěl dále sledovat, odkud se proměnná path_info původně vezme, tak se může odpíchnout v adresáři server od zdrojového kódu v souboru request.c a proměnné r->path_info, kde r je ukazatel na datovou strukturu request_rec* r.

Poznámka doplněná po 5ti letech - ve versi Apache 2.2.12 pak byl do pravidel doplněn příznak DPI, pomocí kterého lze nastavit, aby se obsah proměnné path_info zahazoval, a který řeší výše popsaný problém.

CSS - korekce odlišného chování prohlížečů

Velké problémy mi způsobovala odlišná podpora a zpracování jednotlivých vlastností u různých prohlížečů. Především bylo nutné vypořádat se s problémem IE versus ostatní prohlížeče, kde byly podstatné rozdíly ve zpracování box-modelu a i v chápání velikosti písma. Situaci ještě komplikoval fakt, že novější verze IE část chyb odstranily a v tzv. standardním režimu více dodržují specifikaci CSS, ale umí pracovat i v tzv. quirk módu, kdy zobrazují shodně jako starší verze IE, a pro jistotu tento způsob práce ve dvou režimech přebraly i jiné prohlížeče, jako např. Opera.

Pro dosažení snadné podpory více prohlížečů a to i starších byl nakonec zvolen režim, kdy se pomocí kombinace prvního řádku v HTML kódu, kde je komentář v přesně daném tvaru, a druhého řádku, kde je doctype opět s přesně daným tvarem, přepnou prohlížeče tak, aby IE i včetně verse 7 používal quirk mód. Pak není nutné řešit různé rozdíly chování pro různé verse IE.

DOCTYPE by měl ve skutečnosti sloužit k seznámení parseru prohlížeče se syntaxí použitého značkovacího jazyka, odkazuje na definici typu dokumentu. IE ale na jeho obsah reaguje i přepnutím mezi standardním a quirk módem, kdy se za určitých podmínek snaží zpracovávat dokumenty buď v quirk módu obdobně jako jeho starší verse, nebo ve standardním režimu zpracovává značky a styly novým způsobem. A Opera se po IE v tomto chování částečně opičí.

Vliv prvních 2 řádků dokumentu na mód prohlížeče
Varianta 1 (začíná doctype bez rozepsané URL)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

Varianta 2 (začíná komentářem následovaným doctype s rozepsanou URL)
<!-- rezim quirk pro IE a rezim standard pro jine -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">

Varianta 3 (začíná doctype s rozepsanou URL)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
Vliv variant na režim prohlížeče
Prohlížeč Varianta 1 Varianta 2 Varianta 3
OP6SSS
OP7.0QQS
OP7.5QSS
OP8.0QSS
OP8.5QSS
OP9.0S1SS
IE5.0QQQ
IE5.5QQS
IE6.0QQS
IE7.0QQS
FF1.5SSS
Vliv módu na písmo a boxmodel
Režim Písmo 12px Šířka boxu
S (standard)smallwidth+výplň
Q (quirk)x-smallwidth (výplň je uvnitř)
S1 (standard odlišný)x-smallwidth+výplň

Korekce chování pro IE je zajištěna tak, že se pro něj linkuje extra stylový předpis, který pozmění některé části hlavního stylového předpisu. Vložení korekce jen pro IE je zajištěno za pomoci tzv. podmíněných komentářů, které umí pouze IE.

Způsob vložení korekce IE podmíněným komentářem
<!--[if gte IE 5]>
  kód zpracovávaný pouze IE verse 5 a novější
<![endif]-->

Pro novější prohlížeče IE je pak za pomoci podmíněného komentáře provedeno přepnutí do režimu emulace IE7.

Způsob zapnutí emulace IE7 podmíněným komentářem
<!--[if gte IE 8]>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
<![endif]-->

CSS - způsob nastavení proměnné šířky stránky u IE

Potřeboval jsem nastavit minimální a maximální šířku hlavního sloupce, ale IE bohužel tehdy nepodporoval odpovídající vlastnosti CSS min-width a max-width. Ale naopak podporoval provádění výpočtů použitím expression v hodnotách vlastností. Pro IE se tedy na stránkách provádí poměrně komplikovaný výpočet, kdy se z aktuální šířky okna a velikosti písma vypočítá požadovaná šířka hlavního sloupce.

Ukázka výpočtu šířky sloupce v korekčním předpisu pro IE
#pgwrapper {
  width: expression(document.body.clientWidth >=
         (parseInt(document.documentElement.currentStyle.fontSize) <= 10 ?
         ((parseInt(document.documentElement.currentStyle.fontSize) - 1)
         * 4/3 * 67) :
         ((parseInt(document.documentElement.currentStyle.fontSize)- 2)
         * 4/3 * 67) ) ? "65em" :
         document.body.clientWidth <=
         (parseInt(document.documentElement.currentStyle.fontSize) <= 10 ?
         ((parseInt(document.documentElement.currentStyle.fontSize) - 1)
         * 4/3 * 51) :
         ((parseInt(document.documentElement.currentStyle.fontSize)- 2)
         * 4/3 * 51) ) ? "49em" : "96%");
}

CSS - 2. a další úroveň rozbalovacího menu

Pro rozbalování položek druhé úrovně menu je potřeba aby prohlížeč podporoval pseudotřídu :hover i u jiných prvků než jen u kotev. Bohužel IE až do verze 6 toto neuměl. Jednou z možností je přes vlastnost stylů behavior přidat k položce ve stylu soubor .htc s javaskriptem, který provede korekci chybného chování. Na Internetu byl ale zmiňován problém s chováním WIN XP s SP2, kdy docházelo k chybám načítání tohoto souboru ze serveru (jednalo se o problémy s typem dokumentu, kdy webserver posílá .htc soubor s mime-type nastaveným na text/x-component). Proto byla zvolena jiná alternativa, kdy se pro IE načítá normální externí javaskriptový kód, který naučí IE potřebnou pseudotřídu :hover i pro prvky seznamu.

JS kód řešící problém s pseudotřídou :hover u seznamu v IE
function opravIEhoverElement(jmeno) {
  var element = document.getElementById(jmeno);
  if (element) {
    var liList = element.getElementsByTagName("li");
    for (var i=0; i<liList.length; i++) {
      liList[i].onmouseover=function() {
                              this.className+=" over";
                            }
      liList[i].onmouseout=function() {
                             this.className=this.className.replace(" over","");
                           }
    }
  }
}

function opravIEhover() {
  var name = navigator.userAgent;
  if ( (name.indexOf("MSIE")!=-1) && (name.indexOf("Opera")==-1) ) {
    if ( document.all && document.getElementById && document.getElementsByTagName) {
      opravIEhoverElement("nav");
    }
  }
}

window.onload=function() {
  opravIEhover();
}

Funkce korečního skriptu je vpodstatě jednoduchá. Najde v dokumentu element zadaného jména (v tomto případě se jménem nav) a ve stromu počínaje jím najde všechny elementy LI. Těmto elementům pak přidá dvě události. První způsobí, že po najetí kurzorem myši nad element se mu přidá třída over, a druhá způsobí, že po odjetí kurzoru se přidaná třída opět odebere. Ve stylovém předpisu se potom pro IE místo pseudotřídy :hover použije normální třída over.

MySQL - problém s INSERT ... ON DUPLICATE KEY UPDATE

Po přenesení stránek z testovacího prostředí, kde běhaly na MySQL 5.0 na tabulkách MyISAM, na webhosting, kde je MySQL 5.5 a tabulky InnoDB, jsem zjistil odlišné chování konstrukce INSERT ... ON DUPLICATE KEY UPDATE. V tabulce aktualizované tímto příkazem byl jeden ze sloupců typu primární klíč s autoinkrementací a další sloupec nastavený jako UNIQUE. Na novějším serveru a tabulkách InnoDB se hodnota LAST_INSERT_ID neustále zvyšovala, ikdyž se neprováděl INSERT, ale jen UPDATE. Projevovalo se to tak, že ve sloupci s autoinkrementem vznikaly u vložených záznamů velké díry v číselné řadě. Nakonec jsme to obešel tak, že jsem příkaz přepsal pomocí jiné konstrukce bez použití ON DUPLICATE KEY.

PHP - XMLReader - nízkoúrovňové chyby a dopředné zpracování

Pro zpracování XML dat používám kvůli rychlosti a nárokům na paměť jako základ rutiny parseru XMLReader, a tento je zase postavený nad knihovnou libxml. Při přepisu kódu z ASP.NET/C# zpět do PHP jsem si s tímto parserem užil několik hodin hledání chyb v kódu i ve zdrojových XML datech, které vlastně neexistovaly, resp. byly někde jinde, než parser hlásil.

V původním řešení na platformě ASP.NET jsem po zachycení výjimek neměl problém naprosto přesně identifikovat, kde jsou vstupní data XML vadná, a toto ošetřit slušně vlastním chybovým výpisem. V PHP mi to blblo, i přes zachytávání výjimek z toho vypadávala neodchytitelná chybová hlášení a chyby, které to hlásilo, jsem nemohl stále nalézt, programový kód byl vpořádku, vstupní data také, a přesto zpracování stále v určitém místě kolabovalo, navíc se zcela nelogicky poloha místa, kde parser havaroval, měnila s množstvím textu. Nakonec jsem se značnou nelibostí zjistil, že parser si načítá data ze vstupního souboru po větších blocích textu a tyto bloky si parsuje celé, tj. dopředu před místo, které z něj zatím čtu, a pokud v předzpracovaném bloku je nějaká chyba, kterou bych o něco později zachytil a ošetřil, tak zhavaruje a navíc hlášení, které vyhodí, pochází z nízké úrovně zpracování v libxml, takže se prostě natvrdo vypíše směrem k uživateli a nelze tomu zabránit. Např. stačí aby nebyly správně spárované značky. To bohužel způsobuje dost problém najít pak chybu ve vstupních XML datech, protože místo, kde parser skutečně zhavaruje, nelze programově zjistit, a musí se hledat, kde by to tak asi mohlo být.

Zdroje informací použité při návrhu stránek

Při návrhu a realizaci stránek byla použita celá řada zdrojů informací, ať už v tištěné podobě nebo v podobě informací někde na Internetu. Pro případnou inspiraci z nich zde některé uvádím:

Literatura

  • Zeldman, J.: Tvorba webů podle standardů. Computer Press, 2004.
  • Cederholm, D.: Flexibilní web design. Computer Press, 2006.
  • Mikle, P.: Referenční příručka XCSS. Zoner Press, 2004.
  • Mikle, P.: Referenční příručka XDHTML. Zoner Press, 2004.
  • Prokop, M.: CSS kaskádové styly pro webdesignéry. Mobil Media, 2003.
  • Boumphrey, F. a kol.: XHTML průvodce vývojáře. Mobil Media, 2002.
  • Musciano, C., Kennedy, B.: HTML a XHTML kompletní průvodce. Computer Press, 2000.
  • Naramore, E. a kol.: Vytváříme webové aplikace v PHP5, MySQL a Apache. Computer Press, 2006.
  • Ullman, L.: PHP a MySQL. Computer Press, 2004.
  • Castagnetto, J.: Programujeme PHP profesionálně. Computer Press, 2004.
  • DuBois, P.: MySQL profesionálně. Mobil Media, 2003.
  • Flanagan, D.: JavaScript Kompletní průvodce. Computer Press, 2002.
  • Huseby, S. H.: Zranitelný kód. Computer Press, 2006.
  • Mindžák, R.: Dokonalý webdesign. Computer Press, 2002.
  • Spainhour, S., Eckstein, R.: Webmaster v kostce. Computer Press, 1999.
  • Bradley, N.: XML kompletní průvodce. Grada 2000.
  • Lavin, P.: PHP objektově orientované. Grada, 2009.
  • Kofler, M., Bernd, Ö.: PHP5 a MySQL5 Průvodce webového programátora. Computer Press, 2007.

Internet

Nahoru