Jsou tyto URL stejné?
Otázka, kterou si klade řada webmasterů: vnímají vyhledávače tyto URL jako stejné? Jak s nimi naložit?
http://example.com/articlehttp://example.com/article/http://example.com/Articlehttps://example.com/articlehttp://www.example.com/article
http://example.com/article?a=1&b=2http://example.com/article?b=2&a=1
Stručná odpověď by byla: „URL jsou odlišné.“ Chce to ale podrobnější rozbor.
Z pohledu uživatelů se tyto adresy liší v drobnostech, kterým nepřikládají žádnou váhu. Tedy je vnímají jako stejné, ačkoliv z technického hlediska jde o adresy různé. Říkejme jim třeba adresy podobné. V zájmu uživatelského prožitku proto dodržujte 2 zásady:
- Nedovolte, aby se na podobných adresách nacházel odlišný obsah. Jak záhy ukážu, nevedlo by to jen ke zmatení uživatelů, ale i vyhledávačů.
- Umožněte uživatelům přístup i přes podobné adresy.
Pokud se adresy liší v protokolu http / https
nebo doméně s www či bez, považují je vyhledávače za
různé. Nikoliv tak uživatelé. Bylo by tedy fatální chybou na takto
podobné adresy umístit různý obsah. Nicméně chybou by bylo
i znemožnění přístupu přes podobnou adresu. Musí tedy fungovat
adresa s www i bez www. Přičemž SEO nabádá
držet se jedné varianty a ostatní na ni přesměrovávat HTTP kódem 301. To
lze u www subdomény zajistit například souborem
.htaccess:
# presmerovani na variantu bez www
RewriteCond %{HTTP_HOST} ^www\.
RewriteRule ^.*$ http://example.com/$0 [R=301,NE,L]
# presmerovani na variantu s www
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^.*$ http://www.example.com/$0 [R=301,NE,L]
Schválně si hned vyzkoušejte, jestli vaše servery přesměrovávají a to
včetně celé adresy a správného
předání parametrů. Nezapomeňte i na varianty
www.subdomena.example.cz. Protože některé prohlížeče umí
chybějící přesměrování obcházet, zkuste raději nízkoúrovňovou
službu jako Web-Sniffer.
Velká a malá písmena se v URL rozlišují všude kromě schéma a domény. Avšak uživatel je opět nerozlišuje a je tedy nešťastné nabízet rozdílný obsah na adresách lišících se jen velikostí písmen. Jako špatný příklad může posloužit Wikipedie:
- http://en.wikipedia.org/wiki/Acid o kyselinách
- http://en.wikipedia.org/wiki/ACID o databázových transakcích
Kuriózní chybou trpí Bing, který vrací stejné URL, ať už hledáte kyselinu nebo databázi (ačkoliv textový popis je správný). Google nebo Yahoo tímto problémem netrpí.
Bing nerozlišuje mezi kyselinou a databází
Také některé služby (webmaily, ICQ) převádí velká písmenka v URL na malá, což jsou všechno důvody, proč se rozlišování velikosti vyhnout a to nejlépe i v parametrech. Raději dodržujte konvenci, že všechna písmenka v URL budou malá.
Rozlišit některé podobné adresy je oříšek i pro vyhledávače. Udělal jsem experiment a na URL lišící se v detailech jako je přítomnost pravostranného lomítka nebo pořadí parametrů umístil odlišný obsah. Zaindexovat je byl schopen pouze Google. Ostatní vyhledávače dokázaly pojmout vždy jen jednu z variant.
Jen Google tyto stránky umí indexovat jako rozdílné
Pokud jde o pravostranná lomítka, webový server přesměrovává na kanonickou podobu obvykle za vás; přistoupíte-li k adresáři bez pravostranného lomítka, doplní je a přesměruje. Samozřejmě to neplatí, když URI spravujete ve vlastní režii (Cool URI apod.)
A nakonec: skutečně záleží na pořadí parametrů? Mezi adresou
article?a=1&b=2 a article?b=2&a=1 by neměl
být žádný rozdíl. Jsou ale situace, kdy to neplatí, zejména když
předáváme složitější struktury jako třeba pole. Například
?sort[]=name&sort[]=city může být něco jiného, než
?sort[]=city&sort[]=name. Nicméně přesměrovávat, nejsou-li
parametry ve stanoveném pořadí, bych považoval za zbytečnou
hyperkorektnost.
p. s. Nette Framework přesměrování na kanonické URL provádí zcela automaticky ve své režii
Formuláře a HTML5 - co mi ještě chybí
Pracovat s webovým formulářem na straně JavaScriptu se poměrně snadno může stát očistcem. Nebo jak se nazývá ta věc na čištění záchodové mísy. Přitom za všechno může jedno nešťastné rozhodnutí.
Mějme jednoduchý formulář
<form id=myform>
<input type=text name=query>
<input type=submit value="Vyhledat">
</form>
K jeho jednotlivým prvkům přistoupíme přes vlastnost
elements:
var form = document.getElementById('myform');
var query = form.elements.query.value;
// pochopitelně také form.elements['query'].value
A iterovat nad prvky lze cyklem for:
for (var i = 0; i < form.elements.length; i++) {
alert(form.elements[i].value);
}
Z historických důvodů lze vlastnost elements v příkladech
vynechat, neboť jednotlivé prvky se mapují přímo do objektu
form. Takže by fungovalo i form.query.value,
form.length nebo form[i].value. Což se záhy ukáže
jako nemilé. Formulářové prvky totiž přepisují nativní
metody a proměnné objektu form. Například metoda submit(),
která je klíčová pro AJAXové odeslání formuláře, se stane nedostupnou,
pokud formulář obsahuje prvek nazvaný submit. A uznejte, že to
je zrovinka název pro odesílací tlačítko jako dělaný. Pokud by tedy
formulář vypadal takto
<form id=myform>
<input type=text name=query>
<input type=submit name=submit value="Vyhledat">
</form>
nebude jej možné příkazem form.submit() odeslat, místo toho
JavaScript zařve „form.submit is not a function“ a má pravdu,
form.submit není funkce ale objekt HtmlInputElement. Dobrá, dáme
si pozor a nebudeme formulářové prvky nazývat submit.
(prozradím trik, jak by formulář šlo odeslat i v tomto případě:
document.createElement('form').submit.call(form))
Jenže název submit není tím jediným, kterému se musíme
vyhnout. Prvek pojmenovaný elements způsobí, že
form.elements nebude očekávaná kolekce a výše uvedené
příklady skončí chybou. Název length zase znemožní nad
kolekcí iterovat. A tak by se dalo pokračovat, nativních prvků třeba DOM
Firefoxu definuje hodně přes stovku. Pro zajímavost uvádím seznam jen těch
jednoslovných (tj. vynechávám nodeName nebo
innerHTML):
action, attributes, blur, children, dir, draggable, elements, encoding, enctype, focus, id, lang, length, method, name, normalize, prefix, reset, spellcheck, style, submit, target, title
Bylo by skvělé, kdyby se HTML5 dokázalo s tímto nešvarem vypořádat. Zatím jsem ve specifikaci nic takového nenašel.
Podobně mi chybí možnost, jak v obsluze události onsubmit
zjistit, kterým tlačítkem byl formulář odeslán. Triviální a užitečná
věc a jak složitě se musí řešit.
<form id=myform onsubmit="kterým tlačítkem byl odeslán?">
<input type=hidden name=id value="123">
<input type=submit name=save value="Uložit">
<input type=submit name=delete value="Smazat">
</form>
Řeším to tak, že odchytávám událost click jednotlivých
tlačítek a název prvku ukládám do vlastní proměnné formuláře. O něco
jednodušší je využít bublání a odchytávat click přímo na
formuláři. Nicméně v HTML5 tohle už nebude fungovat spolehlivě, protože
prvek může být umístěn i mimo strom formuláře a přiřazen k němu
atributem form. Bylo by tedy fajn, kdyby HTML5 zavedlo vlastnost
například form.submitter, který by vracela název
odesílajícího tlačítka.
p. s. Nette Framework s těmito situacemi počítá a snaží se je v rámci možností řešit za programátora
Jak posílat klientům náhledy webů
Poslyšte příběh: klient si přál učinit svůj web hezčím a tak jsem mu doporučil jednoho z těch mála dobrých tuzemských grafiků. Před pár dny jsme měli schůzku a on se svěřil, že už dostal od grafika návrh a není z něj gór šťastný. Že písmo je moc malé a celé je to jakési kostrbaté. Nějak se mi to nezdálo, poprosil jsem ho, aby návrh otevřel, že se na to podíváme. Dohledal email, odkliknul obrázek a naběhl mu výchozí prohlížeč obrázků ve Windows. A protože obrázek měl větší rozměry, zobrazil se (mírně) zmenšený. A hned bylo jasné, kde je zakopaný pes.
Pokud klient není expert, nemá šanci zjistit, že se dívá na obrázek
zdeformovaný zmenšením. Prohlížeč obrázků ve Windows XP nebo Vista na to
nijak neupozorní. Ba co víc – i kdyby to zaregistroval, nejspíš se mu
nepodaří obrázek zvětšit na plnou velikost. Alespoň kolečkem myši nebo
klávesami + - to nejde. Ty obrázek
zvětšují/zmenšují o 20 % a hranici 100 % bez zastavení přeskočí.
Zobrazit jej v měřítku 1:1 vyžaduje fištróna.
Z příběhu vyplývá velmi cenná a nejspíš překvapivá zkušenost: neposílejte klientům náhledy webů jako obrázek.
Jak tedy náhledy posílat? Nejvhodnější je klientovi poslat URL. Design
tak uvidí v kontextu webového prohlížeče a bude mít daleko ucelenější
dojem. Ale pozor, pokud byste poslali přímo URL obrázku, prohlížeč by jej
opět zmenšil. Je nad ním potřeba vytvořit HTML obálku. Nahrejte proto na
web kromě obrázku ještě soubor nahled.php:
<html>
<head>
<title>Nahled obrazku</title>
</head>
<body style="margin:0">
<img src="<?php echo htmlSpecialChars($_SERVER['QUERY_STRING']) ?>">
</body>
</html>
Potom např. obrázek pala.png bude dostupný pod URL
http://example.com/nahled.php?pala.png. Tu pošlete klientovi a
učiníte přítrž možným nedorozuměním.
Na závěr ještě tři tipy:
- udělejte obrázek dostatečně široký a výsoký, nebo vhodně nastavte pozadí, aby nebylo vidět bílé pozadí prohlížeče
- náhled ukládejte zásadně jako 24bitový PNG
- ponechte v kódu element
img, zobrazením pomocí CSS stylu background zkomplikujete klientovi tisk
Barnes & Noble v JavaScriptu
Na posledním školení jsme narazili na zajímavost HTML, která mě (v tu chvíli nepříjemně) překvapila.
Podívejte se na následující kus kódu. Vyskočí okénko se zprávou
Barnes & Noble nebo Barnes & Noble?
<body>
<h1>Barnes & Noble test</h1>
<script>
alert('Barnes & Noble');
</script>
</body>
Máte tip? Tak si ho ověřte. Zajímavé přitom je, že pokud bychom entitu nepoužili, bude výsledek nevalidní.
Konečně pravda o XHTML a HTML
Nedávno jsem se zúčastnil diskuse, která mi (opět) připomněla, jak silně jsou u nás zakořeněné mýty týkající se rozdílů mezi HTML a XHTML. Kampaň za formáty s písmenem X doprovázely velké emoce a ty obvykle nechodí ruku v ruce s čistou hlavou. Sice nadšení dávno opadlo, ale značná část odborné veřejnosti i autorit dosud věří celé řadě bludů.
Pokusím se tímto článkem ty největší z nich pohřbít. A to následujícím způsobem. Tento článek bude obsahovat pouze a jen fakta. Své názory i vaše komentáře si nechám až na článek druhý.
V následujícím textu pod termínem HTML rozumím verzi HTML 4.01, pod XHTML verzi XHTML 1.0 Second Edition. Pro úplnost dodávám, že HTML je aplikací jazyka SGML, zatímco XHTML je aplikací jazyka XML.
Mýtus: v HTML je povolené křížení značek
Nikoliv. Křížení značek je zakázáno přímo v SGML, důsledkem čehož i v HTML. Tento fakt je zmíněn například v doporučení W3C: „…overlapping is illegal in SGML…“. Všechny tyto značkovací jazyky chápou dokument jakožto stromovou strukturu, a právě proto není možné značky křížit.
Zároveň tak reaguji i na reformulaci mýtu: „Výhodou XHTML je zákaz křížení značek“. Není tomu tak, značky nelze křížit v žádné existující verzi HTML nebo XHTML.
Mýtus: XHTML zakázalo prezentační elementy a zavedlo CSS
Nikoliv. XHTML obsahuje tutéž sortu elementů, jako má HTML 4.01. Je to zmíněno hned v prvním odstavci XHTML specifikace: „Význam elementů a jejich atributů je definován v doporučení W3C pro HTML 4“. Z tohoto pohledu mezi XHTML a HTML žádný rozdíl neexistuje.
Některé elementy a atributy byly zapovězené (deprecated) již v HTML 4.01. Prezentační elementy se tu zapovídají právě ve prospěch CSS, což je také odpověď na druhou část mýtu: příchod kaskádových stylů s XHTML nesouvisí, odehrál se již dříve.
Mýtus: HTML parser musí tipovat konce značek
Nikoliv. V HTML je možné u definované skupiny
elementů volitelně neuvádět koncovou nebo počáteční značku. Jde
o elementy, u kterých vypuštění značky nemůže způsobit
nejasnost. Jako příklad si můžeme vzít koncovou značku u elementu
p. Jelikož norma říká, že se odstavec nemůže nacházet
uvnitř jiného odstavce, je v případě zápisu…
<p>....
<p>....
…jednoznačně dáno, že otevřením druhého odstavce se musí uzavřít
ten první. Uvedení koncové značky je tedy redundantní. Naopak třeba
element div může být zanořený sám v sobě, proto u něj je
počáteční i koncová značka povinná.
Mýtus: zápis atributů v HTML je nejednoznačný
Nikoliv. XHTML vždy vyžaduje uzavírat hodnoty atributů do uvozovek nebo apostrofů. HTML to vyžaduje také, s výjimkou, pokud hodnotu tvoří alfanumerický řetězec. Pro úplnost dodám, že i v těchto případech specifikace doporučuje uvozovky užít.
Tedy v HTML je přípustné zapsat <textarea cols=20
rows=30>, což je formálně stejně jednoznačné, jako
<textarea cols="20" rows="30">. Pokud by hodnota obsahovala
více slov, HTML trvá na užití uvozovek.
Mýtus: HTML dokument je nejednoznačný
Nikoliv. Jako důvod nejednoznačnosti se uvádí buď možnost křížení značek, nejednoznačnost zápisu atributů bez uvozovek, což jsou již vyvrácené mýty, nebo také možnost některé značky vynechávat. Tady zopakuji, že skupina elementů, u kterých je možné značky vynechávat, je zvolena tak, aby se vynechala pouze redundantní informace.
HTML dokument je tedy vždy jednoznačně určen.
Mýtus: až v XHTML se píše znak & entitou &
Nikoliv – musí se tak psát i v HTML. Pro oba jazyky mají znaky
< a & specifický význam. První otevírá
značku a druhý entitu. Aby nebyly chápány v jejich meta-významu, musí se
zapsat entitou. Tedy i v HTML, jak uvádí specifikace.
Mýtus: HTML dovoluje ‚prasárny‘, které Vám v XHTML neprojdou
Nikoliv. Tento názor má kořeny v řadě mýtů, které už jsem vyvrátil
výše. Ještě jsem nezmínil, že XHTML u jmen elementů a atributů na
rozdíl od HTML rozlišuje velikost písmen (je „case sensitive“). Nicméně
jde o zcela legitimní vlastnost jazyka. Takto se liší například Visual
Basic od C# a nelze objektivně říci, že jeden nebo druhý přístup by byl
horší. HTML kód je možné znepřehlednit tím, že budeme nevhodně
střídat velká a malá písmena (<tAbLe>), XHTML kód
zase třeba používáním řetězců XML kód zase třeba používáním
řetězců abc, AbC,
aBC pro odlišné třídyid, ID, Id pro odlišné
atributy.
Čistota zápisu v žádném případě nesouvisí s volbou jednoho nebo druhého jazyka.
Mýtus: Parsování XHTML je mnohem snazší
Nikoliv. Srovnání na miskách vah by bylo subjektivní, a tedy nemá v tomto článku místo, objektivně však lze prohlásit, že není žádný důvod, proč by jeden z parserů měl mít výrazně jednodušší život. Každý z nich má na krku jiný balvan.
Parsování HTML je podmíněno faktem, že parser musí znát definici typu dokumentu. Prvním důvodem je existence volitelných značek. Ačkoliv je jejich doplňování jednoznačné (viz výše) a algoritmicky snadno řešitelné, tak parser musí příslušnou definici znát. Druhým důvodem jsou prázdné elementy. Že je element prázdný ví parser pouze z definice.
Parsování XHTML je zase ztíženo tím, že dokument může (na rozdíl od HTML) obsahovat interní podsadu DTD s definicí vlastních entit (viz příklad). Raději dodávám, že „entita“ nemusí představovat jeden znak, ale libovolně dlouhý úsek XHTML kódu (obsahující případně další entity). Bez zpracování DTD a ověření jeho správnosti vůbec nelze o parsování XHTML hovořit. Věc navíc zkomplikuje to, že syntakticky je DTD v podstatě protipólem jazyka XML.
Shrnuto: jak HTML tak XHTML parser musí znát definici typu dokumentu. XHTML parser ji navíc musí umět číst v DTD jazyce.
Mýtus: Parsování XHTML je mnohem rychlejší
Z hlediska syntaktické podobnosti obou jazyků je rychlost parsování dána pouze šikovností programátorů jednotlivých parserů. Čas potřebný pro strojové zpracování běžné webové stránky (ať už HTML nebo XHTML) na běžném počítači je lidským vnímáním nepostřehnutelný.
Mýtus: HTML parser si musí vždy poradit
Nikoliv. Specifikace HTML nenařizuje, jak se má aplikace zachovat v případě zpracování chybného dokumentu. Z důvodu konkurenceschopnosti v reálném prostředí došlo k tomu, že prohlížeče se staly zcela tolerantní k vadným HTML dokumentům.
Jinak je tomu v případě XHTML. Specifikace odvoláním na XML nařizuje, že parser v případě chyby nesmí pokračovat v dalším zpracování logické struktury dokumentu. Opět z důvodu konkurenceschopnosti v reálném světě došlo k tomu, že RSS čtečky se staly tolerantní k vadným XML dokumentům (RSS je aplikací XML, stejně jako XHTML).
Pokud bychom chtěli z tolerantnosti webových prohlížečů něco negativního usuzovat o HTML, pak nutně musíme z tolerantnosti RSS čteček něco negativního usuzovat o XML. Objektivně lze shrnout, že drakonický přístup XML k chybám v dokumentech je utopistický.
Závěr?
Pokud už nemáte mysl zatíženou žádným z výše uvedených mýtů, můžete mnohem lépe vnímat rozdíl mezi HTML a XHTML. Lépe řečeno můžete lépe vnímat, že tam žádný rozdíl není. Skutečný rozdíl se odehrává až o patro výše: je jím opuštění SGML a přechod k novému XML.
Bohužel nelze říci, že XML pouze řeší problémy SGML a žádné nové nepřidává. Jen v tomto článku jsem na dva narazil. Jedním z nich je drakonické zpracování chyb v XML, které není v souladu s praxí, a tím druhým je existence odlišného jazyka DTD uvnitř XML, které komplikuje parsování i srozumitelnost XML dokumentů. Navíc vyjadřovací schopnost tohoto jazyka je tak malá, že nedokáže formálně postihnout ani samotné XHTML, takže některé vlastnosti je nutné dodefinovat zvlášť. U jazyka, který není svázán historickými okovy, je to smutné a zarážející zjištění. Kritika XML je však téma na samostatný článek.
(Pokud narazím na další mýty, budu článek postupně doplňovat. Budete-li chtít na ně odkazovat, můžete využít toho, že jednotlivé titulky mají vlastní ID)

