Изображения и динамический HTML

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

Объект изображения

Одним из объектов, которые содержатся в документе, является объект изображения. К сожалению, этот объект поддерживается не всеми браузерами, управляющими сценариями. Самыми старыми версиями браузеров, которые еще работают с такими объектами, являются NN3 и IE4. Поэтому все, что будет описано в этой главе, неприменимо, если используются NN2 (все платформы) или IE3 (для Windows). Если так, то можно использовать специально приведенный для этого случая код, который следует разместить в странице, чтобы избежать ошибок при работе со старыми версиями браузеров.

Хотя, если честно, таких старичков в сети осталось совсем мало. И ими, я думаю, можно пренебречь.

Поскольку документ может содержать больше одного изображения, то ссылки на объект изображения для документа в объектной модели представлены в виде массива, включенного в объект document. Поэтому ссылаться на изображения можно либо по индексу в массиве, либо по названию. Более того, индекс массива может быть строковой версией названия изображения. Поэтому все, что написано ниже, является вполне приемлемым способом задания ссылок:

document.images[n]
document.images["имяИзображения"]
document.имяИзображения

Каждый из атрибутов дескриптора <IMG> доступен в JavaScript в качестве свойства объекта изображения. Никаких обработчиков событий, имеющих отношение к действиям мышью, в объектах изображений не задействовано (вплоть до версий IE4+ и NN6+). Если нужно сделать так, чтобы объект реагировал на щелчок кнопкой мыши и при работе в старых версиях браузеров, то его следует заключить в дескриптор ссылки (и задать границу изображения равную нулю) или присоединить к нему клиентскую карту изображений. Комбинация изображения и ссылки является способом, позволяющим сделать изображение графической кнопкой, реагирующей на щелчки мышью (элемент управления формы с изображением не является доступным для сценариев в объектной модели вплоть до браузеров IE4+ и NN6+).

Изменяемые изображения

Преимущество использования управляемых в сценариях объектов изображений заключается в том, что сценарий может изменять изображения, уже занимающие прямоугольную область на странице. В браузерах IЕ4+ и NN6+ можно даже изменять размер таких изображений с выполнением соответствующего обтекания остального содержимого страницы.

Сценарий, стоящий за такими изменениями изображений, достаточно прост. Все, что он делает,- это присваивает свойству src объекта изображения новый адрес URL. Размер изображения на странице регулируется с помощью атрибутов HEIGHT и WIDTH, которые устанавливаются в дескрипторе <IMG> при загрузке страницы. В самом простом случае для каждого изображения используются одинаковые размеры. В браузерах NN3 и NN4 размер изображения на странице изменить нельзя, что приводит к масштабированию изображений, когда они имеют разные размеры.

Предварительная загрузка изображений

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

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

Для того чтобы загрузить изображения, нужно создать в памяти объект этого изображения. Объект изображения, создаваемый в памяти, в некотором отношении отличается от объекта изображения документа, создаваемого с помощью дескрипторов <IMG>. Те объекты, что создаются сценариями и размещаются только в памяти, на странице не отображаются вообще. Но их присутствие в коде документа приводит к тому, что при загрузке страницы эти изображения также будут загружаться. В объектной модели есть функция-конструктор объекта Image, с помощью которой можно в памяти создавать объекты изображений, как показано ниже.

var myImage=new Image(ширина, высота)

Параметрами функции-конструктора является ширина и высота изображения в пикселях, Размеры должны соответствовать настройкам атрибутов WIDTH и HEIGHT в дескрипторе <IMG>. Если только объект изображения существует в памяти, свойству src этого объекта надо присвоить название файла или адреса URL.

myImage.src="someArt.gif"

Если браузер обнаруживает предписание по присвоению адреса URL свойству src объекта, браузер начинает загружать соответствующее изображение в кэш-память. Все, что при этом видит пользователь, -дополнительную информацию о загрузке в строке состояния, как если бы изображение отображалось на странице. К тому времени, когда будет загружена вся страница, сгенерированное таким способом изображения будут занесены в кэш-память. После этого можно свойству изображения документа, созданного с помощью дескрипторов <IMG>, присваивать значения зарезервированных в памяти изображений или реальных изображений с предопределенным URL.

document.images[0].src=myImage.src

Изменяются изображения в документе таким же способом.

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

Листинг 7.1. Предварительное кэширование изображений

<HTML>
<HEAD>
<TITLE>Object</TITLE>
<SCRIPT   LANGUAGE="JavaScriptl.1">
// Педварительное  кэширование четырех изображений
image1=new Image(120,90)
image1.src="deskl.gif"
image2=new  Image (120, 90)
image2.src="desk2.gif"
image3=new  Image(120,90)
image3.src="desk3.gif"
image4=new Image(120,90)
image4.src="desk4.gif"
// Загрузка изображения,   выбранного из  списка  выбора
function loadCached(list)   {
var  img=list.options[list.selectedlndex].value
document.thumbnail.src=eval(img +".src")
</SCRIPT>
</HEAD>
<BODY>
<H2>Image Object</H2>
<IMG SRC="deskl.gif" NAME="thumbnail" HEIGHT=90 WIDTH=120>
<FORM>
<SELECT NAME="cached" onChange="loadCached(this)">
<OPTION VALUE="imagel">Bands
<OPTION VALUE="image2">Clips
<OPTION VALUE="image3">Lamp
<OPTION VALUE="image4">Erasers
</SELECT>
</FORM>
</BODY>
</HTML>

Как только страница загружается, сразу начинают выполняться всевозможные операторы. Эти операторы создают в памяти четыре новых объекта изображения и присваивают свойствам src этих объектов названия соответствующих файлов. Изображения будут загружены в кэш-память при загрузке страницы. Дальше в теле документа с использованием дескриптора <IMG> реализуется представление на странице одного из изображений в качестве начального. Элемент SELECT используется для задания списка с понятными для пользователя названиями рисунков, которые уже загружены в кэш-память. Когда пользователь выбирает один рисунок из предложенного списка, функция loadCached() находит значение выбранного элемента, которое является строковой версией названия объекта изображения. Для преобразования строки названия в ссылку на соответствующий объект используется функция eval() (часть базового языка JavaScript). Поскольку нужно использовать значение свойства src данного объекта, то функция eval() задействована по отношению к строке со ссылкой на свойство src объекта изображения. Свойство src выбранного объекта изображения присваивается свойству src отображаемого изображения на странице, в результате чего на странице незамедлительно будет представлен сохраненный в памяти рисунок.

Создание ролловеров

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

Если несколько подобных кнопок объединены в группу, то удобно организовать такую структуру в памяти в виде массива объектов изображений с соответствующими вариантами их нумерации и именования, необходимыми при управлении массивами. В листинге 7.2 приведен пример упорядочения массива для четырех управляющих кнопок. Приведенный в листинге код используется в рамках приложения, выполняющего подкачку изображений. Это один из наиболее сложных и длинных листингов в учебном курсе, так что он требует некоторых пояснений. Такие пояснения будут приводиться непосредственно по ходу отображения листинга.

Листинг 7.2. Подкачка рисунков

<HTML>
<HEAD>
<TITLE>Jukebox/Image Rollovers</TITLE>
<SCRIPT LANGUAGE="JavaScript">

Только браузеры, работающие с объектами изображений, могут выполнять загрузку изображений в кэш. Поэтому вся соответствующая последовательность находится внутри конструкции if, в условном операторе которой проверяется наличие массива document.images. В браузерах старых версий это значение не может быть определено, что соответствует значению false при проверке условия в блоке if.

if (document.images) {

Загрузка изображений в память начинается с создания двух массивов объектов изображений. В одном массиве хранится информация об изображениях, которые используются для кнопок в неактивном состоянии (off). В другом содержатся изображения активных кнопок (в состоянии on). В этих массивах в качестве индексов вместо целых чисел используются строки. Строковые названия соответствуют тем именам, которые присвоены видимым графическим объектам, чьи дескрипторы приведены в исходном коде ниже. В этом случае код более прост для восприятия. Например, запись offImgArray[ "play"] вполне определенно дает понять, для чего нужен данный элемент. Как можно будет в дальнейшем увидеть из листинга, подкачиваемые изображения не конфликтуют с прочими отображаемыми на странице рисунками (такое возможно, если в ссылке на отображаемые изображения при подкачке используются исключительно числовые индексы).

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

//   Запись   в  память   кэш  всех  неактивных  кнопок
var  offImgArray=new Array()
offImgArray["play"]=new Image(75,33)
offImgArray["stop"]=new  Image(75,33)
offImgArray["pause"]=new  Image(75,33)
offImgArray["rewind"]=new Image(86,33)
// Массив изображений - указывается путь   к неактивному
изображению для  каждой кнопки
offImgArray["play"].src="images/playoff.jpg"
offImgArray["stop"].src="images/stopoff.jpg" 
offlmgArray["pause"].src="images/pauseoff.jpg"
offImgArray["rewind"].src="images/rewindoff.jpg" 
//  Запись  в  память   кэш всех активных, кнопок 
var onImgArray = new Array() 
onImgArray["play"]=new Image(75,33) 
onImgArray["stop"]=new  Image(75,33) 
onImgArray["pause"]=new  Image(75,33) 
onImgArray["rewind"]=new  Image(86,33) 
// Массив изображений - указывается путь  к активному изображению
для каждой  кнопки
onImgArray["play"].src="images/playon.jpg" 
onImgArray["stop"].src="images/stopon.jpg" 
onImgArray["pause"].src="images/pauseon.jpg" 
onImgArray["rewind"].src="images/rewindon.jpg" 
}

Как можно увидеть из следующего фрагмента HTML-кода, когда пользователь наводит указатель мыши на любой из отображаемых графических объектов документа, обработчик события onMouseOver (в объекте документа) вызовет функцию imageOn(), передав ей название конкретного изображения. Функция imageOn() использует это название для синхронизации записей массива document.images (отображаемые изображения) и массива размещенных в памяти изображений активных кнопок onImgArray. Свойство src элементов этого массива присваивается соответствующим свойствам src изображений документа.

//  Функция,   которая выполняет подкачку изображений
function  imageOn(imgName)    { 
 if   (document.images)    {
  document.images[imgName].src=onImgArray[imgName].src
 }
}

To же происходит при использовании обработчика события onMouseOut, который переводит изображение в "выключенное" состояние, для чего использует функцию imageOff() с тем же индексным значением в качестве параметра.

function  imageOff(imgName)    {
 if   (document.images)    {
  document.images[imgName].src=offImgArray[imgName].src;
 }
}

Оба обработчика событий onMouseOver и onMouseOut настраивают строку состояния так, чтобы там не отображались инструкции javascript: URL при наведении пользователем указателя мыши на изображение. В обработчике события onMouseOut сообщение, отображаемое в строке состояния, выставляется равным пустой строке.

function setMsg(msg) {
window.status=msg;
return true; }

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

//  Функции управления   (не  задействованы)
function playIt()    {
}
function  stopIt()    {
}
function  pauseIt()    {
}
function  rewindIt()    {
}
</SCRIPT>
</HEAD>
<BODY>
<CENTER>
<FORM>
Jukebox  Controls<BR>

Каждое изображение находится в окружении объекта ссылки. Так приходится поступать, поскольку у объекта ссылки есть обработчики события, нужные для задания ответной реакции сценария на манипуляции пользователя с мышью, а это позволяет поддерживать совместимость документа с NN3. Каждый обработчик события onMouseOver вызывает функцию imageOn(), передавая при этом название подкачиваемого объекта изображения. Поскольку в обоих обработчиках onMouseOver и onMouseOut необходимо использовать выражение return true, чтобы процесс был запущен, вызов второй функции setMsg() объединен с требованием return true. Функция setMsg() всегда возвращает значение true, а наличие ключевого слова return перед вызовом этой функции обеспечивает нужный результат. Это просто позволяет уменьшить объем используемого кода, вот и все

При введении этого листинга с последующим его использованием следует внимательно следить за тем, чтобы каждый дескриптор <А> вместе с его атрибутами располагался весь в одной строке.

<А HREF="javascript:playIt()"
onMouseOver="iraageOn('play');   return  setMsg('Play the  selected tune')"
on MouseOut="imageOff('play') ;   return setMsg(''")> 
//  Воспроизвести  выбранную мелодию
<IMG  SRC="images/playoff.jpg"  NAME="play"  HEIGHT=33  WIDTH=75 BORDER=0>
<A HREF="javascript:stopIt()"
onMouseOver="imageOn('stop');   return setMsg('Stop  the playing tune')"
on MouseOut="imageOff('stop');   return setMsg(''")>
//  Остановить  воспроизведение мелодии
<IMG  SRC="images/stopoff.jpg"  NAME="stop"   HEIGHT=33  WIDTH=75 BORDER=0>
<A HREF="javascript:pauseIt()"
onMouseOver="imageOn('pause');   return  setMsg('Pause  the playing tune')"
on MouseOut="imageOff('pause');   return  setMsg(''")>
//  Приостановить   воспроизведение мелодии
<IMG  SRC="images/pauseoff.jpg"  NAME="pause"   HEIGHT=33  WIDTH=75 BORDER=0>
<A HREF="javascript:rewindIt()"    .
onMouseOver="imageOn('rewind');   return setMsg('Rewind tune')" 
on MouseOut="imageOff('rewind');   return  setMsg(''")>
//  Перемотка
<IMG  SRC="images/rewindoff.jpg"  NAME="rewind"   HEIGHT=33  WIDTH=86 BORDER=0>
</FORM> </CENTER> </BODY> </HTML>

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

Больше динамизма в HTML

Технология подкачки объектов изображений является только предварительным знакомством с теми наработками, которые на сегодняшний день доступны в динамическом HTML (Dynamic HTML или DHTML). В браузерах IЕ4+ и NN6+ есть возможность вносить изменения в стиль и содержимое элементов HTML. Все содержимое может буквально "выплясывать" на странице.

По той причине, что долгие годы Microsoft и Netscape использовали принципиально разные подходы к развитию объектных моделей документа, только в браузерах IE5 и NN6, благодаря переходу на стандарт W3C DOM, стало возможным использовать один и тот же код сценариев DHTML в обоих типах браузеров. Но даже при этом IE5 и IE5.5 не поддерживают стандарт W3C DOM в той мере, в какой это делает NN6. Если предполагаемая аудитория, на которую рассчитан сценарий, использует в основном IE, то можно задействовать опцию, которая позволяет реализовать объектную модель Microsoft, совместимую с браузерами вплоть до IE4 (если не считать некоторых проблем с совместимостью для IE4 в Macintosh).

Далее в отдельных статьях я ещё затрону проблемы совместимости различных браузеров и способы написания сценариев, которые будут работать везде.

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

Желаю удачи!
Hosted by uCoz