Kód menu, připomínajícího nabídku Průzkumníka ve Windows, je velmi jednoduchý. Uplatníte ho především pro prezentaci dat, u nichž chcete zdůraznit určitou logickou strukturu, a která jsou třeba většího rozsahu (například seznam kapitol a podkapitol knížky, podrobná navigace, mapa stránek ad.).

Dnešním článkem budeme volně navazovat na seriál o dynamickým menu v DHTML, který nedávno na Intervalu vycházel. Doporučuji vám proto přečíst si alespoň jeho první díl, kde byly popsány základní principy, kterých se zde budeme držet.

Výsledek našeho dnešního snažení si můžete prohlédnout zde.

Celé menu vytvoříte tak, že na stránce řádek po řádku definujete potřebné obrázky a text, jako kdyby všechny větve měly být otevřené. Poté jim pomocí CSS přiřadíte vizuální vlastnosti, aby všechny řádky opravdu vypadaly jako menu z Průzkumníka ve Windows. Vytvoří se tak celý strom, který ale bude statický – nebude možné jednotlivé větve zavírat.

V dalším kroku uzavřete části menu, které se mají otevírat a zavírat, do tagů div s identifikátorem id. Současně přiřadíte obrázkům, pomocí kterých se mají jednotlivé větve otevírat a zavírat, příslušné JavaScriptové funkce.

Vytvoření stromu menu

Celý strom menu vytvoříte nadefinováním po jednotlivých řádcích. Poté jednotlivé části, které se mají zavírat a otevírat, uzavřete do tagů div s id menu1, menu2 atd. Nakonec přiřadíte obrázkům, které mají zajišťovat otevírání/zavírání jednotlivých menu, ovladače událostí onclick a onmouseover. V našem případě to tedy bude vypadat takhle (pro stručnost uvádím pouze kód hlavičky a první větve „Portály“):

<div id=“menuHolder“>
<img src=“disc.gif“ width=“19″ height=“16″ alt=“-„> Navigace<br>
<img src=“minus-cross.gif“ width=“19″ height=“16″ id=“marker1″ alt=““ onmouseover=“this.style.cursor = ‚hand‘;“ onclick=“menuClick(1,false);“><img src=“folder-open.gif“ width=“19″ height=“16″ id=“folder1″ alt=“-„> Portály<br>
<div id=“menu1″><img src=“line.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><img src=“line-cross.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><a href=“http://atlas.cz“><img src=“page.gif“ width=“19″ height=“16″ alt=“-„>Atlas</a><br>
<img src=“line.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><img src=“minus-cross.gif“ width=“19″ height=“16″ id=“marker2″ alt=““ onmouseover=“this.style.cursor = ‚hand‘;“ onclick=“menuClick(2,false);“><a href=“http://centrum.cz“><img src=“folder-open.gif“ width=“19″ height=“16″ id=“folder2″ alt=“-„>Centrum</a><br>
<div id=“menu2″><img src=“line.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><img src=“line.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><img src=“line-cross.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><a href=“http://mail.centrum.cz“><img src=“page.gif“ width=“19″ height=“16″ alt=“-„>E-mail</a><br>
<img src=“line.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><img src=“line.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><img src=“line-cross.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><a href=“http://fulltext.centrum.cz“><img src=“page.gif“ width=“19″ height=“16″ alt=“-„>Fulltext</a><br>
<img src=“line.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><img src=“line.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><img src=“line-corner.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><a href=“http://zabava.centrum.cz“><img src=“page.gif“ width=“19″ height=“16″ alt=“-„>Zábava</a></div>
<img src=“line.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><img src=“line-corner.gif“ width=“19″ height=“16″ alt=“ &nbsp; „><a href=“http://seznam.cz“><img src=“page.gif“ width=“19″ height=“16″ alt=“-„>Seznam</a></div>
...

Všimněte si, že jsem celý strom menu uzavřel do tagu div s identifikátorem menuHolder. Jednak je to lepší z hlediska logické struktury dokumentu a jednak se díky tomu dají snadno definovat CSS vlastnosti menu.

Také jste jistě zaregistrovali, že jsme obrázkům, které se při otevírání/zavírání menu mění, přiřadili pomocí parametru id jména. Ta budeme využívat k přistupování k nim v JavaScriptu.

Přiřazení CSS vlastností

Nyní přiřadíte stromu nabídky takové vizuální vlastnosti, aby se opravdu podobal tomu z Průzkumníka. Dosáhnete toho pomocí CSS:

<style type=“text/css“>
body {color: black; background-color: #c4dce1;}
#menuHolder {font: 11px/100% „Helvetica CE“, „Arial CE“, Helvetica, Arial;}
#menuHolder a {text-decoration: none; color: black;}
#menuHolder img {border: 0; vertical-align: middle;}
</style>

Díky tomuto zápisu již získá nabídka potřebný vzhled v IE 5+, Mozille, Opeře 4+ a v Netscape 6. Bohužel ale ne v IE 4, protože tento prohlížeč nezná hodnotu middle vlastnosti vertical-align. Kvůli tomuto prohlížeči budete muset přidat řádek v JavaScriptu, který ho detekuje a v případě potřeby přepíše vlastnost vertical-align u obrázků menu na text-top, kterou IE 4 zná, a která v něm má v tomto případě stejné účinky jako hodnota middle. Syntaxi řádku si ukážeme za chvíli.

Podpora prohlížečů

Do této chvíle jste vytvořili strom, který je statický a není problémem pro žádný prohlížeč. Nyní budete v JavaScriptu detekovat podporu potřebných vlastností k chodu menu v prohlížeči. Pokud je prohlížeč zná, vytvoříte v něm aktivní menu, pokud je nezná nebo JavaScript nepodporuje, zůstane v něm pouze kompletně otevřený strom menu. Ze známých prohlížečů se menu vytvoří v IE 4+, Mozille a Netscape 6. V Opeře je i v nejnovější šesté verzi podpora DOMu (a JavaScriptu vůbec) poměrně chabá, proto se v tomto prohlížeči menu nevytvoří.

Detekce dynamických vlastností prohlížeče

Nejprve provedeme slíbenou detekci podpory dynamických vlastností v prohlížeči:

<script type=“text/javascript“>
if (document.all) document.getElementById = document.all;
var dhtml = (document.getElementById || document.all) && navigator.userAgent.indexOf(‚Opera‘) == -1 ? true : false;
var i, displayed = new Array(“,true,true,true,true);

Pro přístup k elementům menu budete využívat standardní metodu getElementById. Musíte ale zároveň brát ohled na IE 4, který zná pouze zápis pomocí document.all. Tento rozpor řeší druhý řádek kódu. Na třetím potom vytváříte proměnnou dhtml. Pokud má hodnotu true, vytvoří se v prohlížeči aktivní menu. Metodu getElementById zná i Opera. Neumí ale modifikovat CSS vlastnost display v JavaScriptu, proto musíte zajistit, aby v ní proměnná dhtml neměla hodnotu true.

Na posledním řádku kódu jste již definovali dvě proměnné, které budete ve skriptu používat:
i nalezne svoje využití v cyklech for,
displayed bude vždy udávat, jestli je příslušná větev (celkem jsou čtyři) otevřená (true) nebo zavřená (false).

Přednahrání obrázků

Pokud prohazujete v JavaScriptu obrázky na základě akcí uživatele, bývá dobrým zvykem tyto obrázky přednahrát, aby se nemusely nahrávat až v momentě, kdy jsou potřeba a celý efekt se tak nezdržel. Uděláte to tak, že si pomocí metody DOMu createElement vytvoříte několik tagů img, které ale nezabudujete do stránky. Těmto obrázkům poté přiřadíte zdrojové soubory, které budete potřebovat. Díky tomu se obrázky nahrají do paměti prohlížeče, ale uživatel si ničeho nevšimne:

if (dhtml)
{
  var folder_closed = document.createElement(‚img‘);
  folder_closed.setAttribute(‚src‘,’folder-closed.gif‘);
  var plus_cross = document.createElement(‚img‘);
  plus_cross.setAttribute(‚src‘,’plus-cross.gif‘);
  var plus_corner = document.createElement(‚img‘);
  plus_corner.setAttribute(‚src‘,’plus-corner.gif‘);
  var folder_open = document.createElement(‚img‘);
  folder_open.setAttribute(‚src‘,’folder-open.gif‘);
  var minus_cross = document.createElement(‚img‘);
  minus_cross.setAttribute(‚src‘,’minus-cross.gif‘);
  var minus_corner = document.createElement(‚img‘);
  minus_corner.setAttribute(‚src‘,’minus-corner.gif‘);
  document.write(‚<style type=“text/css“>#menuHolder{visibility: hidden;}‘ + (document.all && (!document.getElementById || !document.getElementsByTagName) ? ‚#menuHolder img {vertical-align: text-top;}‘ : “) + ‚</style>‘);
}

Běh celého kódu je podmíněn hodnotou true proměnné dhtml. Na předposledním řádku navíc celé menu skryjete (odkryjete ho, až se celé nahraje). Navíc zde změníte CSS vlastnost vertical-align tagů img, pokud je prohlížeč IE 4 (jak jsme o tom mluvili výše).

Odkrytí menu

Nyní se přeneseme trochu dál do chvíle, kdy je již menu nahráno. Je třeba udělat dvě věci: zavřít všechny větve menu a celé menu odkrýt. O vše se postará funkce loadMenu():

function loadMenu()
{
  for (i = 1; i <= 4; i++) menuClick(i,i == 4 ? true : false);
  document.getElementById(‚menuHolder‘).style.visibility = ‚visible‘;
}

Jak vidíte, o zavírání a otevírání jednotlivých větví menu se stará funkce menuClick(), které jako parametr předáváte pořadové číslo větve a údaj, zda je větev poslední v pořadí. V takovém případě je třeba dosadit rohové obrázky (v našem příkladě se taková větev vyskytuje jen jedna, ale v praxi pravděpodobně budete pracovat s více takovými).

Nyní, když máte potřebnou funkci definovanou, je potřeba ji spustit. Nejlepší je umístit její volání hned za celý strom:

<div id=“menuHolder“>

</div>
<script type=“text/javascript“>
if (dhtml) loadMenu();
</script>

Funkce menuClick()

Nyní si již konečně představíme funkci menuClick(), která zajišťuje otevírání/zavírání jednotlivých větví menu a s ním spojené změny obrázků:

function menuClick(id,last)
{
  if (dhtml)
  {
    document.getElementById(‚menu‘ + id).style.display = (displayed[id] ? ‚none‘ : ‚block‘);
    if (!last) document.getElementById(‚marker‘ + id).setAttribute(‚src‘,displayed[id] ? plus_cross.getAttribute(‚src‘) : minus_cross.getAttribute(‚src‘));
    else document.getElementById(‚marker‘ + id).setAttribute(‚src‘,displayed[id] ? plus_corner.getAttribute(‚src‘) : minus_corner.getAttribute(‚src‘));
    document.getElementById(‚folder‘ + id).setAttribute(‚src‘,displayed[id] ? folder_closed.getAttribute(‚src‘) : folder_open.getAttribute(‚src‘));
    displayed[id] = (displayed[id] == true ? false : true);
  }
}

K otevírání/zavírání menu využijete CSS vlastnost display a výměnu obrázků zajistíte pomocí metody setAttribute(jméno atributu,nová hodnota atributu). Jako hodnotu zde předáváte atribut src přednahraných obrázků (to získáte pomocí metody getAttribute(jméno atributu)). V posledním řádku funkce potom přehazujete hodnotu proměnné displayed tak, aby v ní byl opět zachycen aktuální stav dané větve.

Celý příklad i s obrázky si potom můžete stáhnout zde.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět