Dynamická menu v DHTML – menu s podnabídkami

18. února 2002

Náš seriál o dynamických menu funkčních v nejpoužívanějších prohlížečích se pomalu chýlí ke konci. Dnes se podíváme na to, jak vytvořit menu s podnabídkami.

Dnes budeme opět vycházet z principů vysvětlených v předcházejích dílech seriálu – tedy v prvním, druhém, třetím a čtvrtém. Na začátku se nejdříve podívejte na příklad.

HTML kód tvořící menu

Celé první menu rozdělíte na tři části, které pojmenujete helpMenu1, helpMenu2 a helpMenu3. Každá část bude obsahovat jednu položku menu a ovladačům událostí každé části přiřadíte různé funkce pro zviditelnění/zneviditelnění menu. Dále si vytvoříte podnabídky, které pojmenujete hiddenMenu4 a hiddenMenu5 a budete je absolutně pozicovat. Jak to vypadá si můžete prohlédnout zde (červeně zvýrazněny jsou ovládače událostí):

<div id=“menuHolder“>
<div id=“visibleMenu1″ onmouseover=“showMenu(1,0);“ onmouseout=“hideMenu(1,0);“><div class=“menuItem“>Portály<script type=“text/javascript“>function onMouseOver() {showMenu(1,0);} function onMouseOut() {hideMenu(1,0);}</script><span class=“cssSupport“><br></span></div></div>
<div id=“hiddenMenu1″><div class=“menuItem“><script type=“text/javascript“>if (ns4) document.write(‚<img src=“invisible.gif“ width=80 height=52 border=0 alt=“Nic“>‘);</script><div id=“helpMenu1″ class=“helpMenu“ onmouseover=“dontHideMenu(); hideMenu(4,0);“ onmouseout=“hideMenu(1,0);“><a href=“http://atlas.cz“ class=“menuLink“>Atlas</a><script type=“text/javascript“>function onMouseOver() {dontHideMenu(); hideMenu(4,0);} function onMouseOut() {hideMenu(1,0);}</script></div><div id=“helpMenu2″ class=“helpMenu“ onmouseover=“dontHideMenu(); hideMenu(5,0); showMenu(4,1);“ onmouseout=“hideMenu(4,1);“><a href=“http://centrum.cz“ class=“menuLink“>Centrum &gt;&gt; </a><script type=“text/javascript“>function onMouseOver() {dontHideMenu(); hideMenu(5,0); showMenu(4,1);} function onMouseOut() {hideMenu(4,1);}</script></div><div id=“helpMenu3″ class=“helpMenu“ onmouseover=“dontHideMenu(); hideMenu(4,0); showMenu(5,1);“ onmouseout=“hideMenu(5,1);“><a href=“http://seznam.cz“ class=“menuLink“>Seznam &gt;&gt; </a><script type=“text/javascript“>function onMouseOver() {dontHideMenu(); hideMenu(4,0); showMenu(5,1);} function onMouseOut() {hideMenu(5,1);}</script></div><span class=“cssSupport“><br></span></div></div>
<div id=“hiddenMenu4″ onmouseover=“dontHideMenu();“ onmouseout=“hideMenu(4,1);“><div class=“menuItem“><a href=“http://mail.centrum.cz“ class=“menuLink“>E-mail</a><br><a href=“http://fulltext.centrum.cz“ class=“menuLink“>Fulltext</a><br><a href=“http://zabava.centrum.cz“ class=“menuLink“>Zábava</a><script type=“text/javascript“>function onMouseOver() {dontHideMenu();} function onMouseOut() {hideMenu(4,1);}</script><span class=“cssSupport“><br></span></div></div>
<div id=“hiddenMenu5″ onmouseover=“dontHideMenu();“ onmouseout=“hideMenu(5,1);“><div class=“menuItem“><a href=“http://chata.seznam.cz“ class=“menuLink“>Chata</a><br><a href=“http://penize.seznam.cz“ class=“menuLink“>Peníze</a><script type=“text/javascript“>function onMouseOver() {dontHideMenu();} function onMouseOut() {hideMenu(5,1);}</script><span class=“cssSupport“><br></span></div></div>
<div id=“visibleMenu2″ onmouseover=“showMenu(2,0);“ onmouseout=“hideMenu(2,0);“><div class=“menuItem“>Zpravodajství<script type=“text/javascript“>function onMouseOver() {showMenu(2,0);} function onMouseOut() {hideMenu(2,0);}</script><span class=“cssSupport“><br></span></div></div>
<div id=“hiddenMenu2″ onmouseover=“dontHideMenu();“ onmouseout=“hideMenu(2,0);“><div class=“menuItem“><a href=“http://cnn.com“ class=“menuLink“>CNN</a><br><a href=“http://ceskenoviny.cz“ class=“menuLink“>České Noviny</a><br><a href=“http://idnes.cz“ class=“menuLink“>iDNES</a><br><a href=“http://www.lidovky.cz“ class=“menuLink“>Lidovky</a><script type=“text/javascript“>function onMouseOver() {dontHideMenu();} function onMouseOut() {hideMenu(2,0);}</script><span class=“cssSupport“><br></span></div></div>
<div id=“visibleMenu3″ onmouseover=“showMenu(3,0);“ onmouseout=“hideMenu(3,0);“><div class=“menuItem“>Zábava<script type=“text/javascript“>function onMouseOver() {showMenu(3,0);} function onMouseOut() {hideMenu(3,0);}</script><span class=“cssSupport“><br></span></div></div>
<div id=“hiddenMenu3″ onmouseover=“dontHideMenu();“ onmouseout=“hideMenu(3,0);“><div class=“menuItem“><a href=“http://www.techno.cz“ class=“menuLink“>Czech Techno</a><br><a href=“http://flashfun.cz“ class=“menuLink“>FlashFun</a><br><a href=“http://www.kompost.cz“ class=“menuLink“>Kompost</a><br><a href=“http://novinky.cz“ class=“menuLink“>Novinky</a><script type=“text/javascript“>function onMouseOver() {dontHideMenu();} function onMouseOut() {hideMenu(3,0);}</script><span class=“cssSupport“><br></span></div></div>
</div>

Funkcím showMenu() a hideMenu(), předáváte dva parametry. Obě funkce totiž najednou manipulují se dvěma hiddenMenu (buď zviditelňují nebo zneviditelňují). K přesnému kódu těchto funkcí se ale ještě dostaneme.

Dále je tu opět jeden ústupek NS4. Každý prvek helpMenu v něm musí být absolutně pozicován, aby se stal layerem a mohly na něm být zachycovány události. Kvůli tomu musíte v tomto prohlížeči uměle (pomocí neviditelného obrázku invisible.gif) roztáhnout prvek hiddenMenu1 a na něj pozicovat prvky helpMenu1, 2 a 3.

Přiřazení CSS vlastností

CSS budete opět přiřazovat dynamické a vizuální vlastnosti. Nejprve k těm vizuálním – vytvoříte si novou třídu helpMenu a přiřadíte šířku ještě dalším dvěma prvkům, podnabídkám hiddenMenu4 a hiddenMenu5:

<style type=“text/css“>
.menuItem {font-family: „Helvetica CE“, „Arial CE“, Helvetica, Arial, „sans-serif“; font-size: 13px; color: black; background-color: #dde3eb; border: 1px solid #7f8893; padding: 2px; text-align: center;}
a.menuLink {font-family: „Helvetica CE“, „Arial CE“, Helvetica, Arial, „sans-serif“; font-size: 13px; color: black; text-decoration: none;}
a.menuLink:active {font-family: „Helvetica CE“, „Arial CE“, Helvetica, Arial, „sans-serif“; font-size: 13px; color: black; text-decoration: none;}
a.menuLink:visited {font-family: „Helvetica CE“, „Arial CE“, Helvetica, Arial, „sans-serif“; font-size: 13px; color: #336699; text-decoration: none;}
a.menuLink:hover {font-family: „Helvetica CE“, „Arial CE“, Helvetica, Arial, „sans-serif“; font-size: 13px; color: #cc0000; text-decoration: none;}
.cssSupport {display: none;}
#visibleMenu1 {height: 16px; width: 52px; cursor: default;}
#visibleMenu2 {height: 16px; width: 85px; cursor: default;}
#visibleMenu3 {height: 16px; width: 49px; cursor: default;}
.helpMenu {width: 74px;}
#hiddenMenu1 {width: 80px;}
#hiddenMenu2 {width: 90px;}
#hiddenMenu3 {width: 92px;}
#hiddenMenu4 {width: 62px;}
#hiddenMenu5 {width: 62px;}
</style>

Třidu helpMenu jste vytvořili jenom kvůli větší stručnosti – je přiřazena všem prvkům helpMenu – ty mají logicky všechny stejnou šířku.

Nyní dynamické vlastnosti:

if (dhtml) document.write (‚<style type=“text/css“>#scriptSupport {display: none;} #menuHolder {position: relative; visibility: hidden; z-index: 1;} #hiddenMenu1, #hiddenMenu2, #hiddenMenu3, #hiddenMenu4, #hiddenMenu5 {position: absolute; visibility: hidden;} #visibleMenu1 {position: absolute; left: 0px; top: 0px;} #visibleMenu2 {position: absolute; left: 51px; top: 0px;} #visibleMenu3 {position: absolute; left: 135px; top: 0px;} #hiddenMenu1 {left: 0px; top: 21px;} #hiddenMenu2 {left: 51px; top: 21px;} #hiddenMenu3 {left: 135px; top: 21px;} #hiddenMenu4 {left: 79px; top: 38px;} #hiddenMenu5 {left: 79px; top: 53px;}‘ + (ns4 ? ‚ #hiddenMenu1 {height: 48px;} #helpMenu1 {position: absolute; left: 6px; top: 9px;} #helpMenu2 {position: absolute; left: 6px; top: 24px;} #helpMenu3 {position: absolute; left: 6px; top: 39px;}‘ : “) + ‚</style>‘);

Celý kód je bohatší o pozicování nových prvků – hiddenMenu4 a hiddenMenu5. V případě prohlížeč NS4 je tu navíc pozicování prvků helpMenu1, helpMenu2 a helpMenu3 (viz výše).

Vytvoření menu

Menu vytvoříte, stejně jako v předchozích případech, pomocí funkce menu(). Ta je dnes stejná jako minule:

function menu()
{
  if (dhtml)
  {
    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‘);
  }
}

Znovu použijete také funkci setVisibility():

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

Nejdříve se podívejte na všechny tři funkce, které pohyb dnešního menu zajišťují:

var timer, i, menuId, menuId2;
function showMenu(id,id2)
{
  if (dhtml)
  {
    clearTimeout(timer);
    for (i = 1; i <= 5; i++) if ((i != id) && (i != id2)) setVisibility((ns4 ? ‚menuHolder.document.‘ : “) + ‚hiddenMenu‘ + i,’hidden‘); //všechna nepotřebná menu skryjeme
    setVisibility((ns4 ? ‚menuHolder.document.‘ : “) + ‚hiddenMenu‘ + id,’visible‘);
    if (id2 != 0) setVisibility((ns4 ? ‚menuHolder.document.‘ : “) + ‚hiddenMenu‘ + id2,’visible‘);
  }
}
function hideMenu(id,id2)
{
  if (dhtml)
  {
    if ((id >= 4) && (id2 == 0)) setVisibility((ns4 ? ‚menuHolder.document.‘ : “) + ‚hiddenMenu‘ + id,’hidden‘); //pokud máme zneviditelnit jen podmenu, uděláme to bez časovače
    else
    {
      menuId = (ns4 ? ‚menuHolder.document.‘ : “) + ‚hiddenMenu‘ + id;
      if (id2 != 0)
      {
        menuId2 = (ns4 ? ‚menuHolder.document.‘ : “) + ‚hiddenMenu‘ + id2;
        timer = setTimeout(„setVisibility(menuId,’hidden‘); setVisibility(menuId2,’hidden‘)“,(ns4 ? 150 : 50)); //v NS4 je kvůli špatné interpretaci CSS třeba použít delší čas
      }
      else timer = setTimeout(„setVisibility(menuId,’hidden‘)“,(ns4 ? 150 : 50));
    }
  }
}
function dontHideMenu()
{
  if (dhtml) clearTimeout(timer);
}

Všimněte si, že jste funkce showMenu() a hideMenu() upravili tak, aby najednou určovali viditelnost dvou menu. Pokud je ale druhý parametr funkce 0, pracují jenom s jedním menu – tuto možnost také hojně využíváte (hlavně u druhých dvou menu, která žádné podnabídky nepoužívají). Celá tato taškařice je nutná kvůli tomu, že prohlížeče (alespoň ty, s kterými jsem pracoval já) mají vcelku dost problémů s používáním dvou časovačů najednou.

Vždy, když kurzor myši opustí jeden z prvků helpMenu, spustíte funkci hideMenu(), která má skrýt celé první menu a případně i podmenu – ta nastaví časovač na 50 milisekund, po kterých se obě nabídky skryjí. Pokud ale uživatel ihned najede kurzorem nad další položku nabídky (další prvek helpMenu), stopne se časovač, případně se navíc objeví podnabídka. Na tomto jednoduchém principu je postavena cela první nabídka, ostatní dvě pracují stejně jako u minulého menu.

K pochopení těchto funkcí je třeba podívat se, jakými událostmi a u jakých prvků jsou volány (viz výše). Pokud i tak budete mít problémy, můžete se zeptat v diskusi pod článkem. Ta je otevřena i vašim námětům, rozšířením menu, a vůbec čemukoli, co se této problematiky týká.

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. Velkej ale mega big programator

    Říj 29, 2010 v 12:42

    Zapoměl ukončit test

    Odpovědět

Napsat komentář: Velkej ale mega big programator Zrušit odpověď na komentář

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