КрасносельскийКонстантинКонстантинович |
ТаблицейБлоками.Приложение Д: выпадающее javascript css html меню |
Последняя модификация: 10.08.2014 г
Страница загружена с адреса: http://webdesign.site3k.ru/conjuncture/append/d/menudrop.html
Другим способом организации навигации (см. «Оглавления для сайтов», многоуровневое раскрывающееся меню, «Ссылки и окна. Внешний вид и внутреннее содержание») являются выпадающие списки.
В последнее время, меню из выпадающих списков приобретают популярность в русском Интернете, и в этом нет ничего удивительного, так как они позволяют разместить большое количество ссылок на малом участке экрана. Все эти меню построены на основе одного шаблона, лежащего, может быть, на сайте www.woscripts.com. И все они могут не работать в некоторых браузерах. Меня, конечно, такие меню не интересовали. Меня интересовали меню, которые работали бы во всех браузерах и имели бы минимум кода, в отличие от громоздких меню по шаблонам.
Простейшим способом создания меню является использование выпадающего списка:
<p style="margin-top:20px; font-size:80%">Выберите место на карте или из списка:
<select name="menu" onchange="window.location=value;">
<option selected value="map.html">Все
<option value="avtovokzal.html">Автовокзал
<option value="gagarina.html">Гагарина
<option value="ispolkom.html">Исполком
<option value="miroshnika.html">Мирошника
</select>
Которое выгляти так:
Выберите место на карте или из списка:
Такое меню я применил в дополнение к навигационной карте и двум другим способам навигации на сайте praktika.net.ua. При желании можно собрать несколько элементов Select в столбец или строку, но выглядит это не очень эффектно.
Более эффектным было бы классическое меню слева от текста, но чтобы оно исчезало, когда не требуется, освобождая пространство для основного содержания.
Не скрою, идея такого меню появилась у меня, когда я увидел его на одном из сайтов. Просмотрев тогда его код, я изрядно запутался: куча функций, назначение которых оставалось непонятным. Тогда я попросил у автора сайта разъяснить, для чего используются некоторые вещи, но вразумительного ответа он не дал, объяснив что, использовал чей-то шаблон. Из принципа, я сделал аналогичное меню, с тем же дизайном, но без шаблона и с компактным кодом. Кроме того, добился, чтобы это меню работало в любом браузере, в отличие от оригинала, не работающего, в частности, в нетскейпе.
И так, классическое меню справа от текста:
<div id="obj" style="position:absolute;top:50px;left:-100px;Z-Index:20" onmouseover="show()" onmouseout="hide()">
<table border=1px cellpadding="0" cellspacing="1" bgcolor=#FEB834 style="border-collapse:collapse;cursor:default">
<tr>
<td WIDTH=98px bgcolor=orange align=center><b>Оглавление</b></td>
<td id=rightKol align="center" rowspan="3" width=20px bgcolor=orange valign=center> <p align="center"><B>О<br>г<br>л<br>а<br>в<br>л <br>е<br>н<br>и<br>е</B></p></TD>
</tr>
<tr><td class=R4>
<p><A HREF="javascript:alert('Пункт меню 1');"><div id=I>Пункт </div></a>
<p><A HREF="javascript:alert('Пункт меню 2');"><div id=I>Пункт меню </div></a>
<p><A HREF="javascript:alert('Пункт меню 3');"><div id=I>Пункт меню </div></a>
<p><A HREF="javascript:alert('Пункт меню 4');"><div id=I>Пункт меню </div></a>
<p><A HREF="javascript:alert('Пункт меню 5');"><div id=I>Пункт меню </div></a>
<p><A HREF="javascript:alert('Пункт меню 6');"><div id=I>Пункт меню </div></a>
<p><A HREF="javascript:alert('Пункт меню 7');"><div id=I>Пункт меню </div></a>
<p><A HREF="javascript:alert('Пункт меню 8');"><div id=I>Пункт меню </div></a>
<p><A HREF="javascript:alert('Пункт меню 9');"><div id=I>Пункт меню </div></a>
<p><A HREF="javascript:alert('Пункт меню 10');"><div id=I>Пункт меню </div></a>
</td></tr>
<tr><td bgcolor=orange align=center><b>Оглавление</b></td> </TR>
</table>
</div> <!-- Перемещаемый объект. Фон лучше менять за счет различия активных и неактивных ссылок -->
Вроде самое обычное меню. Бросается в глаза только реакция на события onmouseover и onmouseout, да и абсолютное позиционирование с Z-индексом применяется в меню не часто. Но именно это и позволяет убирать меню или показывать, поверх текста. Не менее важным является назначение идентификатора всему блоку, содержащему меню (id="obj") и крайней правой ячейке с вертикальным текстом (id=rightKol).
Теперь, нужно выделить меню цветом:
<STYLE TYPE="text/css">
H1, H2, H3 {text-align:center; margin:0 -10 10; color:Teal}
div {text-align:justify}
BODY {margin-left:25pt;background:white}
td P {margin:0;Padding:0;text-indent:0pt;}
.R4 :link {TEXT-DECORATION:none;cursor:default}
:link #I, :visited #I {TEXT-DECORATION:none;color:black;background:#FEB834;cursor:default;}
:hover #I {background:orange}
</STYLE>
И создать функции отображения и скрытия. Начинать стоит со скрытия, так как пункты меню изначально должны быть отображены, чтобы нормально проиндексироваться поисковиками, игнорирующими скрытые слои и отобразится браузерами, не поддерживающими используемые в скриптах функции (эти аспекты не учитываются используемыми в Интернете шаблонами):
function hide() {
mymenu=eval("document.getElementById('obj')");
myRightKol=eval("document.getElementById('rightKol')");
mymenu.style.left=0-myRightKol.offsetLeft;
}
Вот и весь код. Нужен ли для этого громоздкий шаблон? Код учитывает обедненную модель объектов нетскейпа, не позволяющую обращаться к объектам напрямую. Поэтому, обращение установлено по переменным-ссылкам, получающим в первых двух строках объекты «obj» и «rightKol». В третьей строке через назначенную ему переменную, объекту «obj» определяется отступ от левого края, равный ширине основных ячеек таблицы (когда я сочинял код, вместо ширины основной ячейки использовал положение ячейки, ограничивающей таблицу справа, но это ничего не меняет). Поскольку отступ отрицательный и равен по модулю ширине основных ячеек, при запуске функции все меню смещается влево на ширину основных ячеек, так, чтобы виделась только правая ограничивающая ячейка, отображение которой необходимо, чтобы меню не исчезло совсем.
Для отображения меню, требуется навести мышь на оставшуюся видимой правую часть. Как только мышь окажется над меню (произойдет событие onmouseover), запустится функция show, еще более простая, чем hide:
function show() {
mymenu=eval("document.getElementById('obj')");
mymenu.style.left='0px';
}
Достаточно лишь определить что, отступ «obj» за левый край равен нолю.
Фактически, меню готово. Но для большего удобства, стоит сделать так, чтобы оно не уходило вверх, по мере чтения текста, а всегда оставалось на месте (не люблю я, дочитав страницу до конца, искать клавишу HOME, чтобы вновь увидеть меню). Для этого делаем функцию «Move»:
function move() { // Функция перемещения:
mymenu=eval("document.getElementById('obj')"); // объект настолько удален от верхнего угла документа,
mymenu.style.top=document.body.scrollTop+50; // насколько тот перемещен вверх (плюс 50 пикселей)
if (mymenu.style.left!=0) { // если после закрытия меню менялся масштаб на меньший, меню может
myRightKol=eval("document.getElementById('rightKol')"); // оказаться слишком задвинутым влево.
mymenu.style.left=0-myRightKol.offsetLeft; // Исправляем.
}
}
В этой функции мы переопределяем отступ меню от верхнего края документа (более подробные пояснения в Оглавления для сайтов) и, на всякий случай, переустанавливаем левый отступ. Вызывать функцию следует по событию onload, и назначив ей обработчики (если не использовать move, по событию onload следует вызвать функцию hide):
window.onresize=move; // Объявляются обработчики событий: изменение размеров
window.onscroll=move; // и скролинг вызывают функцию move
if (navigator.appName == "Netscape")
{
window.onkeyup=move; // Netscape не генерирует scroll если прокрутка идет с клавиатуры
window.onclick=move; // Netscape не генерирует scroll если прокрутка идет колесом мыши
}
Собираем все в кучу, добавляем на страницу текст, на фоне которого должно появляться меню и получаем:
Аналогично можно создать горизонтальное меню, как у какой-нибудь программы, например, у Internet Explorer.
Для начала изобразим панель меню:
<Table id="obj" cellpadding=0 CELLSPACING=0 width="100%" border=1px BGCOLOR=#FEB834
style="border-collapse:collapse;cursor:default;position:absolute;top:0px">
<TR>
<TD width="16%" onmouseover="show('menu1');" onmouseout="hide('menu1');">
Файл</TD>
<TD width="16%" onmouseover="show('menu2');" onmouseout="hide('menu2');">
Правка</TD>
<TD width="16%" onmouseover="show('menu3');" onmouseout="hide('menu3');">
Вид</TD>
<TD width="16%" onmouseover="show('menu4');" onmouseout="hide('menu4');">
Избранное</TD>
<TD width="16%" onmouseover="show('menu5');" onmouseout="hide('menu5');">
Сервис</TD>
<TD width="20%" onmouseover="show('menu6');" onmouseout="hide('menu6');">
Справка</TD>
</TR>
</Table>
Наиболее очевидным отличием от предыдущего меню, является то, что функции скрытия и отображения теперь вызываются с парамертами. Это необходимо, так как теперь придется скрывать и отображать различные выпадающие списки, а не один, как раньше. И скрипту требуется сообщать их имя.
Затем опишем сами списки (я упрощаю их содержание, чтобы быстрее написать):
<div id="menu1" onmouseover="show('menu1');" onmouseout="hide('menu1');">
<dt>Пункт 1 меню 1
<dt>Пункт 2 меню 1
<dt>Пункт 3 меню 1
<dt>Пункт 4 меню 1
<dt>Пункт 5 меню 1
<dt>Пункт 6 меню 1
<dt>Пункт 7 меню 1
<dt>Пункт 8 меню 1
</div>
<div id="menu2" onmouseover="show('menu2');" onmouseout="hide('menu2');">
<dt>Пункт 1 меню 2
<dt>Пункт 2 меню 2
<dt>Пункт 3 меню 2
<dt>Пункт 4 меню 2
<dt>Пункт 5 меню 2
<dt>Пункт 6 меню 2
<dt>Пункт 7 меню 2
<dt>Пункт 8 меню 2
</div>
<div id="menu3" onmouseover="show('menu3');" onmouseout="hide('menu3');">
<dt>Пункт 1 меню 3
<dt>Пункт 2 меню 3
<dt>Пункт 3 меню 3
<dt>Пункт 4 меню 3
<dt>Пункт 5 меню 3
<dt>Пункт 6 меню 3
<dt>Пункт 7 меню 3
<dt>Пункт 8 меню 3
</div>
<div id="menu4" onmouseover="show('menu4');" onmouseout="hide('menu4');">
<dt>Пункт 1 меню 4
<dt>Пункт 2 меню 4
<dt>Пункт 3 меню 4
<dt>Пункт 4 меню 4
<dt>Пункт 5 меню 4
<dt>Пункт 6 меню 4
<dt>Пункт 7 меню 4
<dt>Пункт 8 меню 4
</div>
<div id="menu5" onmouseover="show('menu5');" onmouseout="hide('menu5');">
<dt>Пункт 1 меню 5
<dt>Пункт 2 меню 5
<dt>Пункт 3 меню 5
<dt>Пункт 4 меню 5
<dt>Пункт 5 меню 5
<dt>Пункт 6 меню 5
<dt>Пункт 7 меню 5
<dt>Пункт 8 меню 5
</div>
<div id="menu6" onmouseover="show('menu6');" onmouseout="hide('menu6');">
<dt>Пункт 1 меню 6
<dt>Пункт 2 меню 6
<dt>Пункт 3 меню 6
<dt>Пункт 4 меню 6
<dt>Пункт 5 меню 6
<dt>Пункт 6 меню 6
<dt>Пункт 7 меню 6
<dt>Пункт 8 меню 6
</div>
Поскольку все эти меню по умолчанию отображены, чтобы индексироваться поисковыми системами, при загрузке документа, их следует скрыть. Для этого создаем функцию initMenu:
function initMenu() { // закрывает изначально открытые выпадающие списки
myObj=eval("document.getElementById('obj')");
for(i=1;i<=myObj.rows[0].cells.length;i++) // Пока i=1, не достигнет количества столбцов
{
mymenu=eval("document.getElementById('menu' + i)"); // получает элимент
mymenu.style.display='none';
}
move(); // Если хотим его перемещать
}
И встраеваем ее вызов в объявление тела документа:
<BODY onload="initMenu();">
Теперь опять создаем функцию закрытия списка в которой имя списка определяется параметром вызова:
function hide(menu) {
mymenu=eval("document.getElementById(menu)");
mymenu.style.display="none";
}
И функцию открытия:
function show(menu) { // Раздельное скрытие.раскрытие работает корректней
if (navigator.appName == "Netscape")
{
for(i=1;i<=myObj.rows[0].cells.length;i++)
// Пока i=1, не достигнет количества столбцов
{
mymenu=eval("document.getElementById('menu' + i)");
// получает выпадающие меню
mymenu.style.display="none";
// закрыть все меню (в Нетскейпе могут не корректно закрываться)
}
}
mymenu=eval("document.getElementById(menu)");
mymenu.style.display="block";
}
Теперь создадим функцию перемещения, если хотим, чтобы меню не уезжало вверх, при перемещении по странице:
function move() // Функция перемещения:
{
myObj=eval("document.getElementById('obj')");
myObj.style.top=document.body.scrollTop;
// объект настолько удален от верхнего угла документа,
for(i=1;i<=myObj.rows[0].cells.length;i++)
// Пока i=1, не достигнет количества столбцов
{
mymenu=eval("document.getElementById('menu' + i)"); // получает выпадающие меню
mymenu.style.top=document.body.scrollTop+myObj.rows[0].cells[i-1].offsetHeight;
// устанавливает свойства выпадающих списков, с большой точностью
mymenu.style.left=myObj.rows[0].cells[i-1].offsetLeft+myObj.offsetLeft;
// определяя высоту и отступ с лева
if (navigator.appName == "Netscape")
{
mymenu.style.display="none";
// закрыть все меню (в Нетскейпе могут не корректно закрываться)
}
}
}
И определим ее обработчиком скролинга и изменения размеров:
window.onresize=move; // Объявляются обработчики событий: изменение размеров
window.onscroll=move; // и скролинг вызывают функцию move
if (navigator.appName == "Netscape")
{
window.onkeyup=move; // Netscape не генерирует scroll если прокрутка идет с клавиатуры
window.onclick=move; // Netscape не генерирует scroll если прокрутка идет колесом мыши
} // частично это компенсируется реакцией на щелчек
Строку «myObj.style.top» следует убрать, из функции move, если меню не планируется перемещать. Остальные строки определяют положение выпадающих списков, меняющееся при изменении пользователем размеров окна.
Собираем все в кучу, добавляем оформление:
<STYLE TYPE="text/css">
H1, H2, H3 {text-align:center; margin:0 -10 10; color:Teal}
TD {text-align:center; font-size:80%; Padding:0pt 5pt}
div {position:absolute;Z-Index:20;background:#FEB834;cursor:default;}
dt {white-space: nowrap; Padding:0pt 5pt}
</STYLE>
и текст, на фоне которого должно появляться меню.
Смотрим (в примере для большей наглядности пункт «Правка» сделан активным).