Веб-школа
Интернет-технологии

РЕКЛАМА

Разное

Иерархическое (многоуровневое)
меню навигации на JavaScript
(часть 6)

< Часть 5

menucont.js. Построение меню более подробно описано в Главе 1. Напомним вкратце принцип создания меню. Сначала создаются конечные элементы меню MenuItem. Эти элементы включаются в состав подменю MenuBox функцией-методом MenuBox.addItem(item). Составленные таким образом подменю вместе с другими элементами MenuItem включаются в подменю низшего уровня (той же функцией MenuBox.addItem(item)). На нулевом уровне все ветки подменю сходятся к набору подменю нулевого уровня, которые включаются в объект MenuBar функцией-методом MenuBar.addMenu(submenu). Этот объект menu типа MenuBar является глобальным объектом и, собственно, ответсвеннен за содержание меню.

handles.js. Рассмотренные выше js-файлы фактически не включали элементы Dynamic HTML, необходимые для обработки событий от элементов меню. Для обеспечения работы меню нам необходимо обработать три события от мышки: перемещение на и с элемента с id=submenu (события onmouseover и onmouseout), перемещение на и с элемента и щелчок на элементе с id=menupunkt (onmouseover, onmouseout, onclick). Элемент (тэг SPAN) с id=submenu должен отвечать за отображение и позиционирование подменю (тэг DIV), ассоциированное с данным пунктом меню, при перемещении мышки на/с него. Элемент (тэг SPAN) с id=menupunkt отвечает за отображение визуальной активности пункта при перемещении мышки с/на него и навигации (или выполнения JavaScript-кода) при щелчке (выборе) на нем.

В файле handles.js (см. Листинг 3) приведены два обработчика событий для элемнтов с id submenu и menupunkt, а также функции, которые используются в этих обработчиках. Каждый обработчик связан с элементом с конкретным id через html-код (см. выше).

Листинг 3. Файл handles.js
 

Реклама


var oldstatus=null; //глобальная переменная;
//хранит предыдущую строку статуса

//Получить SPAN с параметром name равным аргументу функции
function getSpan(name){
for (var i=0; i<spans.length; i++) if (spans[i].name==name) return spans[i];
return null;
}

//Получить DIV с параметром name равным аргументу функции
function getDiv(name){
var dvs = divs.item("submenu");
if (dvs != null)
for (var i=0; i<dvs.length; i++) if (dvs[i].name==name) return dvs[i];
return null;
}

//Спрятать все подменю с zIndex >= zIndex текущего подменю
// zi и имя (name) текущего подменю
function HideGtDiv(zi, dn){
var dvs = divs.item("submenu");
//выделяем из массива divs элементы c id=submenu
for (var i=0; i<dvs.length; i++)
 if (dvs[i].style.zIndex>=zi)
  if (dvs[i].name!=dn) dvs[i].style.visibility="hidden";
}

//Спрятать все подменю выше или равные по иерархии подменю,
//содержащее элемент se
function HideSubMenu(se){
var spn = menu.getMenuItem(se.name);
//получим объект пункта меню с именем элемента se 
if (spn==null) return;
var mb = spn.owner;                //mb - подменю-владелец пункта меню
var div = getDiv(mb.idname);     //найдем DIV с именем текущего подменю
if (div==null) return;
HideGtDiv(div.style.zIndex,div.name);
//спрячем все подменю выше или равные текущему подменю
//восстановим строку статуса 
if (oldstatus!=null) window.status=oldstatus;
else window.status=window.defaultStatus;
}

//Спрятать (скрыть) все подменю
function HideAllSubMenu(){
var dvs = divs.item("submenu");
 for (var i=0; i<dvs.length; i++)
  if (dvs[i].className=="submenu")
    dvs[i].style.visibility="hidden";
}

// Функция отображения меню mb
function ViewSubMenu(mb){
var obj = getDiv(mb.idname);
if (obj == null) return;
var spn = getSpan(mb.idname);
var offs = 0;
var bdy = document.body;
var w=0;
if (bdy!=null) w=bdy.clientWidth;
else  w=window.screen.width;
if (mb.owner.idname==null)
{
 HideAllSubMenu();
 if (spn != null) offs = spn.offsetLeft;
 obj.style.pixelTop = MainMenuBar.offsetTop + MainMenuBar.offsetHeight;
 obj.style.pixelLeft = MainMenuBar.offsetLeft+offs;
 if ((obj.style.pixelLeft + obj.style.pixelWidth)>w)
  if ((w-obj.style.pixelWidth)>0)
     obj.style.pixelLeft = w-obj.style.pixelWidth;
}
else
{
 var ownr = getDiv(mb.owner.idname);
 if (spn != null) offs = spn.offsetWidth;
 obj.style.pixelTop = ownr.offsetTop + spn.offsetTop;
 obj.style.pixelLeft = ownr.offsetLeft+offs-2;
 if ((obj.style.pixelLeft + obj.style.pixelWidth)>w)
  if ((ownr.offsetLeft-obj.style.pixelWidth)>0)
    obj.style.pixelLeft = ownr.offsetLeft-obj.style.pixelWidth+2;
}
 obj.style.visibility="";
}

//******* Обработчик для элементов с id=submenu ******
function doEventMenu(){
 var e = window.event;
 var SE = e.srcElement;
 var TE = e.toElement;
 if (e.type=="mouseout"){
    if (TE==null) return;
    if (TE.name==null) HideAllSubMenu();
 }
 else 
 if (e.type=="mouseover"){
   if (SE==null) return;
   var mb = menu.getSubMenu(SE.name);
   if (mb!=null) ViewSubMenu(mb);
 }
}
//******* Обработчик для элементов с id=menupunkt ******
function doEventSubMenu(){
 var e = window.event;
 var SE = e.srcElement;
 if (e.type=="mouseout"){
    SE.className = "nonact";
    if (oldstatus==null)  window.status=window.defaultStatus;
    else window.status=oldstatus;
}
else
if (e.type=="mouseover"){
   SE.className = "active";
   HideSubMenu(SE)
   var mi = null, mb = null;
   if((mi = menu.getMenuItem(SE.name))==null) return;
   if(oldstatus==null) oldstatus=window.status;
   window.status=mi.a;
}else
 if (e.type=="click"){
   if((mi = menu.getMenuItem(SE.name))==null) return;
   if (mi.objname == "item")
   {
   if ((mi.a.indexOf("javascript",0)!=-1)||(mi.a.indexOf("jscript",0)!=-1)) eval(mi.a);
   else
   {
     if (oldstatus==null)  window.status=window.defaultStatus;
       else window.status=oldstatus;
     document.location=mi.a;
   }
    HideAllSubMenu();
   }
}}

 

Реклама

Каждому сайту - механизм организации собственной ленты новостей бесплатно! Подробнее >>

Напомним что, функция ConstructMenu так генерирует html-код, что id=submenu имеют тэги SPAN полосы меню и DIV всех подменю. Все остальные пункты подменю (заключенные в тэги SPAN), включая ссылки (указатели) на подменю высшего уровня, имеют id=menupunkt. Эти пункты меню включаются в тэги DIV подменю, так что DIV является контейнером (и владельцем) этих пунктов. События от мыши для этих тэгов созникают согласно принципа всплытия пузырька (event bubbling): сначала событие направляется элементу (тэгу), содержащемуся непосредственно под курсором мышки (самому верхнему), затем элементу, содержащему верхний элемент и т.д. Последними получают событие объекты браузера document и window. (Следует заметить, что этот механизм справедлив лишь для браузера MS Internet Explorer; для других браузеров он может отличаться.) Таким образом, в нашем случае, первым событие получает пункт меню (SPAN), а затем подменю (DIV). При получении события пунктом меню он активизируется. Далее событие получает подменю. Если активный пункт меню является указателем на подменю высшего уровня, то отображается это подменю.

Код обработчика события может получить полезную информацию из свойства event объекта window браузера. В частности свойства объекта event – type, srcElement, toElement указывают на тип (строковое представление рода события, например, "mouseover"), элемент активный во время события (элемент-источник) и активизирующийся элемент (для событий перемещения мыши). (Есть и другие свойства event, но мы их рассматривать не будем.)

Код обработчика событий для подменю (id=submenu) довольно прост. Если мышь покинула элемент (событие mouseout) и не определен активизирующийся элемент, то все подменю прячутся. Если мышь перешла на элемент (событие mouseover), то в главном меню menu ищется подменю с именем равным имени элемента-источника. Если оно найдено, то его отображают (функция ViewSubMenu); в противном случае ничего не делают.

Код обработчика событий для пунктов меню (id=menupunkt) немного более сложен. На событие mouseout (деактивизация) имени класса пункта меню присваивается имя определенного в файле стилей класса "nonact" и восстанавливается строка статуса. При событии mouseover (активизация) класс пункта меню меняется на "active", прячутся все подменю высшего, чем подменю данного пункта, уровня (функция HideSubMenu), ищется в главном меню объект MenuItem с именем, равным имени элемента-источника. URL (поле а) найденного объекта записывается в строку статуса. На событие click (пункт меню выбран) ищется в главном меню объект MenuItem с именем, равным имени элемента-источника. Если найденный элемент ссылка (или JavaScript), а не указатель на подменю высшего уровня, то выполняется переход по URL пукта меню (поле а объекта MenuItem). Для этого в свойство location объекта браузера document записывается данный URL. Если вместо ссылки приведен JavaScript-код (дает положительный результат поиск строк "javascript" или "jscript"), то выполняется команда (функция JavaScript eval). Если пункт меню – указатель на подменю высшего уровня, то событие click игнорируется.

За отображение подменю отвечает функция ViewSubMenu (mb), где mb – объект подменю. Позиционирование (т.е. расположение в окне браузера) подменю различается для подменю нулевого уровня и подменю других уровней. Подменю нулевого уровня находится под пунктом полосы главного меню, в то время как другие подменю слева от пункта-указателя на это подменю. Таким образом, для отображения подменю

  • ищутся DIV, отвечающий за подменю, которое надо отобразить, и SPAN – пункт-указатель на это подменю (функции getDiv и getSpan; описание см. в Листинге 3);
  • если имя владельца подменю (поле owner.idname) пустое, то это подменю нулевого уровня (оно не имеет владельца). В этом случае прячутся все подменю. Левая сторона этого подменю приравнивается левой стороне пункта-указателя. Верхняя сторона равна верхней стороне пункта-указателя увеличенной на высоту этого пункта.
  • в противном случае это подменю высшего уровня. Левая сторона этого подменю приравнивается левой стороне пункта-указателя увеличенной на ширину этого пункта. Верхняя сторона равна верхней стороне пункта-указателя.
  • в обоих случаях проверяется возможность выхода подменю за правый край окна браузера (вернее тэга BODY). По возможности позиция корректируется, чтобы устранить это.
  • для объекта подменю убирается свойство невидимости строкой obj.style.visibility="";

Описание остальных функций файла handles.js тривиально и приведено в Листинге 3[> далее >]

© 2000, Сергей Кузнецов
 

Реклама

ВАКАНСИИ (Компьютеры, Интернет). Подробнее >>

ПОИСК по сайту: 
© iD, 2000

Hosted by uCoz