Добавляем...


Библиотека DHTML-процедур, не зависящих от браузера
Как показывают многие примеры книги, популярные Web-браузеры демонстрируют существенные отличия в области поддержки технологий и стандартов. Для некоторых разработчиков приемлемым оказывается решение, предполагающее разрабом сценариев под конкретный браузер (Internet Explorer) либо стандарт (DOM). Но иногда необходимо обеспечить работу сценария во всех браузерах, способных дать необходимый результат. В данном разделе мы обсудим возможность реализации указанной задачи с помощью создания соответствующей библиотеки процедур, не зависящих от браузера. Предлагаемое ниже решение не является единственно возможным, но оно иллюстрирует общие принципы, используемые при решении таких задач. Для позиционирования и видимости слоя (региона содержимого) необходима поддержка трех различных технологий:
  • фирменные дескрипторы <layer> Netscape 4;
  • коллекции all [ ] Internet Explorer 4+ с позиционируемыми дескрипторами <div>;
  • совместимые с DOM браузеры с позиционируемыми дескрипторами <div>.
С учетом этих простых требований мы можем создать набор процедур JavaScript, изменяющих параметры видимости, а также перемещающих и изменяющих размеры и значение содержимого позиционируемых регионов в большинстве браузеров.
Первое, что необходимо создать для такой библиотеки, это средства идентификации браузера пользователя. Проще всего это сделать на основе анализа об Document. Если обнаруживается коллекция layers [ ], мы заключаем, что браузер поддерживает слои Netscape4. Можно проверить доступность коллекции all [ ] и выяснить, поддерживает ли браузер синтаксис коллекции all [ ] Internet Explorer. Наконец, можно попытаться найти метод getElementById () DOM, чтобы выяснить, имеем ли мы дело с браузером, предлагающим поддержку DOM. Вот как можно установить значения переменных, характеризующих тип браузера, с которми имеем дело:

var layerobject = ((document.layers) ? (true) : (false));
var dom = ((document.getElementById) ? (true) : (false));
var allobject = ((document.all) ? (true) : (false));

Выяснив, с каким типом браузера мы имеем дело, можно определить множество функций для работы со слоями. Мы определяем следующие функции слоя, выполняющие типичные задачи:

function hide(layerName) { }
function show (layerName) { }
function setX(layerName, x) { }
function setY(layerName, y) { }
function setZ (layerName, zlndex) { }
function setHeight(layerName, height) { }
function setWidth(layerName, width) { }
function setClip(layerName, top, right, bottom, left) { }
function setContents ( ) { }

Здесб эти функции являются только заглушками, которые мы вскоре заполним, а сейчас нам понадобится специальная процедура, обеспечивающая для них доступ к позиционируемым элементам по имени, поскольку каждый из подходов имеет свои особенности.

function getElement (layerName, parentLayer)
{
if(layerobject)
{
parentLayer = (parentLayer) ? parentLayer : self;
layerCollection = parentLayer.document.layers;
if(layerCollection[layerName]) return layerCollection[layerName];

/* просмотр вложенных слоев */
for (i=0; і < layerCollection.length;)
return(getElement(layerName, layerCollection[i++]));
}

if (allobject)
return document.all[layerName];
іf (dom)
return document.getElementById(layerName);
}

О6ратите внимание на сложности, возникающие из-за возможности вложения дескрипторов <lауеr> и <div> в Netscape. Нам придется просмотреть вложенные слои рекурсивно, пока мы не найдем нужный объект или пока не закончатся объекты для поиска. Обнаружив позиционируемый элемент, мы можем попытаться изменить его стиль. Например, чтобы скрыть или показать позиционируемый регион, можно использовать

function hide(layerName)
{
var theLayer = getElement (layerName);
(layerobject)
theLayer.visibility = 'hide';
else
theLayer.style.visibility = 'hidden';
}

function show(layerName)
{
var theLayer = getElement(layerName);
if (layerobject)
theLayer.visibility = 'show';
else
theLayer.style.visibility = 'visible';
}


Остальные процедуры имеют аналогичную структуру — для них тоже требуются простые условные операции для выявления объектов, с которыми можно работать в соответствующем браузере.
Конечно, кроме тех проблем, которые мы уже обсудили, имеются и другие. Например, в старых браузерах Opera для установки width и height позиционируемого региона приходится использовать свойства pixelHeight и pixelWidth. Чтобы обнаружить наличие браузера Opera, мы рассматриваем объект Navigator и ищем строку userAgent. Ниже устанавливается логическое значение, указывающее, используется ли браузер Opera, а для этого ищется подстрока "opera" в строке агента пользователя.

opera = (navigator.userAgent.toLowerCase().indexOf('opera') != -1);

Имея возможность выяснить наличие указанного браузера, можно записать следующие, не зависящие от браузера процедуры установки высоты и ширины региона:

/* установка height для слоя с именем layerName */
function setHeight(layerName, height)
{
var theLayer = getElement(layerName);

if (layerobject)
theLayer.clip.height = height;
else if (opera)
theLayer.style.pixelHeight = height;
else
theLayer.style.height = height+"px";
}

/* установка width для слоя с именем layerName */
function setWidth(layerName, width)
{
var theLayer = getElement(layerName);

if (layerobject)
theLayer.clip.width = width;
else if (opera)
theLayer.style.pixelWidth = width;
else
theLayer.style.width = width+"px";
}


Такая же ситуация возникает и в случае позиционирования в Opera, поскольку здесь требуется использовать свойства pixelLeft и pixelTop, а не просто left и top. За справкой обратитесь к полной библиотеке функций позиционирования, и вы увидите, что необходимые в данном случае функции аналогичны тем, которые показаны выше.
Следует также учесть некоторые особенности записи содержимого в слой. В Netscapе 4 для изменения содержимого слоя используются методы типа write () объекта Document. В Internet Explorer и большинстве других браузеров можно использовать зойство innerHTML. Однако в браузерах, обеспечивающих строгое соответствие модели DOM, ситуация несколько сложнее, поскольку там приходится удалить все дочерние объекты региона, а затем воссоздать нужные элементы с помощью вставки. Из-за таких сложностей и вследствие того факта, что большинство поддерживающих ЭОМ браузеров поддерживают и innerHTML, мы предпочли использовать именно innerHTML. "За бортом" оказываются версии Opera, предшествующие Opera 7, но наш программный код построен таким образом, что в соответствующих случаях не выводится никаких сообщений об ошибке, а просто ничего не происходит.

function setContents(layerName, content)
{
var theLayer = getElement(layerName);

if (layerobject)
{
theLayer.document.write(content);
theLayer.document.close();
return;
}

if (theLayer.innerHTML)
theLayer.innerHTML = content;
}

Мы пропустим обсуждение других процедур, поскольку их структура и использование аналогичны уже рассмотренным. Вот полная библиотека процедур слоя:

/* layerlib.js: Пример библиотеки Layer, включающей базовую проверку на совместимость */
/* детектор объектов */
var layerobject = ((document.layers) ? (true) : (false));
var dom = ((document.getElementById) ? (true) : (false));
var allobject = ((document.all) ? (true) : (false));

/* детектор браузеров */
opera=navigator.userAgent.toLowerCase().indexOf('opera')!=-l;

/* возврат объекта для передаваемого значения layerName */
function getElement(layerName,parentLayer)
{

if (layerobject)
{
parentLayer = (parentLayer)? parentLayer : self;
layerCollection = parentLayer.document.layers;
if (layerCollection[layerName])
return layerCollection[layerName];
/* просмотр вложенных слоев */
for(i=0; і < layerCollection.length;)
return(getElement(layerName, layerCollection[i++]))
}

if (allobject) return document.all[layerName];

if (dom) return document.getElementById(layerName);

/* скрыть слой с id = layerName */
function hide(layerName)
{
var theLayer = getElement(layerName);
if (layerobject)
theLayer.visibility = 'hide';
else
theLayer.style.visibility = 'hidden';
}

/* показать слой с id = layerName */
function show(layerName)
{
var theLayer = getElement(layerName);
if (layerobject)
theLayer.visibility = 'show';
else
theLayer.style.visibility = 'visible1;
}

/* установить координату х слоя layerName */
function setX(layerName, x)
{
var theLayer = getElement(layerName);
if (layerobject)
theLayer.left=x;
else if (opera)
theLayer.style.pixelLeft=x;
else
theLayer.style.left=x+"px"; }

/* установить координату у слоя layerName */
function setY(layerName, y)
var theLayer = getElement(layerName);
if (layerobject)
theLayer.top=y;
else if (opera)
theLayer.style.pixelTop=y;
else
theLayer.style.top=y+"px";
}
/* установить значение z-index слоя layerName */
function setZ(layerName, zlndex)
{
var theLayer = getElement(layerName);
if (layerobject)
theLayer.zlndex = zlndex;
else
theLayer.style.zlndex = zlndex;
}
/* установить высоту слоя layerName */
function setHeight(layerName, height)
{
var theLayer = getElement(layerName);
if (layerobject)
theLayer.clip.height = height;
else if (opera)
theLayer.style.pixelHeight = height;
else
theLayer.style.height height+"px";

/* установить ширину слоя layerName */
function setWidth(layerName, width)
{
var theLayer = getElement(layerName);
if (layerobject)
theLayer.clip.width = width;
else if (opera)
theLayer.style.pixelWidth = width;
else
theLayer.style.width = width+"px";
}
/* установить прямоугольник отсечения для слоя layerName с помощью установки значений top, right, bottom и left */
function setClip(layerName, top, right, bottom, left)
{
var theLayer = getElement(layerName);
if (layerobject)
{
theLayer.clip.top = top;
theLayer.clip.right = right;
theLayer.clip.bottom = bottom;
theLayer.clip.left = left;
}
else
theLayer.style.clip = "rect("+top+"px "+right+"px "+" "+bottom+"px "+left+"px )";
}

/* установить содержимое layerName равным переданному содержимому*/
function setContents(layerName, content)
{
var theLayer = getElement(layerName);
if (layerobject)
{
theLayer.document.write(content);
theLayer.document.close();
return;
if (theLayer.innerHTML)
theLayer.innerHTML = content;
}

Можно сохранить эту библиотеку в файле с именем "layerlib.j s", а затем проверить ее работоспособность с помощью следующего документа. Если вы не хотите набирать соответствующий программный код вручную, посетите узел поддержи www.javascriptref.com.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtmll/DTD/xhtmll-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Проверка библиотеки, обеспечивающей cовместимость</title>
<meta http-equiv="content-type" content="text/html; charset=windows-1251" />
<script type="text/javascript" src="layerlib. js"x/script>
</head>
<body>
<div id="regionl" style="position: absolute; top: lOpx; left: ЗООрх; width: lOOpx; height: lOOpx; background-color: #ffff99; z-index: 10; "> Позиционировано!
</div>
<div id="region2" style="position: absolute; top: Юрх; left: 450px; :. 1 width: IQQpx; height: 20Qpx; background-color:#33ff99; z-index: 5;">
Слой с z-index, равным 5, для проверки z-index
</div>

<br /><br /><br /><br /><br /><br />
<hr />
<form name="testform" id="testform" action="#" method="get">
Видимость:
<input type="button" value="показать" onclick="show('regionl');" />
<input type="button" value="скрыть" onclick="hide('regionl');" />

<br /><br />
x: <input type="text" value="300" name="x" id="x" size="4" />
<input type="button" valuer"установить" onclick="setX('regionl5,document.testform.x.value);" />

y: <input type="text" value="10" namely" id="y" size="4" />
<input type="button" value="установить" onclick="setY('regionl',document.testform.y.value);" />

z: <input type="text" value="10" name="z" id="z" size="4" />
<input type="button" value="установить" onclick="setZ('regionl',document.testform,z,value);" />
<br /><br />

Высота: <input type="text" value="100" name="height" id="height" size="4" />
<input type="button" value="установить" onclick="setHeight('regionl',document.testform.height.value);" />

Ширина: <input type="text" value="100".name="width" id="width" size="4" />
<input type="button" value="установить" onclick="setWidthl1regionl1,document.testform,width.value);" />
<br /><br />

Прямоугольник отсечения: <br />
сверху <input type="text" value="0" name="top" id="top" size="4" />
слева <input type="text" value="Q" name="left" id-"left" size="4" />
снизу <input type="text" value="100" name="bottom" id="bottom" size="4" />
справа <input type="text" value="100" name=bright" id="right" size="4" />
<input type="button" value="установить" onclick="setClip('regionl',document.testform.top.value, document.testform.right.value, document.testform.bottom.value, document.testform.left.value);" />
<br /><br />
<input type="text" name="newcontent" id="newcontent" size="40"
vа1ue="Позиционировано!" />
<input type="button" value="установить содержимое"
onclick="setContents('regionlf,document.testform.newcontent.value)/" />
</form>
</body>
</html>

Поэкспериментировав с этим сценарием, вы обнаружите, что в Netscape 4 можно столкнуться с проблемами, если задать на странице позицию слоя так, чтобы он накрывал элементы формы. Можно также обнаружить недостатки данного программного кода, связанные с тем, что размещение элементов страницы нарушается при изменении размеров окна. Первая проблема, вообще говоря, неразрешима, но мы можем решить вторую, добавив в текст примера несколько неуклюжий код, который заставит страницу перезагружаться каждый раз, когда изменяется ее размер. Соответствующий фрагмент программного кода представлен ниже для тех читателей, которые захотят добавить его в библиотеку, чтобы обеспечить разрешение этой специфической только для Netscape 4 проблемы.

/* Перезагрузка окна в Nav 4 для сохранения представления при изменении размеров */
function reloadPage(initialload)
{
if (initialload==true)
{
if ((navigator.appName=="Netscape") &&
(parseInt(navigator.appVersion)==4))
{
/* сохранение ширины страницы для проверки в дальнейшем */
document.pageWidth=window.innerWidth; document.pageHeight=window.innerHeight;

/* установка обработчика изменения размеров */
onresize=reloadPage;
}
}
else if (innerWidth!=document.pageWidth ||
innerHeight1=document.pageHeight)
location.reload();
}

/* немедленный вызов функции для исправления ошибки */
reloadPage(true);

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


добавить комментарий
(без перезагрузки и регистрации)


10 случайных разделов

Что ищем на сайте ?


Примеры кода на сайте







@ 2008-2011 Amber
При использовании материалов ссылка на сайт обязательна
Яндекс.Метрика