Password
    
 К титульной странице  |  Форум  |  О проекте  |  Словарь  |  Товары  |  Сделать стартовой  |  В Закладки   
Авторизация
Забыли пароль?
Регистрация 
 
Программирование
Безопасность
Демосцена
Игры
WEB-мастерская
Программное обеспечение
Аппаратное обеспечение



Последние материалы
  The Chronicles of Riddick: Escape from Butcher bay

  Что такое хорошо и что такое плохо, или FAQ по LCD-мониторам

  Организация удаленного доступа

  Инсталляция программного обеспечения используя GPO

  Smarty в веб-разработке

  BioShock или кафе разбитых надежд...



Последние новости
  Латвия подписала АСТА

  Примечательная промо-акция игры STAR WARS: The Old Republic на Times Square в Нью Йорке

  На сайте выложены первые выпуски легендарной телепередачи о компьютерных играх "От винта!"

  На сайте опубликован энциклопедический словарь по информатике Э.Якубайтиса

  Конференция Разработчиков Видеоигр, 1979

  Более шустрый и динамичный Mail.lv



Charitable advertising
Њл ­г¦¤ Ґ¬бп ў ў иҐ© Ї®¬®йЁ!



Ziedot.lv

Penn State Child Life Program



WEB-мастерская--->JavaScript
Создаём Div’ное,выпадающее меню (Часть II: ещё немного о слоях)
  
Автор: Mihail Chernov
Опубликовано: [2005-07-01 11:29]
В предыдущей статье мы занимались изготовлением простейшего двухуровнего выпадающего меню... Сегодня же мы его усовершенствуем так, чтобы оно умело”выезжать” (появляться), а также”заезжать”(исчезать) плавно.

Другими словами, мы добавим немного эффектов. Но сначала я бы хотел сделать небольшое лирическое отступление:

На самом деле, при создании выпадающего меню мы будем работать с DHTML (Dinamic Hypertext Markup Language). Который представляет из себя нечто иное как HTML четвёртой версии с расширенным JavaScript. Основной проблемой,мешающей повсеместному внедрению этой технологии,является несовместимость браузеров. К счастью, на сегодняшний день 2 популярных браузера Netscape Navigator (N.S. 6.0 и выше) и Internet Explorer (I.E. 4.0 и выше) являются, если можно так выразиться, более менее совместимыми (далеко не на все 100). Для них, а также для N.S. 4.0. и написаны сценарии прилагаемые к этой статье.

Что же такое слой? Слой - это некий прямоугольный элемент,содержащий в себе разметку HTML. Сами слои обозначаются следующими тэгами: <div>, <span>, <layer>, <ilayer> и имеют следующие параметры стиля (style):

position - определяет точку отсчёта координат. Может принимать следующие значения: absolute - координаты отсчитываются относительно верхнего левого угла документа; relative - от верхнего левого угла слоя содержащий описываемый слой;

top - определяет Y слоя;
left - определяет X слоя;

z-index - определяет уровень слоя. Данный параметр используется при наложении слоёв друг на друга (перекрытии). Он указывает браузеру какой слой находится выше (рекомендуется использовать значения z-index>=0).

visibility - видимость слоя:
visible - слой виден;
hidden - слой скрыт.

А это HTML код одного из слоя-подменю (в нашем примере их 3):

<DIV ID="submenu1" STYLE="FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;LEFT: -1000px; VISIBILITY: hidden;POSITION: absolute;TOP: -1000px;" onMouseOut="hidemenu(true)" onMouseOver="cancelhide()">
<table cellpadding=1 cellspacing=0 BORDER=1 width=150>
<tr>
<td width=80><a href="">SubMenu1_1</a></td>
</tr>
<tr>
<td><a href="">SubMenu1_2</a></td>
</tr>
<tr>
<td><a href="">SubMenu1_3</a></td>
</tr>
<tr>
<td><a href="">SubMenu1_4</a></td>
</tr>
</table>
</DIV>

Слоями можно манипулировать,изменяя их параметры с помощью JavaScript. Например, чтобы заставить браузер отобразить невидимый слой,мы можем использовать следующий скрипт:

Для IE 4:
document.all["layername"].visibility=’visible’;

Для NS 4:
document.layers["layername"].visibility="visible";

Для IE 5 и NS 6:
layer= document.getElementById(“layername”);
layer.style.display = "";

Оказывается,можно не только отображать весь слой целиком, но и его часть. С помощью так называемой области отсечения (поддерживается в IE и в NS начиная с версии 4). Вот таким образом:

Для IE 5 и NS 6:
layer = document.getElementById("layername");
layer.style.clip = "rect(top right bottom left)";

(Где top, right, bottom, left - координаты области отсечения).

Для IE 4:
document.all.layername.style.clip = "rect(top right bottom left)";

Для NS 4:
document.layers.layername.clip.top = top;
document.layers.layername.clip.right = right;
document.layers.layername.clip.bottom = bottom;
document.layers.layername.clip.left = left;

Но и это ещё не всё! Вы также можете управлять прозрачностью слоёв с помощью JS:

В IE:
document.all.layername.style.filter="alpha(opacity=75)";

В NS 6:
layer = document.getElementById("layername");
layer.style.MozOpacity = 75/100;

Ну а теперь, когда мы знаем что такое слои и с чем их едят,можно приступить к модификации сценариев для работы меню. Ведь если в предыдущей статье этого цикла мы писали меню, которое раскрывается мгновенно, то здесь нам нужно добавить эффекты при его открытии и закрытии. А это будет стоить нам нескольких десятков дополнительных строк кода, и ничего здесь не поделаешь. Поверьте мне, результат того стоит (см. ниже) !!! ;)

<Script Language="JavaScript">

var mstatus=true; 

//mstatus - определяет раскрывается(true) или закрывается(false) меню  


var timer1=false; 
// сюда будет записываться задержка закрытия

var mstep=3;
// кол-во пикселей, на которые будет передвигаться меню за 1 итерацию

var cm=null;
// здесь будет запоминаться последний активный слой



var hide_delay=500;
// задержка перед тем, как активный слой станет невидимым

var tstat=0;
// имеются ли видимые слои (0 - нет, 1 - да)



// Определяем браузер пользователя

isNS4 = (document.layers) ? true : false;
isIE4 = (document.all && !document.getElementById) ? true : false;
isIE5 = (document.all && document.getElementById) ? true : false;
isNS6 = (!document.all && document.getElementById) ? true : false;


// Функция, отображающая и скрывающая слои

// Вход:
// objElement - идентификатор(id) слоя;
// bolVisible - булева переменная:
// true  - отобразить слой;
// false - скрыть слой.

// Выход:
// 1


// P.S: В зависимости от типа браузера
// сценарий для манипуляции с видимостью слоёв
// несколько различается.

function switchDiv(objElement,bolVisible){
if(isNS4||isIE4){
     if(!bolVisible) {
       objElement.visibility ="hidden"
     } else {
       objElement.visibility ="visible"
     }     
 } else if (isIE5 || isNS6) {
      if(!bolVisible){
         objElement.style.display = "none";
         
      } else {
        objElement.style.display = "";
        
        }

      }

return 1;
}



// Функция, возвращающая значение указанного ей 
// свойства объекта (не обязательно слоя).

// Вход:
// el    - идентификатор элемента;
// sProp - свойство (left,top...)

// Выход:
// Значение какого-нибудь свойства объекта.



function getPos(el,sProp) {
	var iPos = 0;
	while (el!=null) {
		iPos+=el["offset" + sProp]
		el = el.offsetParent
	}
	return iPos

}



// Функция выдаёт объект с указанным
// ей названием.

// Вход:
// myid - название объекта

// Выход: объект.

function getelementbyid(myid) {
   if (isNS4){
        objElement = document.layers[myid];
     }else if (isIE4) {
        objElement = document.all[myid];
     }else if (isIE5 || isNS6) {
             objElement = document.getElementById(myid);
     }
return(objElement);
}



// Функция отображающая|скрывающая
// слои.

// Данная Функция не меняет координаты слоёв,
// не делает их прозрачными, а вызывает функцию movefx,
// которая этим занимается. 


// Вход:
// el - яйчейка таблицы на которой 
// находится указатель;
// m  - наименование слоя, который надо
// отобразить под этой яйчейкой.

function show(el,m) {

if (m!=null) {
m=getelementbyid(m);
}

// получаем элемент в m


        if ((el==null) && (cm)) {
        mstatus=false;
        movefx()
// закрываем меню через movefx

        } else if ((m!=cm) && (m)) {
        if (cm!=null) switchDiv(cm,false);
// пользователь перешёл на другой пункт основного меню
// немедлено сделать невидимым предыдущий (cm) видимый в данный момент слой.  

        switchDiv(m,true); // сделать видимым  слой m
        fxel=el;             
        fxm=m;
        fxrect=0; // текущая высота области отсечения (см. ниже)

        // запоминаем значения в глобальных переменных
        // для использования в дальнейшем

        mstatus=true; // будем открывать меню с помощью movefx
        movefx()
	}
        
        if (m) cm=m; 
        // запоминаем значение m в cm 

  if (tstat==1) {
  clearTimeout(timer1);
  tstat=0
// если таймер timer1 запущен, останавливаем его
  }
 
}


// Функция, "закрывающая" меню.

// Функция принимает на вход b типа boolean
// при true закрывает меню учитывая задержку hide_delay;
// при false (или каком-либо другом значении кроме true) 
// закрывает меню немедленно
 
// и возвращает 1.

function hidemenu(b) {
 if (b)  {
 tstat=1;
 timer1=setTimeout("show(null)",hide_delay);
 } else {
 tstat=0;
 show(null);
 }

}



// Функция, останавливающая таймер, запущенный
// прошлой функцией. Таким образом,
// меню не пропадает.

// Функция ничего не принимает на вход
// и возвращает 1.

function cancelhide() {

if (!mstatus) {
mstatus=1;
// если меню закрывалось, открываем его вновь
}
 
tstat=0;
clearTimeout(timer1);
// останавливаем таймер
 

}



// Функция, отвечающая за эффектное выпадение меню. 
// Ничего не принимает на вход
// Возвращает 1.


function movefx() {

if ((mstatus) && (fxrect>fxm.offsetHeight)) {
fxrect=fxm.offsetHeight;
return 1;

// Если меню открывается и высота области отсечения больше
// высоты самого слоя, то делаем высоту области равной высоте слоя
// и выходим из функции.
 
} 



if ((!mstatus) && (fxrect<0)) {
fxrect=0;
switchDiv(fxm,false);
mstatus=true;
cm=null;
return 1;

// Если меню закрывается и область отсечения меньше 0 
// (признак того, что меню полностью закрылось)
// делаем область = 0
// делаем слой невидимым
// ставим mstatus=true (чтобы при следующем вызове show 
// меню снова открывалось)
// выходим из функции (возвращая 1) 
}

if ((isIE5)||(isIE4)||(isNS4)||(isNS6)) {
 if (!isNS4) {
 fxm.style.left = getPos(fxel,"Left")+"px";
 fxm.style.clip='rect(' + (fxm.offsetHeight-fxrect) + 
' '+ fxm.offsetWidth + ' ' + fxm.offsetHeight +' '+ 0 +')';
 fxm.style.top = getPos(fxel,"Top")+(fxel.offsetHeight-fxm.offsetHeight+fxrect+2)+"px"; 
 } else {
 fxm.left=getPos(fxel,"Left");
 fxm.clip.top=fxm.offsetHeight-fxrect;
 fxm.clip.bottom=fxm.offsetHeight;
 fxm.clip.left=0;
 fxm.clip.right=fxm.offsetWidth;
 fxm.top=getPos(fxel,"Top")+(fxel.offsetHeight-fxm.offsetHeight+fxrect+2); 
 }

// это всё описано вначале данной статьи :)

  if (mstatus) {
  fxrect=fxrect+mstep;
  setTimeout('movefx()',1);
// Если меню открывается,
// прибавляем к высоте области отсечения значение mstep;
// запускаем таймер для повторного выполнения movefx через 1 м.сек.
  } else {
  fxrect=fxrect-mstep;
  setTimeout('movefx()',1);

// Иначе (меню закрывается), отнимаем от высоты области отсечения 
// значение mstep.
  }

 return 1; 
} else {
  if (mstatus) {
  fxm.style.left =getPos(fxel,"Left")+"px";
  fxm.style.top = (getPos(fxel,"Top")+ fxel.offsetHeight) +"px";
   } else {
  switchDiv(fxm,false);
  cm=null;
  mstatus=true;
  }
return 1 
}

}


</Script>

HTML код таблицы - основного меню:

<TABLE WIDTH=450 BORDER=1 onMouseOut="hidemenu(true)" onMouseOver="cancelhide()">
<TR>
<TD width=150 align="center" onMouseOver="show(this,'submenu1')"><a href="">Menu 1</a></TD>
<TD Width=150 align="center" onMouseOver="show(this,'submenu2')"><a href="">Menu 2</a></TD>
<TD width=150 align="center" onMouseOver="show(this,'submenu3')"><a href="">Menu 3</a></TD>
</TR>
</TABLE>

Попробуйте навести курсор на какой-либо пункт данного меню и смотрите, что будет:




Menu 1 Menu 2 Menu 3









Посмотреть пример в отдельном окне

Вы хотите чтобы меню не «ездило», а плавно появлялось? No problem =) Для этого нам придётся переписать всего одну функцию. Функцию movefx(). Теперь она будет выглядеть следующим образом:


function movefx() {


if ((mstatus) && (fxrect>100)) {
fxrect=100;
return 1;
} 



if ((!mstatus) && (fxrect<0)) {
fxrect=0;
switchDiv(fxm,false);
mstatus=true;
cm=null;
return 1;
}

if ((isIE5)||(isIE4)||(isNS6)) {
 fxm.style.top=getPos(fxel,"Top")+(fxel.offsetHeight+2)+'px'; 
 fxm.style.left=getPos(fxel,"Left")+'px';
 if (isNS6) {
 fxm.style.MozOpacity = fxrect/100;
 } else {
 fxm.style.filter = 'alpha(opacity='+fxrect+')';
 }

  if (mstatus) {
  fxrect=fxrect+mstep;
  setTimeout('movefx()',1);
  } else {
  fxrect=fxrect-mstep;
  setTimeout('movefx()',1);
  }

 return 1; 
} else {
  if (mstatus) {
  fxm.style.left =getPos(fxel,"Left")+"px";
  fxm.style.top = (getPos(fxel,"Top")+ fxel.offsetHeight) +"px";
   } else {
  switchDiv(fxm,false);
  cm=null;
  mstatus=true;
  }
return 1 
}


}

Подставив эту функцию вместо приведённой в 1-ом листинге, мы получим вот такую симпатичную менюшку:




Menu 1 Menu 2 Menu 3









Посмотреть пример в отдельном окне

Конечно здесь были рассмотрены далеко не все возможные варианты. Но я уверен, что используя упомянутые приёмы, вам будет по плечу создать любое выпадающее меню. Вы можете также свободно использовать все описанные в этой статье сценарии на своих веб-сайтах, изменять их, только одна просьба, если не жалко, в этом случае разместите ссылку на www.abc-it.lv на какой-нибудь странице вашего сайта! =)

До новых встреч!





Перейти к рубрике --> JavaScript

Наши друзья
Juridiskie pakalpojumi  
IT Works
  Codenet - всё для программиста
   
• Hi-tech NEWS • InCube e-mag
  Программисты, Вам сюда!
КомментарииВсего:1
selevo
[2011-12-23 14:23:02]Спасибо пригодился.
Но заметил что в FireFox не корректно работает
http://izhbazar.ru/index.php
вот пример
Слой не закрывается в нужный момент и менюшки прозрачные.
Что делать !?


Только зарегистрированные пользователи могут оставлять здесь комментарии. Зарегистрироваться можно здесь. Если вы уже зарегистировались ранее, то можете войти в систему здесь.


© Mihail Chernov (MiHack) Обмен ссылками