Kliknij poniższe nagłówki menu myszką:
Wymagana wiedza:
Aby wstawić na swoją stronę menu rozwijane, postępują według poniższych instrukcji:
Utwórz w swoim edytorze (X)HTML nowy dokument. Wklej do niego poniższy kod i zapisz w pliku menu.js:
/** * @author Sławomir Kokłowski {@link http://www.kurshtml.boo.pl} * @copyright NIE usuwaj tego komentarza! (Do NOT remove this comment!) */ function Menu(id, style, otworz, wysun, czasRozwin, czasZwin, czasOtworz, czasZamknij) { if (typeof czasRozwin == 'undefined' || czasRozwin < 0) czasRozwin = 25; if (typeof czasZwin == 'undefined' || czasZwin < 0) czasZwin = 25; if (typeof czasOtworz == 'undefined' || czasOtworz < 0) czasOtworz = 250; if (typeof czasZamknij == 'undefined' || czasZamknij < 0) czasZamknij = 500; if (style) { style = style.replace(/(^\s+|(\s|;)+$)/g, '').split(/\s*;\s*/); for (var i = 0; i < style.length; i++) { style[i] = style[i].split(/\s*:\s*/); for (var j = 0, c, property = ''; j < style[i][0].length; j++) { c = style[i][0].charAt(j); property += c == '-' ? style[i][0].charAt(++j).toUpperCase() : c.toLowerCase(); } eval('document.getElementById("' + id + '").style.' + property + ' = "' + style[i][1].replace(/"/g, '\\"') + '"'); } } for (var i = 0; i < document.getElementById(id).getElementsByTagName('dt').length; i++) { var dd = new Array(); var el = document.getElementById(id).getElementsByTagName('dt')[i].nextSibling; var nodeName; while (el && (nodeName = el.nodeName.toLowerCase()) != 'dt') { if (nodeName == 'dd') { el._dt = document.getElementById(id).getElementsByTagName('dt')[i]; if (otworz) { el.onmouseover = function() { clearTimeout(this._dt._timoutID); this._dt._displayed = false; this._dt.onclick(); } el.onmouseout = function() { clearTimeout(this._dt._timoutID); var dt = this._dt; this._dt._timoutID = setTimeout(function () { dt._displayed = true; dt.onclick(); }, czasZamknij); }; } dd[dd.length] = el; } el = el.nextSibling; } document.getElementById(id).getElementsByTagName('dt')[i]._dd = dd; document.getElementById(id).getElementsByTagName('dt')[i]._timoutID = null; document.getElementById(id).getElementsByTagName('dt')[i]._displayed = false; document.getElementById(id).getElementsByTagName('dt')[i].onclick = function() { clearTimeout(this._timoutID); if (!this._displayed) { var el = this.parentNode.getElementsByTagName('dt')[0]; while (el) { if (el.nodeName.toLowerCase() == 'dt' && el != this) { el._displayed = false; if (czasZwin) display(el, 0); else display(el); } el = el.nextSibling; } } this._displayed = !this._displayed; if (this._displayed && czasRozwin || !this._displayed && czasZwin) display(this, 0); else display(this); return false; }; if (otworz) { document.getElementById(id).getElementsByTagName('dt')[i].onmouseover = function() { clearTimeout(this._timoutID); var dt = this; this._timoutID = setTimeout(function () { dt._displayed = false; dt.onclick(); }, czasOtworz); }; document.getElementById(id).getElementsByTagName('dt')[i].onmouseout = function() { clearTimeout(this._timoutID); var dt = this; this._timoutID = setTimeout(function () { dt._displayed = true; dt.onclick(); }, czasZamknij); }; } } for (var i = 0; i < document.getElementById(id).getElementsByTagName('dd').length; i++) { with (document.getElementById(id).getElementsByTagName('dd')[i]) { if (getElementsByTagName('a').length && getElementsByTagName('a')[0].href && unescape(getElementsByTagName('a')[0].href) == unescape(window.location.href)) className = (className ? className + ' ' : '') + 'active'; } } start(document.getElementById(id).getElementsByTagName('dt')[0]); function start(dt) { var hide = true; var el = dt; while (el) { var nodeName = el.nodeName.toLowerCase(); if (nodeName == 'dt') { dt = el; hide = true; } else if (nodeName == 'dd') { if (el.getElementsByTagName('a').length && el.getElementsByTagName('a')[0].href && unescape(el.getElementsByTagName('a')[0].href) == unescape(window.location.href)) { dt._displayed = true; display(dt); hide = false; var el_parentNode = el.parentNode; while (el_parentNode != document.getElementById(id)) { if (el_parentNode.nodeName.toLowerCase() == 'dd') { var el_sibling = el_parentNode.previousSibling; while (el_sibling) { if (el_sibling.nodeName.toLowerCase() == 'dt') { el_sibling._displayed = true; display(el_sibling) break; } el_sibling = el_sibling.previousSibling; } } el_parentNode = el_parentNode.parentNode; } } if (hide) el.style.display = 'none'; start(el.getElementsByTagName('dt')[0]); } el = el.nextSibling; } } function display(dt, i) { if (typeof i == 'undefined') { for (var i = 0; i < dt._dd.length; i++) { dt._dd[i].style.display = dt._displayed ? 'block' : 'none'; } } else if (i < dt._dd.length) { var dir = wysun ? !dt._displayed : dt._displayed; dt._dd[dir ? i : dt._dd.length - 1 - i].style.display = dt._displayed ? 'block' : 'none'; dt._timoutID = setTimeout(function() { display(dt, i + 1); }, dt._displayed ? czasRozwin : czasZwin); } } }
Na samym początku w wyróżnionych miejscach można zmienić domyślne ustawienia konfiguracyjne: czas rozwijania i czas zwijania pojedynczego elementu menu oraz opóźnienie przy otwieraniu i zamykaniu menu (tylko w wersji otwieranej - szczegóły dalej w tym rozdziale). Wszystkie czasy są podane w milisekundach (1 s = 1000 ms). Wartości te zostaną przypisane wszystkim takim blokom menu na stronie, dla których nie określimy inaczej.
Następnie na stronie, gdzie ma być umieszczone menu, należy w nagłówku dokumentu (wewnątrz <head>...</head>) wstawić:
<script type="text/javascript" src="menu.js"></script>
W wyróżnionym miejscu oczywiście należy podać lokalizację utworzonego wcześniej pliku menu.js. Dalej trzeba na stronie w wybranym miejscu osadzić blok menu za pomocą znaczników listy definicyjnej <dl>...</dl>, np.:
Wykazy<dl id="menu0"> <dt>Nagłówek 1</dt> <dd>Element 1.1</dd> <dd>Element 1.2</dd> <dd>Element 1.3</dd> <dt>Nagłówek 2</dt> <dd>Element 2.1</dd> <dd>Element 2.2</dd> <dd>Element 2.3</dd> <dt>Nagłówek 3</dt> <dd>Element 3.1</dd> <dd>Element 3.2</dd> <dd>Element 3.3</dd> </dl>
<dt>...</dt>
). Można tutaj wstawić zwykły tekst, jak również inne elementy - np. obrazek. Aby nagłówek wyglądał jak odsyłacz, można się posłużyć kodem: <a href="javascript:void(0)">Treść nagłówka</a>
.<dd>...</dd>
), przynależące do kolejnych, poprzedzających nagłówków menu (<dt>...</dt>
). Tutaj również nie ma ograniczeń, co do zawartości, którą można umieścić wewnątrz. Mogą to być po prostu odsyłacze ale też inne elementy.Poniżej wystarczy już tylko umieścić wywołanie skryptu:
<script type="text/javascript"> // <![CDATA[ new Menu('menu0'); // ]]> </script>
...i to wszystko :-). Zwróć tylko jeszcze uwagę na wyróżniony identyfikator menu0 w dwóch ostatnich fragmentach kodu: musi być on w obu miejscach identyczny! Dodatkowo w jednym dokumencie nie mogą istnieć dwa bloki menu o takich samych identyfikatorach. Jeśli chcesz osadzić w jednym dokumencie kilka różnych menu tego typu, postępuj następująco:
<script type="text/javascript" src="menu.js"></script>
id="..."
- np. id="menu0"
, id="menu1"
, id="menu2"
itd.Warto nadmienić, że w przypadku kiedy elementy menu zawierają odsyłacze, gałąź menu, w której znajduje się odnośnik do aktualnie wczytanej strony, zostanie na starcie automatycznie rozwinięta. Dzięki temu użytkownik łatwiej odnajdzie punkt w nawigacji, w którym teraz się znajduje. Dodatkowo w takiej sytuacji elementowi <dd>...</dd>
, w którym znajduje się bieżący odsyłacz, zostanie przypisana klasa CSS pod nazwą active, dzięki której można dodatkowo wyróżnić aktualną pozycję menu, dodając odpowiednie deklaracje CSS w arkuszu stylów, np.:
#menu0 dd.active { font-weight: bold; }
Prezentowany skrypt obsługuje również wielopoziomowe struktury menu. Zasada zagnieżdżania polega na zbudowaniu najpierw pierwszego, płaskiego poziomu, a następnie wybraniu określonego elementu <dd>...</dd>
i umieszczeniu w nim podrzędnej listy <dl>...</dl>
, ze swoimi nagłówkami <dt>...</dt>
i elementami <dd>...</dd>
. Oczywiście ilość poziomów zagnieżdżenia nie jest niczym ograniczona.
W celu osadzenia wielopoziomowego menu, należy powtórzyć wszystkie przedstawione wcześniej kroki. Zmianie ulegnie tylko kod (X)HTML tworzący sam blok menu:
<dl id="menu0"> <dt>Nagłówek 1</dt> <dd> <dl> <dt>Nagłówek 1.1</dt> <dd> <dl> <dt>Nagłówek 1.1.1</dt> <dd>Element 1.1.1.1</dd> <dd>Element 1.1.1.2</dd> <dd>Element 1.1.1.3</dd> <dt>Nagłówek 1.1.2</dt> <dd>Element 1.1.2.1</dd> <dd>Element 1.1.2.2</dd> <dd>Element 1.1.2.3</dd> </dl> </dd> <dt>Nagłówek 1.2</dt> <dd>Element 1.2.1</dd> <dd>Element 1.2.2</dd> <dd>Element 1.2.3</dd> </dl> </dd> <dt>Nagłówek 2</dt> <dd> <dl> <dt>Nagłówek 2.1</dt> <dd>Element 2.1.1</dd> <dd>Element 2.1.2</dd> <dd>Element 2.1.3</dd> <dt>Nagłówek 2.2</dt> <dd>Element 2.2.1</dd> <dd>Element 2.2.2</dd> <dd>Element 2.2.3</dd> </dl> </dd> </dl>
Przykład:
Aby przyspieszyć lub zwolnić rozwijanie/zwijanie pozycji menu, należy powtórzyć wszystkie przedstawione kroki, poza ostatnim (wywołanie skryptu), który tym razem należy wykonać następująco:
<script type="text/javascript"> // <![CDATA[ new Menu('menu0', '', false, false, czasRozwin, czasZwin); // ]]> </script>
<dd>...</dd>
). Aby wymusić natychmiastowe rozwinięcie wszystkich elementów, należy podać wartość 0 (zero).Przykład:
Normalnie pozycje menu są rozwijane począwszy od pierwszej do ostatniej, a zwijane od ostatniej do pierwszej. Można odwrócić te kolejności, dzięki czemu uzyskamy efekt wysuwania:
<script type="text/javascript"> // <![CDATA[ new Menu('menu0', '', false, true); // ]]> </script>
Przykład:
Czasem przydatne jest wstawienie menu, które otwiera się po wskazaniu nagłówka myszką, a chowa automatycznie po usunięciu wskaźnika myszki z obrębu wybranego fragmentu menu.
<script type="text/javascript"> // <![CDATA[ new Menu('menu0', '', true); // ]]> </script>
Przykład:
Wskaż poniższe nagłówki menu myszką:
Dla tej wersji menu można dodatkowo zmienić opóźnienie, które występuje bezpośrednio przed rozpoczęciem otwierania oraz zamykania menu. Czas ten jest konieczny, aby posługiwanie się takim menu przez użytkownika mogło przebiegać komfortowo. Zbyt małe opóźnienie - zwłaszcza przy zamykaniu - może znacznie utrudnić nawigację!
<script type="text/javascript"> // <![CDATA[ new Menu('menu0', '', true, false, -1, -1, czasOtworz, czasZamknij); // ]]> </script>
Szczególnie dla menu otwieranego dość nieprzyjemną właściwością jest fakt, że przy jego rozwijaniu elementy poniżej są przesuwane w dół. Można temu zapobiec określając odpowiednią pozycję absolutną bloku. Oczywiście można to zrobić bezpośrednio dodając odpowiednie deklaracje CSS. Jednak trzeba przewidzieć, co się stanie, jeśli przeglądarka użytkownika nie będzie obsługiwać JavaScript. Samo menu nadal będzie funkcjonalne pod względem nawigacji, tzn. jego elementy (odsyłacze) będą dostępne, ale oczywiście funkcja rozwijania nie będzie działać. Jest to jednak sytuacja dopuszczalna. Natomiast niedopuszczalne mogłoby być w takiej sytuacji ułożenie wypozycjonowanego absolutnie menu, które zakrywałoby na stałe fragmenty innych elementów strony, które znajdują się poniżej określonej pozycji. Dlatego pozycję należy ustalać nie poprzez atrybut style="..."
ani wewnętrzny czy zewnętrzny arkusz stylów, tylko modyfikując fragment kodu wywołujący skrypt:
<script type="text/javascript"> // <![CDATA[ new Menu('menu0', 'position: absolute'); // ]]> </script>
Powyższy sposób pozycjonuje blok menu w miejscu, w którym został wstawiony, ale rozwijanie i zwijanie nie powoduje już żadnych przesunięć pozostałych elementów strony. Można oczywiście dokładnie ustalić pozycję bloku menu, dodając dodatkowe deklarację CSS: 'position: absolute; left: 10px; top: 100px'
.
Ponieważ menu otworzy się ponad innymi elementami strony, należy zadbać, aby posiadało ustawione tło. W przeciwnym razie będzie nieczytelne!
Przykład:
Wskaż poniższy nagłówek menu myszką:
Zauważ, że po otworzeniu, menu przykrywa ten tekst.
Wszystkie z przedstawionych powyżej opcji można ze sobą łączyć, uzyskując w ten sposób dodatkowy efekt, np. następujące wywołanie skryptu:
<script type="text/javascript"> // <![CDATA[ new Menu('menu0', 'position: absolute', true, true, 0, 100, 0, 250); // ]]> </script>
spowoduje osadzenie wypozycjonowanego absolutnie menu otwieranego w wersji wysuwanej ze zmodyfikowanymi czasami rozwijania/zwijania oraz opóźnieniem przy otwieraniu i zamykaniu. Aby pominąć określenie pozycji, należy po prostu wpisać '' (dwa apostrofy). Aby pominąć ustalenie wersji otwieranej lub/i wysuwanej, należy w ich miejsce zamiast true wpisać false. Aby pozostawić domyślną wartość dowolnego czasu (rozwijania, zwijania, otwierania lub zamykania) można ich po prostu nie podawać - o ile są to ostatnie wartości (końcowe przecinki też należy usunąć)! Natomiast, aby określić np. opóźnienie przy otwieraniu, nie zmieniając jednocześnie domyślnych wartości czasów rozwijania i zwijania, które go poprzedzają, można im przypisać wartość -1. W takiej sytuacji przyjęta zostanie wartość domyślna: new Menu('menu0', 'position: absolute', true, true, -1, -1, 100);
Przykład:
Wskaż poniższy nagłówk menu myszką:
Zauważ, że po otworzeniu, menu przykrywa ten tekst.
Jeżeli nie odpowiada nam podstawowy wygląd menu, można go zmienić wykorzystując polecenia CSS. W tym celu w pliku menu.css należy wkleić np.:
#menu0 { width: 200px; margin: 10px; padding: 0; } #menu0 dt { background-color: #888; color: #fff; font-weight: bold; text-align: center; cursor: pointer; margin: 10px 0 0 0; padding: 2px; } #menu0 dd { background-color: #eee; color: #000; border-width: 0 1px 1px 1px; border-style: solid; border-color: #888; margin: 0; padding: 1px 5px; } #menu0 dd.active { font-weight: bold; }
W wyróżnionych miejscach wpisano zdefiniowany uprzednio identyfikator menu. Teraz w nagłówku dokumentu (X)HTML (<head>...</head>), na którym wstawione jest menu, wystarczy wstawić odwołanie do utworzonego właśnie zewnętrznego arkusza stylów:
<link rel="Stylesheet" type="text/css" href="menu.css" />
Przykład: