Vlastné roletové menu na web stránke

24. května 2001

Pri pozeraní webových stránok ste sa už asi stretli s nejakým, viac, či menej podareným roletovým menu. Ja osobne som už dlho chcel niečo podobné spraviť a keďže sa mi výsledok pozdával, rozhodol som sa podeliť o neho s vami v tomto článku.

Inšpiroval ma k tomu článok Vylepšená kontextová nápověda pomocí JavaScriptu tu na Intervale, môj výtvor teda čerpá z neho, resp. je to ďalšie využitie princípu spomínaného v článku. Nedovolím si tvrdiť, že je to jediné, alebo najoptimálnejšie riešenie menu. Naopak, jedným z dôvodov napísania tohoto článku sú aj vaše nápady pre jeho vylepšenie, či zjednodušenie.

Čo budeme k tomu potrebovať? Stačí nám štipka JavaScriptu, HTML a kaskádových štýlov (CSS) a samozrejme ich základné znalosti. Pre začiatok je tu odkaz na to, čo vlastne chceme dosiahnuť. V ukážke je zahrnuté aj prípadné využitie zvláštnych efektov (filtrov), ktoré ale podporuje iba Internet Explorer od verzie 4.0 a viac, preto každé sub-menu vyzerá trochu inakšie. Chcem ešte upozorniť, že ukážka je robená iba pre Internet Explorer 4.0+, ale ďalej uvádzam úpravy potrebné pre Netscape Navigator. Bohužiaľ, dosiahnutia rovnakého výsledku, hlavne, čo sa týka grafickej úpravy, je v Netscape Navigatore ťažko dosiahnuteľné, alebo aj nemožné.

Samotný kód príkladu, resp. jeho syntax, sa skladá z dvoch častí. Jednou z nich sú funkcie v JavaScripte, ktoré riadia správanie sa menu a druhou je potom „obyčajné“ HTML, pomocou ktorého je vytvorené a zobrazované vlastné menu, teda si tým môžete zvoliť ľubovoľný design samotného menu.

Začneme zobrazením menu a podľa potreby budem popisovať funkcie JavaScriptu. Celý princíp spočíva vo využívaní vlastnosti VISIBILITY, ktorá zapína a vypína zobrazenie nejakého objektu/elementu. V tomto prípade je tým objektom obyčajná tabuľka, ktorou je vytvárané dané sub-menu. Na začiatku sa jednotlivé tabuľky „vykreslia“, ale vlastnosť VISIBILITY majú nastavenú na HIDDEN, čiže budú skryté a neskôr, pomocou JavaScriptu, ich budeme vo vhodnej dobe „ukazovať“ a zase skrývať.

Počet tabuliek sa rovná počtu sub-menu, plus jedna tabuľka na vytvorenie prvého riadku. Ešte uvediem, že je potrebné všetkým tabuľkám dôkladne uviesť ich veľkosť a umiestnenie na stránke, aby sa toto nemenilo pri zmene veľkosti okna prehliadača, resp. ostávalo rovnaké.

Nebudem uvádzať celý zdrojový kód ukážky, ale iba jeho časti potrebné na jeho pochopenie. Celý zdrojový kód môžete získať kliknutím na ukážku a jeho zobrazením, prípadne uložením.

Ešte pred tým by som rád uviedol definíciu pár použitých kaskádových štýlov. Tie sú potrebné jedine kvôli designu menu a stránky.

<style&gt
BODY {background-color: orange; color: white;}
.menu {text-decoration: none;}
A.menu:link {text-decoration: none; color: darkblue;}
A.menu:visited {color: darkblue;}
A.menu:hover {color: white;}
</style&gt
  • <BODY> – nastaví farbu podkladu stránky a textu,
  • .menu – trieda menu, která bude mať text nepodčiarknutý. Položka v sub-menu je vlastne odkaz a nechcem, aby bol podčiarknutý, resp. každá položka menu je triedy menu. Tu som si pomohol klasickými úpravami vlastnosti odkazu (funguje iba v Internet Exploreri4.0+, Netscape Navigator6, mozile a možno aj Opere),
  • A.menu:link/visited/hover – nastaví vlastnosti odkazu podľa jeho stavu (nenavštívený/už navštívený/kurzor je nad odkazom)

Ďalej teda pokračujeme zápisom prvého riadku menu, resp. jeho vytvorením:

<table width=“400px“ border=“0″ style=“background-color: darkblue; color: darkblue;“&gt
<tr&gt
   <td id=“Nmenu1″ width=“80px“ align=“center“ style=“background-color: white;“ OnMouseOver=“Hide();MenuSel(1);Show(1);“&gtMenu 1</td&gt
   <td id=“Nmenu2″ width=“80px“ align=“center“ style=“background-color: white;“ OnMouseOver=“Hide();MenuSel(2);Show(2);“&gtMenu 2</td&gt
   <td id=“Nmenu3″ width=“80px“ align=“center“ style=“background-color: white;“ OnMouseOver=“Hide();MenuSel(3);Show(3);“&gtMenu 3</td&gt
   <td id=“Nmenu4″ width=“80px“ align=“center“ style=“background-color: white;“ OnMouseOver=“Hide();MenuSel(4);Show(4);“&gtMenu 4</td&gt
   <td id=“Nmenu5″ width=“80px“ align=“center“ style=“background-color: white;“ OnMouseOver=“Hide();MenuSel(5);Show(5);“&gtMenu 5</td&gt
</tr&gt </table&gt

Pomocou CSS je v tágu table definovaná farba podkladu a farba písma. Farby sú preto rovnaké, aby som dosiahol modrý rámček okolo každej bunky. Všimnete, že potom v každej bunke (každom tágu td) je definovaná pomocou CSS biela farba podkladu (background-color) – čím dostanem modrý text na bielom podklade, modro orámovaný. Šírku rámčeku môžeme ovplyvniť parametrom cellspacing. Ak parameter nie je uvedený, tak štandardne je šírka 2 pixle (Internet Explorer), čo je náš prípad. Na to aby nám to celé fungovalo treba každej bunke priradiť unikátne ID, aby sme potom pomocou JavaScriptu mohli ľahko určovať objekt, ktorému budeme meniť parameter. Najdôležitejšie z hľadiska funkčnosti je postupnosť volania JavaScriptových funkcií Hide(), MenuSel(CisloNadpisuMenu) a Show(CisloNadpisuMenu), ktoré sa vykonajú vtedy, ak na bunku ukážeme kurzorom, čo nám zabezpečuje udalosť OnMouseOver.

Pred tým, ako presne popíšem jednotlivé funkcie, uvediem ešte príklad zobrazenia tabuľky s prvým menu a potom popíšem dané funkcie. Tabuľky pre ostatné menu sú identické, líšia sa iba súradnicami umiestnenia tak, aby korešpondovali s daným nadpisom prvého riadku menu. Líšia sa ešte v použití filtrov na dosiahnutie niektorých efektov – o nich napíšem na konci článku, lebo nemajú súvislosť s fungovaním menu ako celku.

Tabuľka prvého menu:

<span id=“menu1″ style=“position: absolute; left: 10px;top: 40px; visibility: hidden;“&gt
<table width=“150px“ border=“0″ style=“background-color: white; color: darkblue; border-color: darkblue; border-style: solid; border-width: 2px;“&gt
<tr&gt<td id=“polozka11″ onmouseover=“TabSel(11)“ onmouseout=“TabUnSel(11)“&gt <a href=“kuk.html“ class=“menu“&gtPolozka menu cislo 1.1</a&gt</td&gt<tr&gt
<tr&gt<td id=“polozka12″ onmouseover=“TabSel(12)“ onmouseout=“TabUnSel(12)“&gt <a href=“kuk.html“ class=“menu“&gtPolozka 1.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td&gt<tr&gt
<tr&gt<td id=“polozka13″ onmouseover=“TabSel(13)“ onmouseout=“TabUnSel(13)“&gt <a href=“kuk.html“ class=“menu“&gtPolozka 1.3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td&gt<tr&gt
</table&gt
</span&gt

Tak ako v prípade prvého riadku menu, aj toto je „obyčajná“ tabuľka. Každý riadok tabuľky je vlastne jedna položka. Je tu ale aj niekoľko odlišností. Celá tabuľka je ohraničená tágom span, ktorý nastavuje, pre nás kľúčové vlastnosti, tabuľky. Sem patrí najmä nastavenie umiestnenia tabuľky. V podstate môže byť ľubovoľné, ale ak chceme aby to vyzeralo ako menu, tak tabuľku musíme umiestniť presne na začiatok tabuľky s prvým riadkom menu a zároveň presne pod neho. V tágu table nastavíme parametre šírky tabuľky a pomocou CSS nastavíme farbu podkladu tabuľky na bielu, textu na modrú, nastavíme ohraničenie tabuľky na plnú čiaru (border-style), šírku ohraničenia na 2 pixle (border-width) a farbu ohraničenia na modrú (border-color). Ďalej treba nastaviť najdôležitejšiu vlastnosť – VISIBILITY – na HIDDEN, aby sa nám pri prvom načítaní stránky tabuľka nezobrazila. Tak ako aj minule, nezaobídeme sa bez nastavenia ID (aby sme rozoznávali jednotlivé sub-menu – teraz stačí rozoznávať celé tabuľky; každá tabuľka submenu bude mať iné ID). Na každom riadku tabuľky v tágu td je definované pomocou udalostí, čo sa má urobiť ak naň (riadok) ukážeme myšou (OnMouseOver – zavolá sa funkcia TabSel(CisloPolozky)), a ak odídeme z daného riadku (OnMouseOut – zavolá sa funkcia TabUnSel(CisloPolozky)).

Tak to je z hľadiska funkčnosti skoro všetko. Ešte chcem upozorniť – treba mať v JavaScripte definovanú jednu globálnu premennú – PocetMenu – ktorá má hodnotu počtu menu – v našom prípade 5.

No a teraz snáď konečne vysvetlím ako to funguje a popri tom aj uvediem toľko sľubované funkcie v JaveScripte :).

Takže, po načítaní stránky sa zobrazí iba prvý riadok menu a text. Načítajú sa aj tabuľky vytvárajúce menu, ale tie sa nezobrazia, lebo majú nastavenú vlastnosť VISIBILITY na HIDDEN. Keď sa ukáže kurzorom myši na bunku v menu, tak potom sa vďaka udalosti OnMouseOver vykonajú po sebe tri funkcie: Hide(), MenuSel(CisloNadpisuMenu) a Show(CisloNadpisuMenu);

Funkcia Hide:

function Hide()
{
    var menu, i;
    MenuUnSel();
    for(i=1; i<=PocetMenu; i++)
    {
        menu=eval(„document.all.menu“+i);
        menu.style.visibility=“hidden“;
    }
}

Slúži na uzavretie všetkých menu (ak je nejaké otvorené), t.j. nastaví všetkým tabuľkám sub-menu vlastnosť VISIBILITY na HIDDEN. Kód v tele cyklu zabezpečuje nastavenie vlastnosti VISIBILITY pre tabuľky sub-menu, ktorá každá z nich má, ak si ešte spomínate, vlastné ID – menu1, menu2, … menu5. Týmto ID sa vlastne odkazujeme na príslušnú tabuľku a toto meno (ID) je v premennej menu vo funkcii Hide(). Musím podotknúť, že uvedený kód bude fungovať len pre Internet Explorer 4.0+. Ak chceme tento kód prispôsobiť aj Netscape Navigatoru, treba ho upraviť takto:

menu = eval(„document.menu“+i); menu.visibility=“hidden“;

Ak chceme aby nám kód automaticky rozlišoval, či sa jedná o Internet Explorer alebo Netscape Navigator, treba telo cyklu upraviť takto (ďalej už nebudem uvádzať verziu pre Netscape Navigator, lebo je to analogické a každý si môže daný kód upraviť podľa potreby):

for(i=1; i<=PocetMenu; i++)
{
    if(document.all)
    {
        menu=eval(„document.all.menu“+i);
        menu.style.visibility=“hidden“;
    }
    if(document.layer)
    {
        menu = eval(„document.menu“+i);
        menu.visibility=“hidden“;
    }
}

Pred cyklom sa ale vykoná ešte funkcia MenuUnsel():

function MenuUnSel()
{
    var i, menu;
    for(i=1; i<=PocetMenu; i++)
    {
        menu=eval(„document.all.Nmenu“+i)
        menu.style.backgroundColor=“white“;
        menu.style.color=“darkblue“;
    }
}

Funkcia ruší inverzné farebné zobrazenie všetkých buniek prvého riadku menu. To je zase potrebné v prípade, že prechádzame z menu do menu. Inverzné zobrazenie vlastne „vysvecuje“ danú bunku prvého riadku menu, ak je otvorené. V cykle sa prejdú všetky bunky prvého riadku menu a zmení sa im farba podkladu a textu na pôvodnú. Ďalšou funkciou po Hide() volanou pri udalosti OnMouseOver nad prvým riadkom menu, je funkcia MenuSel(cislopolozky):

function MenuSel(cispol)
{
    var i, menu;
    menu=eval(„document.all.Nmenu“+cispol);
    menu.style.backgroundColor=“darkblue“;
    menu.style.color=“white“;
}

Je to vlastne opak funkcie MenuUnsel(), čiže zobrazí farebne inverzne tú bunku, na ktorej akurát máme kuzor myši, čo nám zaručuje parameter cispol. No a poslednou z trojice volaných funkcií je funkcia Show(cislomenu):

function Show(CisMenu)
{
    var menu=eval(„document.all.menu“+CisMenu);
    menu.style.visibility=“visible“;
}

Jej úlohou je iba zobraziť tabuľku prislúchajúcu danému menu (CisMenu). Princíp je ten istý ako je telo cyklu vo funkcii Hide(), tak isto aj prispôsobenie pre Netscape Navigator, či oba prehliadače naraz. No, teraz máme už otvorené jedno menu (submenu) a ostáva nám iba jediné – prechádzanie po jednotlivých položkách submenu. Ono by stačilo vlastne už iba nechať prehliadač aby sám zvýraznil odkazy nachádzajúce sa v tabuľke (submenu), ale sami uznáte, že to by nebolo pekné. Preto sú tu ešte dve funkcie, ktoré zabezpečia, aby sa prechádzanie po položkách podobalo skutočnému menu, napr. vo Windowse a podobne.

Princíp práce je úplne rovnaký ako pri zobrazovaní, resp. vysvecovaní buniek tabuľky prvého riadku menu. Teda meníme farbu podkladu textu a farbu textu v závislosti na tom, či sa na danej položke nachádza kurzor myši, alebo nie, teda pomocou udalostí OnMouseOver, a OnMouseOut. Pri udalosti OnMouseOver sa volá funkcia TabSel(cislopolozky),

function TabSel(cispol)
{
    var pol=eval(„document.all.polozka“+cispol);
    pol.style.backgroundColor=“darkblue“;
    pol.style.color=“white“;
}

ktorá zmení farby danej položky (pomocou cispol). Číslo položky je ľubovoľné, ale malo by byť zhodné s číslom v reťazci ID danej položky, definovanej v tabuľke daného submenu. No a pri opustení položky myšou sa volá funkcia TabUnsel(cislopolozky),

function TabUnSel(cispol)
{
    var pol=eval(„document.all.polozka“+cispol);
    pol.style.backgroundColor=“white“;
    pol.style.color=“darkblue“;
}

ktorá robí úplne to isté, čo TabSel, akurát mení farby v opačnom garde.
Ešte sa zmienim o toľkých znakoch &nbsp;. Tie sú tam jedine z toho dôvodu, aby sa aj prázdne miesto medzi názvom položky a pravou stranou tabuľky (viď hotové menu napr. položka 1.2, 1.3, 3.3…) rátalo ako odkaz, teda aby sme kliknutím na ľubovoľnú časť riadku klikli ako na odkaz.

Takže celé menu je už hotové až na jeden detail. Treba zabezpečiť aby sa menu „samočinne“ zavrelo, hneď ako z neho odídeme myšou. Tu som narazil na problém, ktorý sa mi podarilo vyriešiť, ale možno niekoho z Vás napadne lepšie a hlavne účinnejšie riešenie – dopredu ďakujem. Zavretie menu som vyriešil tak, že všetok ostatný text, tabuľky, obrázky atď. som uzavrel do tágu span, pre ktorý som nastavil, že pri nastavení kurzoru myši nad túto oblasť (udalosť OnMouseOver), sa zavolá funkcia Hide(), ktorá, ako už určite viete, spôsobí zavretie celého menu.

<span onmouseover=“Hide()“&gt
text text, obrázky, odstavce…
<p&gt…
<br&gt…

<img src…

<table&gt….</table&gt

</span&gt

Avšak na stránke ešte stále ostanú miesta, na ktoré keď sa dostaneme myšou, tak sa menu neuzavrie. Aby som to odstránil, tak tág body reaguje na udalosť kliknutia myšou (OnClick) tak, že tiež zavolá funkciu Hide(). To znamená, že ak na ľubovoľnom mieste na stránke kliknem myšou (okrem menu), tak sa menu zavrie.

Ešte uvediem sľúbené ukážky filtrov, ktoré som použil pri jednotlivých submenu. Tieto filtre sa dajú použiť pre skoro ľubovoľný element (tabuľka, obrázok, …). Jedinou podmienkou úspešného použitia je okrem Internet Exploreru 4.0+ aj presné stanovenie veľkosti oblasti použiteľnosti filtra. Nestačí iba uviesť veľkosť napr. tabuľky, ale ak chcem pre ňu použiť aj filter, tak veľkosť treba definovať znova. Filter sa definuje parametrami v tágu span a daný element (tabuľka…) sa musí nachádzať samozrejme v tom tágu. Príklad som urobil tak, že každé submenu ukazuje použitie iného filtra, prípadne ich kombináciu. Jedine prvé submenu som nechal bez použitia filtrov. V ukážke neuvádzam všetky filtre, o tých sa môžete dozvedieť na stránkach Intervalu. Odporúčam pozrieť, lebo jednotlivé filtre obsahujú značný počet parametrov, ale to by bol už námet na iný článok.

V príkladoch budem uvádzať iba prvý riadok s tágom span, v ktorom sú filtre definované. V tom tágu span je potom uzavretá tabuľka daného submenu. Celá tabuľka prvého submenu je uvedená pri príklade ako urobiť prvé submenu. Ostatné tabuľky sú tvorené analogicky, jediný rozdiel je v tágu span, ktorý je prispôsobený pre daný filter.

Submenu 2 používa filter – DropShadow – ktorý vytvára tieň (šírka a výška sa týka filtra! – nie tabuľky – tá ju má definovanú v tágu table)

<span id=“menu2″ style=“width: 90px; height: 200px; filter:dropshadow(); position: absolute; left: 89px;top: 40px; visibility: hidden;“&gt

Submenu 3 – filter DropShadow + Alpha – dovoľuje meniť priehľadnosť, alebo transparentné prechody

<span id=“menu3″ style=“width: 155px; height: 150px; filter:DropShadow(), Alpha(Opacity=60); position: absolute; left: 168px;top: 40px; visibility: hidden;“&gt

SubMenu 4 – Dropshadow + Gray – prevedie všetko na odtiene šedej

<span id=“menu4″ style=“width: 90px; height: 300px; filter:dropshadow(), Gray; position: absolute; left: 248px;top: 40px; visibility: hidden;“&gt

SubMenu 5- Dropshadow + Blur: – rozmazanie, ale niekedy dokáže vytvoriť zaujímavý efekt

<span id=“menu5″ style=“width: 155px; height: 80px; filter:dropshadow(), Blur(Strength=50); position: absolute; left: 328px;top: 40px; visibility: hidden;“&gt

Zjednodušenie

Ako všetci určite viete, tak naprogramovať jednu úlohu sa dá mnohými spôsobmi (ak by sme sa zaoberali každým detailom, mohli by sme povedať, že máme nekonečne veľa možností, ako niečo naprogramovať). Preto aj tu sa dajú použiť určité zjednodušenia, ako napr. nepoužívať lokálne premenné i a menu, a namiesto nich zaviesť len dve globálne, kľudne rovnakého názvu, zlúčiť dve funkcie do jednej, alebo napr. namiesto cyklu vo funkcií Hide() použiť jednu globálnu premennú, ktorá si zapamätá číslo menu, ktoré treba zrušiť a podobne. Chcem tým len naznačiť, že viem, že to nie je úplne optimalizovane napísaný skript, avšak myslím si, že pre lepšie pochopenie to takto stačí. Je potom samozrejme na vás ako si ho upravíte, či vylepšíte a budem rád ak sa potom o to vylepšenie so mnou podelíte.

Tak a sme na konci. Dúfam, že aspoň tretina z vás sa dočítala na koniec a že budete mať nejaký úžitok z tohoto postupu. Ešte raz by som chcel pripomenúť, že na celkové pochopenie bude asi potrebné si pozrieť celý kód príkladu.

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ší

Napsat komentář

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