Андрей Новиков
Введение
Internet Exploter 4.0 (IE) и Netscape Communicator 4.0 (NC) по разному интерпретируют
HTML 4.0. Поэтому прежде, чем рассматривать принципы создания Динамических HTML,
рассмотрим основные отличия этих браузеров и как с ними бороться.
Различия в реализации
IE представляет слои с помощью CSS и тэга div, в то время как NC советует использовать
изобретенный им тэг layer.
Например для IE:
<head>
<style type="text/css">
#loading {POSITION: absolute; TOP:0; LEFT:0; Z-INDEX: 80000; WIDTH: 100%; HEIGHT: 100%;}
</style>
</head>
<body>
<div id="loading">
<table width="100%" height="100%">
<tr><td align="center" valign="middle">
Еще немного и из-за поворота выглянет то, к чему Вы так стремились...
</td></tr>
</table>
</div>
</body>
а для NC:
<body>
<layer name="loading" left="0" top="0" z-index="80000" width="100%" height=100%">
<table width="100%" height="100%">
<tr><td align="center" valign="middle">
Еще немного и из-за поворота выглянет то, к чему Вы так стремились...
</td></tr>
</table>
</layer>
</body>
Тэг layer ничем не отличается от CSS, за исключением параметра source, с помощью
которого можно указать внешний файл в котором хранится содержимое слоя. Если Вы
не собираетесь поддерживать IE, лучше выбрать синтаксис NC. Это позволит строить
сложные документы и не повторять во всех файлах стандартные слои, такие как
навигационнфя панель или шапка страницы.
Более подробно синтаксис слоев мы рассмотрим в других уроках, а пока можно
обратиться к рассыльному.
На этом проблемы совместимости не заканчиваются, а только начинаются.
Классы JavaScript в IE и NC также реализованны по разному. Например,
чтобы спрятать слой в NC надо сказать:
document.layers["loading"].visibility="visible";
а в IE:
document.all["loading"].style.visibility="visible";
Наш урок носит обзорный характер, поэтому мы не будем подробно рассматривать все
различия реализации языка. Посмотрим лучше, как решаются эти проблемы.
Как с ними бороться
Слава Netscape, в JavaScript есть пракрасная функция eval(). Она
параметр в строку и интерпретирует ее так, как-будто это строка программы.
Чтобы корректно спрятать слой как в IE, так и в NC необходимо написать
следующую строку:
eval(layerRef+'["loading"]'+styleSwitch+'.visibility="visible"');
Теперь все, что остается, это правильно инициализовать переменные layerRef и
styleSwitch с помощью следующего кода:
var layerRef="null", styleSwitch="null";
function init(){
if (navigator.appName == "Netscape") {
layerRef="document.layers";
styleSwitch="";
}else{
layerRef="document.all";
styleSwitch=".style";
}
}
вызвав его в тэге body:
<body onload="init();">
Прятание и показывание слоя
Теперь давайте для разминки напишем код, который прячет указанный нами слой.
Создадим функцию hideLayer с параметром, содержащим имя слоя, несколько
изменив приведенный выше eval(...):
function hideLayer(layerName){
eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.visibility="hidden"');
}
По аналогии с ней создается и функция showLayer:
function showLayer(layerName){
eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.visibility="visible"');
}
Пример. Предзагрузка изображений для правильного их показа.
Создадим два слоя. Уже извесное нам сообщение о загрузке (им может быть
какая-нибудь новость или цитата)
<style type="text/css">
#loading {POSITION: absolute; TOP:0; LEFT:0; Z-INDEX: 80000; WIDTH: 100%; HEIGHT: 100%;}
</style>
<div id="loading">
<table width="100%" height="100%">
<tr><td align="center" valign="middle">
Подождите пожалуйста...
</td></tr>
</table>
</div>
и невидимый рабочий слой
<style type="text/css">
#logo {POSITION: absolute; TOP:50; LEFT:150; VISIBILITY: hidden; Z-INDEX: 84000; WIDTH: 360px; HEIGHT: 280px;}
</style>
<div id="logo">
<img src="../images/biglogo.gif" width=359 height=279 border=0>
</div>
Теперь в тэге body вызовем функцию прятания слоя loading и показа слоя logo
<body onload="init();hideLayer('loading');showLayer('logo');">
Работающий вариант (Необходим IE 4 или NC 4)
Движение слоя по окну
Для примера рассмотрим движение сверху вниз. Затем по аналогии Вы сможете
организовывать перемещение в других направлениях или по более сложным
траекториям. Для того, чтобы осуществить перемещение нужно знать четыре
значения: текущее положение, место остановки, шаг перемещения, время задержки.
Мы ограничимся двумя переменными, а шаг и задержку зададим константами.
Создадим функцию перемещения
function moveLayerDown(layerName,currTop,topstop)
В ней сначала проверим, не достиг ли слой конечной точки
if (eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.top != topstop'))
если это не произошло, сдвинем слой вниз
currTop+=2;
eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.top = currTop');
и рекурсивно вызовем функцию
setTimeout('moveLayerDown("'+layerName+'",'+currTop+','+topstop+')',50);
Вот, что у нас получилось:
function moveLayerDown(layerName,currTop,topstop){
if (eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.top != topstop')){
currTop+=2;
eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.top = currTop');
setTimeout('moveLayerDown("'+layerName+'",'+currTop+','+topstop+')',50);
}
}
Работающий вариант (Необходим IE 4 или NC 4)
Свертывание и развертывание слоя
Рассмотрим более сложную операцию - свертывание и развертывание слоя. Будем
выполнять ее по горизонтали. По вертикали эта операция выполняется аналогично.
Для ее выполнения нам нужно знать ширину слоя. Если мы хотим свернуть слой,
никаких предварительных действий предпринимать не надо, но если мы хотим
его развернуть, то нужно установить область обреза с левым и правым краями,
равными половине ширины слоя. Это можно установить при определении слоя, или
в начале программы JavaScript. При этом надо не забыть предварительно спрятать
слой для устранения мелькания.
Создадим функцию свертки/развертки:
function curtainWidth(layerName,xinc,inctime,stopwidth)
второй параметр определяет величину прироста/уменьшения ширины, третий -
задержку, а четвертый - конечную ширину. Если мы развертываем слой, то
конечная ширина должна быть равна ширине слоя, если свертываем, то нулю.
Первым делом изменим левый и правый край области обреза:
eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.clip.left += -(xinc/2)');
eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.clip.right += (xinc/2)');
Если мы перестарались, то подправим ширину обреза:
if (eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.clip.width < 0')){lyr.clip.width = 0}
Теперь проверим, не достигли ли мы конечного условия:
if (((xinc < 0) && (eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.clip.width > stopwidth'))) ||
((xinc > 0) && (eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.clip.width < stopwidth'))))
Если нет, то рекурсивно вызовем функцию:
setTimeout('curtainWidth("'+layerName+'",'+xinc+','+inctime+','+stopwidth+')',inctime);
Вот, что у нас получилось:
function curtainWidth(layerName,xinc,inctime,stopwidth) {
eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.clip.left += -(xinc/2)');
eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.clip.right += (xinc/2)');
if (eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.clip.width < 0')){lyr.clip.width = 0}
if (((xinc < 0) && (eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.clip.width > stopwidth'))) ||
((xinc > 0) && (eval(layerRef+'["'+layerName+'"]'+styleSwitch+'.clip.width < stopwidth')))) {
setTimeout('curtainWidth("'+layerName+'",'+xinc+','+inctime+','+stopwidth+')',inctime);
}
}
Работающий вариант (Необходим IE 4 или NC 4)
Заключение
Мы только-что рассмотрели три простых операции над слоями. Продумав дизайн и
немного усложнив функции, можно с помощью этих операций добиться потрясающего
эфекта на ваших страницах.
|