Управляем загрузкой изображений. Объекты JavaScript Размещение кода на HTML-странице

От автора: Похоже, что загрузка изображений либо полностью упускается из вида, либо поручается излишне большим плагинам. Красивая, гладкая и быстрая загрузка сайта – важнейшая часть хорошего пользовательского впечатления, а также – элементарная вежливость по отношению к вашему дизайнеру. Кому хочется каждый раз при входе на страницу видеть свой дизайн испорченным медленной построчной загрузкой изображений?

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

Каждый раз при виде медленно загрузки изображения я вспоминаю эту классическую сцену с парнем из комикса.

1. Загрузка каждого изображения в отдельности (Single-Asset)

Это методика, которую можно применить к любому или ко всем изображениям своего сайта для предотвращения (или хотя бы скрытия) традиционной построчной загрузки базовых JPG’ов. Мы начнем с упаковки каждого изображения в div с классом img_wrapper:

< div class = "img_wrapper" >

< img src = "comicbookguy.jpg" alt = "" / >

< / div >

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

Для этого примера ограничим свое изображение коэффициентом пропорциональности 4:3 – очень важно для адаптивных сайтов. Обратите внимание, что мы также скрыли изображение с помощью opacity: 0;, что дает нам возможность управлять тем, как и когда мы его увидим при наступлении нужного момента.

Img_wrapper{ position: relative; padding-top: 75%; overflow: hidden; } .img_wrapper img{ position: absolute; top: 0; width: 100%; opacity: 0; }

Img_wrapper {

position : relative ;

padding - top : 75 % ;

overflow : hidden ;

Img_wrapper img {

position : absolute ;

top : 0 ;

width : 100 % ;

opacity : 0 ;

Каждая картинка в DOM запускает событие load, когда все его данные загружены с сервера, а само изображение отображено браузером. Чтобы захватить и привязать это событие, нам понадобится использовать JavaScript. Я начну с добавления атрибута onload к тэгу изображения.

< div >

< img src = "comicbookguy.jpg" alt = "" onload = "imgLoaded(this)" / >

< / div >

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

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

Альтернативой этому является индивидуальная привязка события load к каждому изображению в document ready. Однако проблема возникает, когда изображения загружаются прежде запуска document ready, и до того, как у нас появляется возможность привязать функциональность к событию загрузки каждого изображения. Отдельная проблема, когда изображения уже кэшированы браузером с предыдущей сессии, и загружаются мгновенно. Мы пропускаем событие, а наша функция не вызывается. У атрибута onload отсутствуют такие проблемы, потому что он, так сказать «предварительно привязан» к событию и поэтому обрабатывается, когда браузер анализирует HTML.

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

При добавленном атрибуте onload в момент загрузки изображения будет вызываться функция imgLoaded(). Ее нужно поместить в файл javascript в head самой страницы (после jQuery, если вы его применяете в своей функции, и после любых остальных плагинов) с тем, чтобы она компилировалась до парсинга body и загрузки изображений. Если вставить функцию внизу страницы, высока вероятность того, что изображения станут грузиться до определения функции.

С помощью ключевого слова this мы можем послать необработанный объект DOM изображения в свою функцию JavaScript в качестве аргумента:

function imgLoaded(img){ var $img = $(img); $img.parent().addClass("loaded"); };

function imgLoaded (img ) {

var $ img = $ (img ) ;

$ img . parent () . addClass ("loaded" ) ;

Или простым JavaScript’ом:

function imgLoaded(img){ var imgWrapper = img.parentNode; imgWrapper.className += imgWrapper.className ? " loaded" : "loaded"; };

function imgLoaded (img ) {

var imgWrapper = img . parentNode ;

imgWrapper . className += imgWrapper . className ? " loaded" : "loaded" ;

С помощью javascriptа можно быстро пройти по DOM на один уровень вверх и добавить к содержащему элементу упаковщика класс loaded. Я уверен, вы согласитесь с тем, что это удивительно элегантное решение. Выборочно назначив этому классу стили, можно теперь показать свое загруженное изображение, установив его непрозрачность на 1:

Img_wrapper.loaded img{ opacity: 1; }

Img_wrapper . loaded img {

opacity : 1 ;

Чтобы процесс происходил гладко, мы добавим к img несколько переходов CSS3 и добьемся при загрузке своего изображения эффекта «постепенного проявления».

Img_wrapper img{ position: absolute; top: 0; width: 100%; opacity: 0; -webkit-transition: opacity 150ms; -moz-transition: opacity 150ms; -ms-transition: opacity 150ms; transition: opacity 150ms; }

Img_wrapper img {

position : absolute ;

top : 0 ;

width : 100 % ;

opacity : 0 ;

Webkit - transition : opacity 150ms ;

Moz - transition : opacity 150ms ;

Ms - transition : opacity 150ms ;

transition : opacity 150ms ;

Смотрите работающий пример на codepen.io, включающий альтернативную версию с отображением спиннера загрузки.

Прогрессивные JPGи

В качестве примечания к этой технике и в ответ на некоторые полученные мною к этой статье отзывы, определенно стоит упомянуть «прогрессивные» JPG’и. Это еще одна давняя методика родом из 1990-х, затрагивающая сохранение JPG’ов как «прогрессивных», а не «обычных» с целью предотвращения построчной загрузки – а вместо нее покадрово прорисовывая изображения одной высоты по мере его загрузки. Основное преимущество этого приема состоит в том, что он предотвращает «скачки» прибывающего контента по странице при загрузке изображений.

Раздражают ли такие эффекты, как спиннеры загрузки и постепенное проявление – это дело личного вкуса, но в основном прием с упаковывающим div’ом решает эти проблемы с помощью минимума CSS и JavaScript’а .

В применении техники упаковывающего div’а лучше всего то, что можно не волноваться по поводу изменения высоты изображений по мере их загрузки, а также не нужно обрекать своих пользователей на уродливое объединение пикселей в группы, что, по моему мнению, может для пользователя оказаться настолько же раздражительным, как и обычная загрузка. К тому же она ничего не стоит – процесс повторного отображения рисунка по нескольку раз на самом деле создает дополнительную нагрузку на маломощные мобильные устройства. Раздражают ли такие эффекты, как спиннеры загрузки и постепенное проявление – это дело личного вкуса, но в основном прием с упаковывающим div’ом решает эти проблемы с помощью минимума CSS и JavaScript’а, и отсутствует необходимость полагаться на пользователя (в ситуации с CMS) при сохранении JPG’ов определенным способом.

2. Пакетная загрузка нескольких изображений

Вышеописанная техника очень хороша для отдельных изображений, но как быть, если у нас есть подборка изображений, которые нужно отобразить в «карусели» или слайдшоу, или если мы пользуемся плагином разметки вроде Masonry? Обычная ошибка при использовании плагинов «карусели»/слайдера – их обработка при document ready, зачастую до загрузки всех их изображений. Это может вызвать переход слайдшоу к пустому, еще не загрузившемуся изображению, особенно если мы имеем дело с фотографиями с высоким разрешением и большим размером файла.

Для предупреждения этого явления нужно подвергать обработке предпочитаемый вами плагин только тогда, кoгда все необходимые изображения уже загрузились. Применив вариацию вышеприведенной техники, мы снова добавим атрибут onload ко всем изображениям своего слайдшоу:

NB: Нижеприведенная разметка приводится только как упрощенный примерный вариант разметки плагина слайдшоу, и должна быть адаптирована в соответствии с вашими требованиями.

< div id = "Slideshow" >

< img src = "slide_1.jpg" alt = "" onload = "slideLoaded(this)" / >

< img src = "slide_2.jpg" alt = "" onload = "slideLoaded(this)" / >

< img src = "slide_3.jpg" alt = "" onload = "slideLoaded(this)" / >

< / div >

В JavaScript’е мы применим функцию slideLoaded() для отслеживания процесса загрузки изображений, и подвергнем свой плагин обработке, когда готов:

function slideLoaded(img){ var $img = $(img), $slideWrapper = $img.parent(), total = $slideWrapper.find("img").length, percentLoaded = null; $img.addClass("loaded"); var loaded = $slideWrapper.find(".loaded").length; if(loaded == total){ percentLoaded = 100; // ИНИЦИАЛИЗИРУЙТЕ ПЛАГИН $slideWrapper.easyFader(); } else { // ОТСЛЕДИТЕ ПРОЦЕСС percentLoaded = loaded/total * 100; }; };

function slideLoaded (img ) {

var $ img = $ (img ) ,

$ slideWrapper = $ img . parent () ,

total = $ slideWrapper . find ("img" ) . length ,

percentLoaded = null ;

$ img . addClass ("loaded" ) ;

var loaded = $ slideWrapper . find (".loaded" ) . length ;

if (loaded == total ) {

percentLoaded = 100 ;

// ИНИЦИАЛИЗИРУЙТЕ ПЛАГИН

$ slideWrapper . easyFader () ;

} else {

// ОТСЛЕДИТЕ ПРОЦЕСС

percentLoaded = loaded / total * 100 ;

Каждый раз при загрузке материала мы добавляем к нему класс loaded для слежения за его прогрессом.
С помощью последнего if мы инициализируем плагин (в данном случае jQuery EasyFader), когда количество изображений с классом loaded равно общему количеству изображений в контейнере. В качестве дополнительного свойства можно разделить переменную loaded на переменную total и использовать ее для визуализации прогресса для пользователей: путем либо отображения процентного соотношения, либо используя ее для управления шириной индикатора выполнения, или другим подобным образом.

И снова, этот скрипт должен быть помещен в head вашего документа, после jQuery и того плагина, который вы будете подвергать обработке, когда готов.

3. Предварительное кэширование изображений для быстродействия

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

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

var heroArray = [ "/uploads/hero_about.jpg", "/uploads/hero_history.jpg", "/uploads/hero_contact.jpg", "/uploads/hero_services.jpg" ]

var heroArray = [

"/uploads/hero_about.jpg" ,

"/uploads/hero_history.jpg" ,

"/uploads/hero_contact.jpg" ,

"/uploads/hero_services.jpg"

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

Когда пользователь зайдет на домашнюю страницы моего сайта, я дождусь ее полной загрузки, перед тем, как что-то делать, чтобы убедиться, что я не прерываю загрузку контента самой страницы, добавляя сторонюю загрузку. Для этого, я прикреплю функциональность JavaScript’а к событию window load, запускающемуся только когда весь контент страницы уже загружен и отображен (включая изображения), в отличие от события document ready, которое запускается, как только готов DOM:

function preCacheHeros(){ $.each(heroArray, function(){ var img = new Image(); img.src = this; }); }; $(window).load(function(){ preCacheHeros(); });

function preCacheHeros () {

$ . each (heroArray , function () {

var img = new Image () ;

img . src = this ;

} ) ;

$ (window ) . load (function () {

preCacheHeros () ;

} ) ;

Или простым JavaScript’ом:

function preCacheHeros(){ for(i = 0; i < heroArray.length; i++){ var url = heroArray[i], img = new Image(); img.src = url; }; }; window.onload = preCacheHeros();

function preCacheHeros () {

for (i = 0 ; i < heroArray . length ; i ++ ) {

var url = heroArray [ i ] ,

img = new Image () ;

img . src = url ;

window . onload = preCacheHeros () ;

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

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

Имеет смысл рассмотреть аналитику вашего сайта до внедрения предварительного кэширования

Прекогнитивное предварительное кэширование

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

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

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

Возможно, звучит несколько фантастично, но вы удивитесь тому, насколько точно можно предсказать поток посетителей

4. «Ленивая» загрузка изображения для снижения нагрузки на сервер

Понятие lazy-loading относится к изображениям, загружаемым программным путем после специального события, чтобы запретить браузеру запрашивать и отображать все изображения на странице как только документ загружается.

В основном применяется в длинных или перегруженных изображениями страницах. На целевой странице блога Barrel мы сочетаем «ленивую» загрузку с плагином MixItUp для того, чтобы гарантировать, что изображения, отсутствующие в текущем фильтре или странице, не станут загружаться без особой в том нужды, пока этот элемент не станет видимым. Любые изображения, подлежащие «ленивой» загрузке, мы снова обернем в div с классом img_wrapper, которому в свою очередь зададим класс lazy_load для того, чтобы можно было легко их выбрать с помощью jQuery:

) . load (function () {

lazyLoad () ;

Вышеприведенная функция «лениво» загружает все изображения после запуска события window load, но код внутри цикла.each() можно адаптировать так, чтобы он подходил к множеству ситуаций. Очень распространенное его применение – прикрепить к событию window scroll и «лениво» загружать изображения по мере их прокрутки до окна просмотра.

Вперед, к загрузке изображений

В процессе экспериментирования с парой этих методик над множеством проектов в течение последних примерно 12 месяцев мне пришлось по-настоящему сократить и отточить их для применения в недавно переделанном проекте barrelny.com (выпущенном обратно в свет в апреле), где я применял сочетание всех четырех методов для того, чтобы обеспечить грациозную загрузку изображений, пытаясь при этом выжать каждую унцию производительности из экстремально перегруженного фотографиями и изображениями вебсайта. Путем комбинирования предварительного кэширования и «ленивой» загрузки с загрузкой страниц при помощи AJAX, слайдшоу и постраничной разбивкой на стороне клиента мы смогли создать отличное впечатление гладкости и всего сайта.

Пытаясь сделать выжимку из этих приемов для презентации команды разработчиков Barrel, я был приятно удивлен тем, насколько легковесны все эти методики на бумаге – обычно 5-10 строк кода в jQuery – и как легко их внедрить в любой проект. Кроме того, каждуя из них можно написать простым JavaScript’ом без лишних хлопот и дополнительного кода, но если вы пользуетесь jQuery, как это часто делаем мы, определенно следует воспользоваться преимуществами его надежных методик прохода DOM.

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

каскадными таблицами стилей .

Таким образом, инструментарий работы с представлением веб – документа нам предоставляет CSS .

Осталось пояснить вопрос с поведением веб–страницы. Прежде всего необходимо понять, что скрывается за термином "поведение".

Поведение веб страницы это то, как она будет реагировать на активность пользователя . Также можно сказать, что поведение веб–страницы – это ряд правил, по которым она взаимодействует с пользователем.

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

То есть никто изначально не закладывал в HTML поддержку интерактивного взаимодействия с пользователем. Попросту никто не мог и предположить, какое развитие получит глобальная паутина в дальнейшем.

При помощи HTML и CSS можно создавать прекрасно оформленные и грамотно структурированные, но не интерактивные сайты. Конечно, существует ряд сайтов, прекрасно обходящихся без какого – либо "сложного" взаимодействия с пользователем. Но следует помнить, что единственным неоспоримым на данный момент показателем успешности сайта является число его посетителей.

Поэтому хорошим тоном стало "обрастание" сайтов форумами, блогами , возможностями взаимодействия со сторонними сервисами и т.д. А в этом деле без интерактивности уже далеко не уйти.

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

Веб – сценарии

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

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

Выходом из ситуации стали веб – сценарии – программы написанные на "обычных" языках программирования и внедренные непосредственно в HTML – код страницы.

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

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

Для поддержки языка сценариев используется так называемый интерпретатор (или виртуальная машина ) языка. Web -обозреватель выделяет сценарии из HTML -кода страницы и передает его на выполнение интерпретатору . Последний анализирует код сценариев, расшифровывает их и выполняет, передавая результат выполнения обратно Web -обозревателю.

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

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

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

JavaScript

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

Сам JavaScript был разработан Брендоном Айхом (на тот момент сотрудником компании Netscape ). Собственно, о самом процессе работы над JavaScript ходят чуть ли не легенды, поскольку сроки были очень и очень сжатыми, нужен был результат. Это объясняет ряд все еще существующих в языке ошибок. Подробнее об этом можно прочитать в указанных материалах для самостоятельного изучения.

Предпосылкой появления JavaScript стало желание дать разработчикам HTML -документов возможность динамически управлять всеми объектами, описываемыми в веб-страницах. Изначально язык был включён в браузер Netscape Navigator , начиная с версии 2.0B3 в декабре 1995 года. Первоначально язык назывался Mocha, затем был переименован в LiveScript. На синтаксис JavaScript оказали влияние такие языки, как C и Java , и поскольку технология Java была в то время очень модной, LiveScript переименовали в JavaScript , получив соответствующую лицензию от Sun Microsystems , Inc.

Реализация компании Microsoft получила название JScript . Internet Explorer , начиная с версии 3.0, выпущенной в августе 1996 года, поддерживает JScript . Стандартизация языка ассоциацией ECMA иниицирована компанией Netscape . Стандартизированная версия имеет название ECMAScript , описывается стандартом ECMA-262 .

Web -обозреватель, работающий на компьютере-клиенте, обеспечивает среду, в которой JavaScript имеет доступ к объектам, которые представляют собой окна, меню , диалоги, текстовые области, фреймы , cookies(куки) и ввод-вывод в Web -страницу. Кроме того, обозреватель позволяет присоединить сценарии на языке и выгрузка страниц и графических образов, нажатие клавиш и движение мыши, выбор текста и пересылка форм. При этом программный код сценариев только реагирует на события и поэтому не нуждается в главной программе. Набор объектов, предоставляемых обозревателем, известен под названием Document Object Model ( DOM ).

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

Мы уже затрагивали эту тему. Сейчас поговорим об этом более подробно. В языке JavaScript все элементы на web-странице выстраиваются в иерархическую структуру. Каждый элемент представляется в виде объекта. И каждый такой объект может иметь определенные свойства и методы.

Предположим, у нас есть вот такая web-страница:

Ее html-код: Иерархия объектов, создаваемая этой html-страницей, выглядит так:

Каждый объект этой структуры имеет свое имя и индекс. Индекс определяется положением объекта на странице (сверху вниз). Поэтому картинка, которая расположена выше на странице имеет меньший номер. Нумерация начинается с 0. Объект forms имеет свойство-массив - elements , в котором содержатся ссылки на элементы формы в порядке их перечисления в теге form . Их нумерация также начинается с 0. У объектов формы могут быть свои подчиненные объекты. В нашем примере у объекта elements , который является списком, это пункты списка, которые имеют свою внутреннюю нумерацию.

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

Document.images

Путь к форме:

Путь к списку:

Document.forms.elements

А путь к третьему пункту списка:

Document.forms.elements

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

Например, наша форма имеет имя forma1, а первое текстовое поле - имя name. Тогда, чтобы получить к нему доступ, мы должны написать:

Document.forma1.name

Чтобы узнать, что пользователь ввел в это текстовое поле, используется свойство value :

Document.forma1.name.value

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

Function prov(){ var a=document.forma1.elements.value; var b=document.forma1.elements.value; if (a==b){ alert ("Вы зарегистрированы!"); } else { alert ("Введите правильный пароль."); } }

Пусть эта функция срабатывает при нажатии на кнопку "Отправить":

... ... ... ... ... ...

Чтобы узнать, какой пол указал пользователь, используется свойство переключателей checked . А для определения выбранного пользователем пункта из списка - свойство selected .

Предположим, мы хотим, чтобы в зависимости от выбранных пола и увлечения, пользователю выдавалось какое-либо сообщение. Перепишем функцию prov():

function prov(){ if (document.forma1.elements.checked && document.forma1.elements.selected){ alert ("Мужчина, который любит животных заслуживает уважения."); } else if (document.forma1.elements.checked && document.forma1.elements.selected) { alert ("Женщина за рулем всегда вызывает интерес."); } else { alert ("Отличное увлечение."); } }

* && - логическое И, было рассмотрено в уроке 1 * В JavaScript много объектов. Чтобы выяснить, какое из свойств и методов объекта позволяет получить доступ к нужной информации, необходимо обратиться к какому-либо справочнику по JavaScript, найти в нем нужный объект и посмотреть его свойства и методы. Целью же этого урока было показать на примере, как обратиться к объекту страницы и использовать информацию введенную пользователем.

Для работы с изображениями в JavaScript используется объект Image . Данный объект является очередным свойством объекта Document . И о том, как управлять изображениями через JavaScript , Вы узнаете из этой статьи.

Конструктор у объекта Image практически не используется (да и он классический). Методы у него присутсвуют (наследуются от объекта Object ), но ничего интересного из себя не представляют. Поэтому в этой статье мы разберём самое важное в объекте Image - его свойства .

Прежде чем начать обрабатывать изображение необходимо его создать. Разумеется, создание происходит в HTML , поэтому знакомый Вам тег:

Теперь мы можем обратиться к этому объекту через JavaScript :

Document.write(document.img)

Как видите, обращение к объекту Image очень простое: сначала пишится объект Document , а затем его свойство с именем объекта Image (это имя мы задали в атрибуте "name "). В результате выполнения этого скрипта Вы увидите: " ". Это сработал метод toString() , но, впрочем, забудьте, что я сейчас написал - это тема будущих статей.

ВНИМАНИЕ: Необходимо соблюдать очень важное правило: нельзя обращаться к тому, чего ещё не существует . Какой вывод из этого можно сделать? Очень простой: пока не создано изображение, его нельзя обрабатывать. То есть Вы не можете запустить приведённый здесь скрипт ДО того, как появилось изображение. На это очень часто напарываются новички, поэтому не забывайте, что прежде чем работать с чем-либо, необходимо для начала это создать.

Теперь переходим к свойствам. Начнём со свойства border . Данное свойство отвечает за размер рамки вокруг изображения. Разумеется, мы его можем и прочитать, и записать. Давайте изменим размер рамки нашего изображения:

Document.img.border = 5;

Разумеется, есть два свойства, отвечающие за ширину и высоту изображения. Это свойства width и height объекта JavaScript . Давайте их выведем:

Document.write("Ширина изображения - " + document.img.width + "
");
document.write("Высота изображения - " + document.img.height);

И последнее свойство, которое мы рассмотрим - это src . Данное свойство отвечает за путь к картинке. И давайте с Вами решим такую задачу: есть картинка и есть кнопка. При нажатии на кнопку картинка меняется.


var flag = 0;
function changeImage() {
if (flag == 0) {
document.img.src = "image1.jpg";
flag = 1;
}
else {
document.img.src = "image2.jpg";
flag = 0;
}
}




Теперь поясню, как работает данный скрипт. Сначала мы описываем саму функцию. Создаётся переменная flag . Это некий флаг, который переключается при смене изображения. Дальше идёт функция changeImage() , которая и занимается сменой изображения. Изображению присваивается тот путь к картинке, которому соответствует флаг. После смены изображения меняется и значение флага (чтобы в следующий раз было другое изображение). За пределами скрипта создаётся форма с одной кнопкой. Здесь обратите внимание на атрибут "onClick ". Этот атрибут отвечает за обработку события "Клик мыши по кнопке ". О событиях мы поговорим отдельно, но здесь достаточно понять принцип. В значении атрибута "onClick " стоит функция, которую надо выполнить при нажатии на кнопку. Таким образом, у нас и меняется изображение. Надеюсь, что понятно объяснил.

Остальные свойства объекта Image в JavaScript используется достаточно редко, поэтому я их опустил. А самое важное я Вам поведал. В следующей статье мы перейдём к следующему свойству объекта Document - объект Link .

Изображения на web-странице

Рассмотрим теперь объект Image, который стал доступен, начиная с версии с 1.1 языка JavaScript (то есть с Netscape Navigator 3.0). С помощью объекта Image Вы можете вносить изменения в графические образы, присутствующие на web-странице. В частности, это позволяет нам создавать мультипликацию.
Заметим, что пользователи браузеров более старых версий (таких как Netscape Navigator 2.0 или Microsoft Internet Explorer 3.0 - т.е. использующих версию 1.0 языка JavaScript) не смогут запускать скрипты, приведенные в этой части описания. Или, в лучшем случае, на них нельзя будет получить полный эффект.
Давайте сначала рассмотрим, как из JavaScript можно адресоваться к изображениям, представленным на web-странице. В рассматриваемом языке все изображения предстают в виде массива. Массив этот называется images и является свойством объекта document. Каждое изображение на web-странице получает порядковый номер: первое изображение получает номер 0, второе - номер 1 и т.д. Таким образом, к первому изображению мы можем адресоваться записав document.images.
Каждое изображение в HTML-документе рассматривается в качестве объекта Image. Объект Image имеет определенные свойства, к которым и можно обращаться из языка JavaScript. Например, Вы можете определить, который размер имеет изображение, обратившись к его свойствам width и height . То есть по записи document.images.width Вы можете определить ширину первого изображения на web-странице (в пикселах).
К сожалению, отслеживать индекс всех изображений может оказаться затруднительным, особенно если на одной странице у Вас их довольно много. Эта проблема решается назначением изображениям своих собственных имен. Так, если Вы заводите изображение с помощью тэга

то Вы сможете обращаться к нему, написав document.myImage или document.images["myImage"] .

Хотя конечно и хорошо знать, как можно получить размер изображения на web-странице, это не совсем то, чего бы мы хотели. Мы хотим осуществлять смену изображений на web-странице и для этого нам понадобится атрибут src . Как и в случае тэга , атрибут src содержит адрес представленного изображения. Теперь - в языке JavaScript 1.1 - Вы имеете возможность назначать новый адрес изображению, уже загруженному в web-страницу. И в результате, изображение будет загружено с этого нового адреса, заменив на web-странице старое. Рассмотрим к примеру запись:

Здесь загружается изображение img1.gif и получает имя myImage . В следующей строке прежнее изображение img1.gif заменяется уже на новое - img2.gif :

document.myImage.src= "img2.src";

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

Один из недостатков такого подхода может заключаться в том, что после записи в src нового адреса начинает процесс загрузки соответствующего изображения. И поскольку этого не было сделано заранее, то еще пройдет некоторое время, прежде чем новое изображение будет передано через Интернет и встанет на свое место. В некоторых ситуациях это допустимо, однако часто подобные задержки неприемлемы. И что же мы можем сделать с этим? Конечно, решением проблемы была бы упреждающая загрузка изображения. Для этого мы должны создать новый объект Image. Рассмотрим следующие строки:

HiddenImg= new Image(); hiddenImg.src= "img3.gif"; В первой строке создается новый объект Image. Во второй строке указывается адрес изображения, которое в дальнейшем будет представлено с помощью объекта hiddenImg . Как мы уже видели, запись нового адреса в атрибуте src заставляет браузер загружать изображение с указанного адреса. Поэтому, когда выполняется вторая строка нашего примера, начинает загружаться изображение img2.gif . Но как подразумевается самим названием hiddenImg ("скрытая картинка"), после того, как браузер закончит загрузку, изображение на экране не появится. Оно будет лишь будет сохранено в памяти компьютера (или точнее в кэше) для последующего использования. Чтобы вызвать изображение на экран, мы можем воспользоваться строкой:

document.myImage.src= hiddenImg.src;

Но теперь изображение уже немедленно извлекается из кэша и показывается на экране. Таким образом, сейчас мы управляли упреждающей загрузкой изображения.
Конечно браузер должен был к моменту запроса закончить упреждающую загрузку, чтобы необходимое изображение было показано без задержки. Поэтому, если Вы должны предварительно загрузить большое количество изображений, то может иметь место задержка, поскольку браузер будет занят загрузкой всех картинок. Вы всегда должны учитывать скорость связи с Интернет - загрузка изображений не станет быстрее, если пользоваться только что показанными командами. Мы лишь пытаемся чуть раньше загрузить изображение - поэтому и пользователь может увидеть их раньше. В результате и весь процесс пройдет более гладко.
Если у Вас есть быстрая связь с Интернет, то Вы можете не понять, к чему весь этот разговор. О какой задержке все время говорит этот парень? Прекрасно, но еще остаются люди, имеющие более медленный модем, чем 14.4 (Нет, это не я. Я только что заменил свой на 33.6, да...).

Изменение изображений в связи с событиями, инициируемыми самим читателем

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

Исходный код этого примера выглядит следующим образом:

При этом могут возникнуть следующие проблемы:

  • Читатель пользуется браузером, не имеющим поддержки JavaScript 1.1.
  • Второе изображение не было загружено.
  • Для этого мы должны писать новые команды для каждого изображения на web-странице.
  • Мы хотели бы иметь такой скрипт, который можно было бы использовать во многих web-страницах вновь и вновь, и без больших переделок.
Теперь мы рассмотрим полный вариант скрипта, который мог бы решить эти проблемы. Хотя скрипт и стал намного длиннее - но написав его один раз, Вы не больше будете беспокоиться об этих проблемах.
Чтобы этот скрипт сохранял свою гибкость, следует соблюдать два условия:
  • Не оговоривается количество изображений - не должно иметь значения, сколько их используется, 10 или 100
  • Не оговоривается порядок следования изображений - должна существовать возможность изменять этот порядок без изменения самого кода
Посмотрим этот код в работе:


Рассмотрим скрипт (я внес туда некоторые комментарии):

Данный скрипт помещает все изображения в массив pics . Создает этот массив функция preload(), которая вызвается в самом начале. Вызов функции preload() выглядит просто как: preload("link1", "img1f.gif", "img1t.gif"); Это означает, что скрипт должен загрузить с сервера два изображения: img1f.gif и img1t.gif . Первое из них - это та картинка, которая будет представлена, пока курсор мыши не попадает в область изображение. Когда же пользователь помещает курсор мыши на изображение, то появляется вторая картинка. При вызове функции preload() в качестве первого аргумента мы указываем слово "link1" и тем самым задаем на web-странице объект Image, которому и будут принадлежать оба предварительно загруженных изображения. Если Вы посмотрите в нашем примере в раздел , то обнаружите изображение с тем же именем link1 . Мы пользуем не порядковый номер, а именно имя изображения для того, чтобы иметь возможность переставлять изображения на web-странице, не переписывая при этом сам скрипт.
Обе функции on() и off() вызываются посредством программ обработки событий onMouseOver и onMouseOut. Поскольку сам элемент image не может отслеживать события MouseOver и MouseOut, то мы обязаны сделать на этих изображениях еще и ссылки.
Можно видеть, что функция on() возвращает все изображения, кроме указанного, в исходное состояние. Делать это необходимо потому, что в противном случае выделеными могут оказаться сразу несколько изображений (дело в том, что событие MouseOut не будет зарегистрировано, если пользователь переместит курсор с изображения сразу за пределы окна).

Изображения - без сомнения могучее средство уличшения Вашей web-страницы. Объект Image дает Вам возможность создавать действительно сложные эффекты. Однако заметим, что не всякое изображение или программа JavaScript способно улучшить Вашу страницу. Если Вы пройдетесь по Сети, то сможете увидеть множество примеров, где изображения использованы самым ужасным способом. Не количество изображений делает Вашу web-страницу привлекательной, а их качество. Сама загрузка 50 килобайт плохой графики способна вызвать раздражение. При создании специальных эффектов с изображениями с помощью JavaScript помните об этом и ваши посетителями/клиентами будут чаще возвращаться на Ваши страницы. ©1996,1997 by Stefan Koch