Dynamická menu v DHTML – klikací menu 2.

4. února 2002

V minulém dílu jsme začali vytvářet dynamické menu, které se objeví po stisknutí tlačítka myši. Dnes jej dokončíme.

Vytvoření dynamického menu z HTML kódu

V dynamických stylech jsem přiřadil prvku menuHolder mj. vlastnost visibility: hidden. Znamená to, že celé menu bude v době nahrávání stránky neviditelné, protože by mohlo dojít k chybám při manipulaci s nabídkou v době, kdy ještě není celá načtená do prohlížeče. Hned jak menu načtená, je třeba jí pomocí JavaScriptu „zviditelnit“.

Za celý kód doplňte volání JavaScriptové funkce menu(). Pokud v nabídce používáte obrázky, bude lepší volání této funkce umístit do události onload tagu BODY:

<script type=“text/javascript“>
menu();
</script>

Tuto funkci potom definujte v hlavičce stránky, uvnitř tagu SCRIPT (nejlépe hned za přiřazení dynamických stylů):

var timer, i, ns4_menuFunction, justVisibleMenuId = 0, may_hideMenu = true; // několik proměnných, které budete používat
function menu()
{
  if (dhtml)
  {
    if (ns4)
    {
      for (i = 1; i <= 3; i++)
      {
        ns4_menuFunction = eval(‚ns4_moveMenu‘ + i);
        document.menuHolder.document.layers[‚visibleMenu‘ + i].document.captureEvents(Event.MOUSEDOWN);
        document.menuHolder.document.layers[‚visibleMenu‘ + i].document.onmousedown = ns4_menuFunction;
      }
      document.captureEvents(Event.MOUSEDOWN);
      document.onmousedown = hideMenu;
    }
    if (opera) for (i = 1; i <= 3; i++) document.getElementById(‚hiddenMenu‘ + i).style.top = 20;
    if (ie4) for (i = 1; i <= 3; i++) document.all[‚hiddenMenu‘ + i].style.top = 18;
    setVisibility(‚menuHolder‘,’visible‘);
  }
}

Všimněte si, že je kód celé funkce přístupný pouze tehdy, je-li hodnota proměnné dhtml true – takovou podmínku dejte na začátek všech funkcí, které v souvislosti s menu používáte. Ještě před samotným „zviditelněním“ nabídky musíte provést několik úprav podle prohlížeče používaného uživatelem.

Pokud je tímto prohlížečem NS4, musíte registrovat událost onMouseDown pro elementy visibleMenu1, 2 a 3, jinak by k těmto událostem byl NS4 netečný (nerespektuje jejich zápis pomocí parametru onmousedown). Použijte metodu captureEvents, kterou lze využít u jakéhokoli layeru, a jejímiž parametry jsou události, které chcete u layeru registrovat, oddělené znaménkem „|“. Pokud chcete registrovat jen jednu událost, znaménko nepoužívejte.

Událost předávaná této metodě musí být ve speciálním tvaru Event (JMÉNO UDÁLOSTI BEZ POČÁTEČNÍHO „ON“). V dalším kroku dokončíte registraci události pomocí zápisu layer.událost = funkce. Funkci uveďte bez závorek pro předávání parametrů. Jako parametr je jí v NS4 automaticky předáván objekt Event, který můžete použít pro čtení vlastností události. V našem případě asociujte událost onMouseDown s funkcemi ns4_moveMenu1 (u elementu visibleMenu1), ns4_moveMenu2 (u elementu visibleMenu2) a ns4_moveMenu3 (u elementu visibleMenu3). Tyto funkce mají jediný příkaz, a sice zavolání funkce moveMenu() s příslušným parametrem (číslem 1, 2 nebo 3). I v NS4 tedy dosáhnete zavolání stejné funkce se stejným parametrem jako ve všech ostatních prohlížečích (zde jste toho dosáhli pomocí parametru onmousedown u příslušných elementů). Syntaxe funkcí ns4_moveMenuX vypadá následovně:

function ns4_moveMenu1(){moveMenu(1);}
function ns4_moveMenu2(){moveMenu(2);}
function ns4_moveMenu3(){moveMenu(3);}

Navíc ještě přiřazujete funkci hideMenu() události onmousedown nad celým dokumentem. Tuto funkci použijete pro skrytí nabídky v momentě, kdy uživatel klepne myší jinam. Pro ostatní prohlížeče tuto událost přiřadíte pomocí následujícího zápisu uvnitř tagu BODY:

<body onmousedown=“hideMenu();“>

Pokud je prohlížečem Opera nebo IE4, posunujete elementy hiddenMenu o 1, resp. 3 pixely nahoru – je to kvůli chybné interpretaci CSS vlastnosti height v těchto prohlížečích.

Na samém konci funkce menu() se nachází příkaz, který celé menu „zviditelní“. Je realizován voláním funkce setVisibility(), které předáte jméno elementu a stav viditelnosti, který chcete u elementu nastavit. Syntaxe funkce setVisiblity() je následující:

function setVisibility(element,newVisibility)
{
  if (dhtml)
  {
    if (dom) document.getElementById(element).style.visibility = newVisibility;
    else if (ie4) document.all[element].style.visibility = newVisibility;
    else if (ns4) eval(‚document.‘ + element + ‚.visibility = newVisibility‘);
  }
}

Rozhýbání menu

Nyní již máte celé menu úspěšně vytvořeno a můžete se zabývat jeho funkcí – tedy zobrazením dolní nabídky poté, co uživatel klepne na horní nabídku. Proto jsme horním nabídkám přiřadili pro událost onmousedown funkci moveMenu(), které je jako parametr předáváno číslo nabídky, z které je volána (viz minulý článek). Syntaxe funkce moveMenu() je následující:

function moveMenu(id)
{
  if (dhtml)
  {
    if (justVisibleMenuId == 0)
    {
      setVisibility((ns4 ? ‚menuHolder.document.‘ : “) + ‚hiddenMenu‘ + id,’visible‘);
      justVisibleMenuId = id;
    }
    else
    {
      setVisibility((ns4 ? ‚menuHolder.document.‘ : “) + ‚hiddenMenu‘ + justVisibleMenuId,’hidden‘);
      if (justVisibleMenuId != id)
      {
        setVisibility((ns4 ? ‚menuHolder.document.‘ : “) + ‚hiddenMenu‘ + id,’visible‘);
        justVisibleMenuId = id;
      }
      else justVisibleMenuId = 0;
    }
    may_hideMenu = false;
    setTimeout(‚may_hideMenu = true‘,50);
  }
}

Jak vidíte, opět jsme běh celé funkce podmínili tím, aby proměnná dhtml byla true. Pro celou funkci je velmi důležitá proměnná justVisibleMenuId. Ta má vždy hodnotu menu, které je v danou chvíli viditelné. Pokud jsou všechna menu skryta, má justVisibleMenuId hodnotu 0. Na začátku funkce moveMenu() tedy otestujete, zda je nějaké menu viditelné. Pokud není, pak zviditelněte hiddenMenu s id, které jste získali jako argument funkce (pokud je prohlížeč NS4, musíte ještě zohlednit umístění hiddenMenu v elementu menuHolder). Hodnotu proměnné justVisibleMenuId nastavíte právě na toto id. Pokud nějaké z menu viditelné je, pak ho „zneviditelníte“ a testujete, zda se id neshoduje s justVisibleMenuId. Bylo-li klepnuto na již viditelné menu, jen ho skryjete a neskrýváte žádné další menu. Pokud ne, pak zviditelníte novou nabídku. V jiném případě nastavíte proměnnou justVisibleMenuId na 0, protože není právě viditelné žádné z menu.

Poslední dva řádky kódu jsou zde kvůli protékání událostí. Správně by měla událost onMouseDown protékat nahoru až k objektu document. Tím by se ovšem spustila funkce hideMenu(), což nechcete. Potřebujete ji spouštět pouze při stisknutí tlačítka někam vedle menu. Proto běh funkce hideMenu() podmiňujete tím, aby proměnná may_hideMenu měla hodnotu true, což v tomto případě bude mít až za 50 milisekund – v té době už ale událost dávno proteče. Tento problém by šlo řešit i elegantnější cestou, a to pomocí proměnné cancelBubble objektu event (pomocí té je možno protékání zastavit). Přístup k ní je ale v NS6 a Mozille zbytečně zdlouhavý, a proto se mi zdá lepší řešení, které jsem použil.

Když už se bavíme o funkci hideMenu(), rovnou vám ukáži její syntaxi:

function hideMenu(e)
{
  if (dhtml)
  {
    if ((justVisibleMenuId != 0) && (may_hideMenu))
    {
      setVisibility((ns4 ? ‚menuHolder.document.‘ : “) + ‚hiddenMenu‘ + justVisibleMenuId,’hidden‘);
      justVisibleMenuId = 0;
    }
    if (ns4) routeEvent(e);
  }
}

Princip této funkce je jednoduchý – otestovat, zda je viditelné nějaké menu. Pokud ano, pak ho skryje a nastaví proměnnou justVisibleMenuId na 0. To vše musí být podmíněno hodnotou true proměnné may_hideMenu.

Zajímavý je poslední řádek kódu. Používá funkci routeEvent, která je známá pouze v NS4. NS4 totiž používá, narozdíl od ostatních prohlížečů, směr protékání událostí odzdola nahoru – to znamená, že v momentě, kdy klepnete na visibleMenu, zavolá se událost onmousedown objektu document a tím pádem funkce hideMenu(). Proto musíte použít funkci routeEvent(), která předá událost dalšímu elementu. Ten se jí pak snaží zachytit (v našem případě tedy visibleMenu). Pokud žádný takový element není, neudělá funkce nic. Jako parametr této funkce se používá objekt e, který obsahuje informace o události a který je v NS4 automaticky předáván funkcím volaným pomocí ovladačů událostí.

Co jste vlastně vytvořili?

Odpověď je jednoduchá – první dynamické menu. V příštích článcích se budeme zabývat jeho různými modifikacemi, přičemž ale základní princip zůstane stejný. Lze ho shrnout do tří bodů:

  • Celé menu je tvořeno blokem HTML kódu, jehož jednotlivé části jsou pojmenovány a dodatečně formátovány pomocí CSS a JavaScriptu. Díky tomu je menu všeobecně přístupné.
  • Dynamické menu se zobrazí pouze v prohlížečích správně podporujících DHTML, v ostatních prohlížečích se zobrazí dobře strukturovaná navigace s upozorněním.
  • Celé menu je uzavřeno v jednom prvku DIV s relativní pozicí. To umožňuje pozicovat jednotlivé prvky menu absolutně, aniž byste byli závislí na rozlišení uživatele.

Budu rád, pokud v diskusním fóru pod článkem vyjádříte své připomínky, náměty na vylepšení ad., týkající se dynamického menu. Pokud používáte prohlížeč, případně platformu, na které nebylo menu testováno (např. Linux nebo Mac), budu rád, pokud se o své zkušenosti podělíte.

V příštím článku se podíváme na to, jak vytvořit menu, které se objeví při přejetí myší nad nabídkou.

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

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

Mohlo by vás také zajímat

Nejnovější

1 komentář

  1. Tomáš

    Zář 6, 2009 v 12:35

    Dobry den:
    Menu je dobré ale potřeboval bych poradit jak změnit barvu potřeboval bych ho žluté a černý text.
    Díky.

    Odpovědět

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *