PÅ™i tvorbÄ› jakékoli aplikace je dobré vyvažovat pÅ™ehlednost zápisu kódu s jeho efektivitou. Protože interprety JavaScriptu bohužel nejsou z nejrychlejÅ¡Ãch, pÅ™icházà velmi Äasto ke slovu právÄ› faktor druhý, na úkor intuitivnosti zápisu. Jako tÅ™eba u následujÃcÃho problému:
Máme barevné složky R, G a B, z nichž každá je vyjádÅ™ena desetinným ÄÃslem v intervalu <0; 1>. Z tÄ›ch potÅ™ebujeme zÃskat Å™etÄ›zec ve tvaru RRGGBB. Složky bude tedy tÅ™eba zvÄ›tÅ¡it do rozsahu 0–255, zaokrouhlit, pÅ™evést na ÄÃsla Å¡estnáctková a jednoznakové výsledky zleva doplnit nulou, aby sestavený Å™etÄ›zec mÄ›l vždy právÄ› Å¡est znaků. Jak ale splnit poslednà požadavek co nejrychleji a bez podmÃnÄ›ného pÅ™idávánà nuly?
Metoda ÄÃslo.toString(16) sice pÅ™evede ÄÃslo do Å¡estnáctkové soustavy, ale k doplnÄ›nà poÄáteÄnà nuly ji pÅ™imÄ›t nelze. Na sprintf() můžeme zapomenout a co se týÄe regulárnÃch výrazů, jejich vyhodnocenà je pomalé. NabÃzà se vkládat nulu vždy a potom z Å™etÄ›zce zprava vytáhnout dva znaky, tedy ('0'+cislo).substr(-2), jenže IE záporný offset nepodporuje.
Nedávno mÄ› trklo zajÃmavé Å™eÅ¡enÃ. K ÄÃslům nejprve pÅ™iÄteme 256, ÄÃmž po pÅ™evodu zÃskáme vždy nejménÄ› 10016 a nejvÃce 1FF16. Pak zbývá jen oÅ™Ãznout poÄáteÄnà jedniÄku. Jak jsem zmÃnil na zaÄátku, pÅ™ehlednost takového algoritmu je na pováženou, ale za tu efektivitu jistÄ› stojÃ:
function rgbToHex(R, G, B) { return ( Math.round(256 + 255*R).toString(16).substr(1) + Math.round(256 + 255*G).toString(16).substr(1) + Math.round(256 + 255*B).toString(16).substr(1) ) }
Å ablony jsou běžnou souÄástà dynamických webů. Nenà proto divu, že dosud vzniklo nemalé množstvà šablonovacÃch systémů, vÃce Äi ménÄ› vydaÅ™ených. Smarty osobnÄ› Å™adÃm do té druhé skupiny, myslÃm, že se jedná o nepraktický molouch spatlaných regulárnÃch výrazů. MÃsto dalÅ¡Ãho hanobenà Smarty zneužiji jeho nestydaté velikosti a dám ji do kontrastu se svým skromným Å¡ablonovacÃm uzlÃÄkem o cca 70 řádcÃch.
Žádná odlehÄená syntaxe, nic se nekompiluje, Å¡ablonu pÅ™edstavujà běžné PHP soubory, které bych se koderovi bez znalosti PHP zdráhal svěřit. Neznà to pÅ™ÃliÅ¡ pÅ™esvÄ›dÄivÄ›, že? PÅ™inejmenÅ¡Ãm pro vlastnà projekty je to ale bájeÄná vÄ›c. Ono to totiž má i výhody.
Ten šablonovacà skript jestli chcete vidět. Ano? Tak tady je (pro PHP5).
A tuhle je ukázka, jak se s nÃm bezva pracuje:
require_once('Template.inc.php');
$doc = new Template('tpl/'); // šablony jsou v adresáři tpl/
$doc->nazev = 'Hudebnà nástroje'; // nastavÃme nadpis stránky
$nastroje[] = array('nazev'=>'Harmonika', 'ladeni'=>'C#');
$nastroje[] = array('nazev'=>'PÅ™ÃÄná flétna', 'ladeni'=>'F');
// zparsujeme seznam nástrojů
foreach($nastroje as $nastroj) {
$doc->parse('nastroj.php', '.NASTROJE', $nastroj);
}
// tisknout šablonu stranka.php
$doc->parse('stranka.php', Template::dstPrint);
Neboli:
$doc. Potom můžeme nastavit jejà vlastnosti – Å™Ãkejme jim z pohledu Å¡ablony globálnà promÄ›nné, i když tento termÃn má obecnÄ› jiný význam. Globálnà proto, že jsou pÅ™Ãstupné ve vÅ¡ech Å¡ablonách parsovaných tÃmto objektem.foreach dvakrát zparsujeme Å¡ablonu tpl/nastroj.php. Výsledek se pÅ™ipojà do promÄ›nné $doc->NASTROJE (PÅ™ipojà se dÃky té teÄce na zaÄátku, kdyby tam nebyla, tak tu promÄ›nnou pÅ™epÃÅ¡eme.)Template::dstPrint namÃsto uloženà tiskneme. NÄ›kdy se může hodit Template::dstReturn, ÄÃmž, jak jistÄ› tuÅ¡Ãte, obdržÃme výsledek návratovou hodnotou.
<html>
<head>
<title><?=htmlspecialchars($nazev)?></title>
</head>
<body>
<h1><?=htmlspecialchars($nazev)?></h1>
<ul>
<?=$NASTROJE?>
</ul>
</body>
</html>
<li><strong><?=htmlspecialchars($nazev)?></strong> - laděnà <?=$ladeni?></li>
V obou šablonách jsem záměrně použil stejnou proměnnou $nazev, aby bylo vidět, že lokálnà proměnné majà přednost.
$res = mysql_query('SELECT jmeno, prijmeni FROM uzivatele');
while($row = mysql_fetch_assoc($res)) {
$doc->parse('uzivatel.php', '.UZIVATELE', $row);
}
Metodu Template::init() voláme na zaÄátku Å¡ablony, když je tÅ™eba urÄit, které rozÅ¡iÅ™ujÃcà funkce Å¡ablona použÃvá (tÅ™eba pro práci s URL). NedÄ›lá nic jiného než require_once vÅ¡ech skriptů, které jsou uvedeny jako parametry. Hledá je ve stejném adresáři, kde je umÃstÄ›na tÅ™Ãda a na konec automaticky doplňuje koncovku .inc.php. Je-li napÅ™. tÅ™Ãda umÃstÄ›na v adresáři lib/, pak Template::init('string') provede require_once('lib/string.inc.php')
Template->check() ověřuje dostupnost Å¡ablony. Vracà TRUE pokud daná Å¡ablona existuje a lze ji pÅ™eÄÃst.
Template->clear() Äistà vÅ¡echny nastavené vlastnosti objektu.
Zpracovánà šablon je pekelnÄ› rychlé (hlavnÄ› proto, že se nemusejà kompilovat). Dále, spousta Å¡ablonovacÃch systémů použÃvá k nastavenà promÄ›nných nÄ›jakou funkci, nejÄastÄ›ji assign(). Nemohou tak dÄ›lat psà kusy jako tÅ™eba list($doc->id, $doc->nazev) = mysql_fetch_row($res), což tady možné je.
Zde popsaný bastl nepovažuji za průlomové dÃlo, ostatnÄ› pár hodnÄ› podobných jsem už vidÄ›l. Na svou jednoduchost mi ale pÅ™ijde nesmÃrnÄ› efektivnà a jistÄ› bude pro nÄ›koho alespoň inspiracÃ.
HTML definuje celou Å™adu formulářových prvků, nÄ›které situace ale vyžadujà komfortnÄ›jšà ovládánà než tato základnà sada nabÃzÃ. Ke slovu se pak dostává DHTML, které se se základnÃmi prvky vhodnÄ› smÃsÃ. ÄŒasto ve formulářÃch postrádám textové pole výhradnÄ› pro celoÄÃselnou hodnotu, se Å¡ipkami pro inkrementaci a dekrementaci po pravé stranÄ› (v Å™eÄi Visual Basicu by to byl TextBox provázaný s objektem UpDown). To ale nechme na jiný Älánek…
Co mi vpravdÄ› až donedávna chybÄ›lo vÃc byl dialog pro výbÄ›r barvy. Velká Äást uživatelů hexadecimálnà zápis barvy neovládá a je dobré jim výbÄ›r odstÃnu usnadnit nÄ›jakým jednoduchým rozhranÃm, jednoduššÃm než Vyber barvu v Photoshopu a zkopÃruj ji. Tedy, ne že by takových rozhranà k dneÅ¡nÃmu dni už desÃtky neexistovaly, povÄ›tÅ¡inou ale bývajà realizována jako klikatelné matice 216 web-safe barev, což je hodnÄ› málo – proÄ nedopřát uživateli vÃce volnosti? A tak, hnán moudrým heslem, rozhodl jsem se vytvoÅ™it color picker vlastnÃ, minimalistický, avÅ¡ak s volbou barvy velejemnou.
Do svÄ›ta tedy dnes vypouÅ¡tÃm nástroj jscolor. NechÅ¥ má spokojených uživatelů, jako je konkurenÄnÃch projektů, a aÅ¥ poskytne hezkých barev alespoň z půlky tolik, kolik pÅ™i ladÄ›nà padlo nadávek na IE.
PozadÃ: Text:
TÃmhle Älánkem bych rád zapoÄal svou obÄasnou knihovnu regulárnÃch výrazů, i když vÃm že podobné projekty se už nÄ›jaký ten pátek po internetu válejÃ.
Na úvod jsem si Å¡etÅ™il Äasovou známku. Výraz propustà téměř vÅ¡echny platné formáty, kterými lze v MySQL nastavovat sloupec TIMESTAMP. KromÄ› formátu kontroluje také platost data a Äasu, a věřte nebo ne, poradà si i s pÅ™estupnými roky. Možná proto je tak nevkusnÄ› dlouhý. Zadané datum a Äas mohou být v rozmezà 1970-01-01 00:00:00 až 2037-12-31 23:59:59. Výraz peÄlivÄ› zkontrolován cyklem v celém rozsahu :-)
/^((((19)?[7-9][0-9]|(20)?([0-2][0-9]|3[0-7]))[[:punct:]]+(0?2[[:punct:]]+(0?[1-9]|1[0-9]|2[0-8])|
(0?[469]|11)[[:punct:]]+(0?[1-9]|[12][0-9]|30)|(0?[13578]|10|12)[[:punct:]]+(0?[1-9]|[12][0-9]|3[01])))|
((19)?(8[048]|[79][26])|(20)?([02][048]|[13][26]))[[:punct:]]+0?2[[:punct:]]+29)([[:punct:]\s]+([01]?[0-9]|2[0-3])
([[:punct:]]+([0-5]?[0-9])([[:punct:]]+([0-5]?[0-9]))?)?)?$/
1970-01-21
2037-3#24 16&39
08-3-24 16:39:42
2008?03+24@!_16%39?42
200803-24-16-39-42
20080324163942
U administrace je tÅ™eba ve vÄ›tÅ¡inÄ› pÅ™Ãpadů poÄÃtat s tÃm, že ji může použÃvat i vÃce uživatelů naráz. Je zÅ™ejmé, že provedou-li zmÄ›nu stejné databázové buňky souÄasnÄ›, poslednà zápis pÅ™episuje ostatnÃ. O tomhle problému se v souvislosti s PHP rozepsal Jakub Vrána.
Jsou ale situace, kdy pravidlo poslednà vyhrává je tÃm nejmenÅ¡Ãm zlem. Jednou takovou je triviálnà pÅ™evrácenà boolean sloupce. MÄ›jme napÅ™Ãklad výpis Älánků u nichž je tlaÄÃtko publikovat, které se kliknutÃm pÅ™epÃná na nepublikovat a zase zpÄ›t. URL takového tlaÄÃtka může vypadat takto:
?clanek=70&akce=prohodPublik?clanek=70&akce=publikovat pro nepublikovaný Älánek?clanek=70&akce=nepublikovat pro publikovaný ÄlánekPrvnà zápis je jednoduchý a univerzálnÃ, protože ve výpisu mÄ›nÃme jenom ID Älánku a akce zůstává stejná. PÅ™evrátit boolean sloupec v databázi je také snadné. PÅ™esto takové Å™eÅ¡enà nelze doporuÄit, protože pÅ™evracejÃ-li uživatelé A a B hodnotu souÄasnÄ›, vÅ¡e se takhle zamotá:
Druhý zápis si ve stejné situaci vede znamenitě. Uplatňuje ono pravidlo poslednà vyhrává:
Neboli PHP, dost! Možná to bude pro nÄ›koho novinka, ale PHP se dá taky vypnout. V takovém pÅ™ÃpadÄ› server odeÅ¡le skripty tak jak ležà a běžÃ. Jde mimochodem o skvÄ›lý způsob, jak zajistit bezpeÄnost pÅ™i uploadovánà souborů formulářem. DoteÄ, když jsme se chtÄ›li vyhnout spuÅ¡tÄ›nà cizÃho PHP skriptu na serveru, museli jsme (nÄ›kteÅ™Ã) preciznÄ› kontrolovat koncovku Äi vyhodnocovat obsah. Ale ono staÄà udÄ›lat v daném adresáři soubor .htaccess obsahujÃcÃ:
php_flag engine off
VÅ¡echny PHP skripty kolem takového .htaccess (vÄetnÄ› podadresářů) ztrácejà na své skriptovitosti. Stávajà se z nich obyÄejné textové soubory které nikomu ani v nejmenÅ¡Ãm nevadÃ. TÅ™i vÄ›ci je tÅ™eba mÃt na zÅ™eteli:
To jsem jednou potÅ™eboval udÄ›lat barevný pÅ™echod. Ale ne GIMPárnu na jedno použitÃ, nóbrž pÅ™echod dynamický, nÄ›co jako že by se zavolal soubor a vono se to vygenerovalo a tvářilo jako obrázek. S PHP a knihovnou GD je vÄ›c snadná a pÅ™idá-li se i mod_rewrite, pak i velmi sluÅ¡ivá. LaÅ¥ku jsem si nastavil zhruba do téhle výše:
Co se týÄe bodu 1, skript dostane seznam klÃÄových barev a velikosti mezer které má mezi nimi proložit pÅ™echodem. Jako oddÄ›lovaÄ takového seznamu jsem zvolil znak VaÅ¡e komentáře mÄ› pÅ™imÄ›ly zmÄ›nit oddÄ›lovaÄ na spojovnÃk "-" KlÃÄové barvy se zapisujà šesti velkými hexadecimálnÃmi ÄÃslicemi, mezery desÃtkovÄ›. Aby se mezera odliÅ¡ila od barvy, může mÃt maximálnÄ› pÄ›t cifer – v praxi se použijà nanejvýš ÄtyÅ™i. Zbývá jeÅ¡tÄ› rozliÅ¡it orientaci (bod 2). Tak co tÅ™eba jednÃm malým pÃsmenem na zaÄátku? A bude to buÄ + který asi nejlépe znázorňuje spojovánÃ.x pro horizontálnÄ› se opakujÃcà pÅ™echod nebo y pro pÅ™echod s opakovánÃm vertikálnÃm.
Bod 3: Skript na konci, pokud je to možné, uložà výsledek do souboru. Název souboru má stejný tvar s jakým pracuje mod_rewrite, takže pÅ™i pÅ™ÃÅ¡tÃm požadavku už soubor fyzicky existuje a má pÅ™ednost. Když vÃm, že obrázek potÅ™ebuju jenom jednou a je zbyteÄné ho cachovat (tÅ™eba jako v testovacÃm rámeÄku nÞ), pÅ™idám na konec parametr ?tmp. Jelikož parametry nejsou souÄástà názvu souboru, majà cachované soubory opÄ›t pÅ™ednost. A proÄ je to cachovánà tak nechutnÄ› důmyslné? Protože pÅ™episovánà URL je nastaveno case-sensitive, takže v cache nevzniknou duplicity – každý pÅ™echod je jednoznaÄnÄ› identifikován. Nuže a bod 4 vyÅ™eÅ¡Ãme omezenÃm délky celého pÅ™echodu – dejme tomu na 5000px?
Jak je popsáno výše, na zaÄátku musà být malé pÃsmeno x/y, za nÃmž následujà klÃÄové barvy a ÄÃselnÄ› vyjádÅ™ené mezery mezi nimi. Pokud mezi barvami prolnutà být nemá (tedy nulová mezera), pak se zapÃÅ¡e ihned dalšà barva, napÅ™. yFF00FF-00FF00 jsou fialový a zelený pixel vedle sebe. Jednoduchý gradient pro svislé opakovánà (y) zÃskáme tÅ™eba pod tÃmhle názvem:

Délku celého pruhu spoÄÃtáme souÄtem klÃÄových barev (3) a mezer mezi nimi (5+2). Pruh je tedy dlouhý 10px.
gradient/ si zkopÃrujete kam je pohodlnogradient/y00FF00-300-0000FF.png je 302px dlouhý pÅ™echod od zelené k modréKdo náhodou nemá k dispozici mod_rewrite, může skript volat pÅ™Ãmo: gradient/gradient.php?repeat=y&grad=00FF00-300-0000FF
… když by staÄil 1px? TuÄňákům nestaÄÃ. A možná i tygrům, pÅ™iznám se, že jsem po tom pÅ™ÃliÅ¡ nepátral. Problém je v hladkosti pÅ™echodu. ZatÃmco pod Windows je opakovaný pÅ™echod stejný pÅ™i jakékoli Å¡ÃÅ™ce pruhu, FF/Linux ukáže 1px proužek pÅ™i nižšà barevné hloubce jako nekoukatelnÄ› ohyzdné Äáry. ZjevnÄ› nejprve obrázek proložà a teprve potom ho opakuje. Je tedy jasné, že jednorozmÄ›rný pÅ™echod nemůže proložit nikterak rozmanitÄ›, ovÅ¡em dostane-li vÄ›tšà plochu, stane se s nÃm pÅ™ibližnÄ› tohle:

Opakovaný ÄernobÃlý pÅ™echod pÅ™i 8-bitové hloubce (FF/Linux)
K pÄ›ti pixelům jsem doÅ¡el po sáhodlouhém zkouÅ¡enÃ. VÅ¡e do 3px je bÃda, 4px zaÄÃnajà být pÅ™ijatelné a pÄ›t – bingo! Vyššà hodnoty samosebou pÅ™inášejà výsledek o Å¡petku lepÅ¡Ã, ale to už je pÅ™ÃliÅ¡ na úkor velikosti souboru (aÄkoli nijak drasticky, PNG komprese se celkem vytáhla). A protože tÄ›ch 5px je krásná a vždy použitelná hodnota, dal jsem ji na pevno do hlaviÄky skriptu namÃsto do URL, které je tÃm jednoduššÃ. PÅ™ipomÃnám, že fujtajblproužkový problém se týká jen nÞšÃch barevných hloubek (do 16 bitů).
body {
background:url('gradient/x664477-600-CC99FF.png') left top repeat-x fixed #CC99FF;
}