11. Объектная модель документа. Ранняя упрощенная модель
Что такое DOM
HTML-документ браузер отображает в своём окне, которое описывается объектом window.
Объект window является родителем всех других объектов, ссылки на которые содержатся в соответствующих свойствах объекта window.
Объект | Краткое описание объекта |
---|---|
window.navigator | Свойства и методы для доступа к данным, описывающих браузер. |
window.location | Свойства и методы для работы с URL открытого окна. |
window.history | Свойства и методы для работы со списком URL документов, которые загружались в окно браузера. |
window.screen | Свойства и методы для доступа к параметрам и настройкам экрана монитора. |
window.document | Объектная модель документа — содержит иерархию объектов, построенных браузером по HTML-коду, загруженному в окно документа. |
Объектная модель документа (DOM — Document Object Model) — это иерархия объектов, моделирующая текущий HTML-документ. Набор свойств и методов объектов DOM образует прикладной программный интерфейс (API — Application Programming Interface). DOM начинается с объекта document, все другие объекты, соответствующие элементам HTML-документа, являются его потомками.
Когда браузер загружает страницу, он анализирует её и строит DOM. После того как документ полностью загружен и DOM построен, в окне возникает событие onload. Теперь можно обращаться к свойствам и методам объектов DOM.
Какой бывает DOM
Уровень 0 (DOM Level 0) == ранняя версия DOM
Ранняя упрощенная объектная модель документа сложилась де-факто в результате «военного» этапа развития браузеров (до того, как консорциумом W3C разработал стандарт DOM уровня 1).
Эта упрощенная версия DOM сохранилась для обратной совместимости, и её поддерживают (и будут поддерживать) все современные браузеры.
Уровень 1 (DOM Level 1)
В 1998 году консорциум W3C опубликовал стандарт DOM Level 1.
Уровень 2 (DOM Level 2)
В 2000 году была стандартизована модель DOM Level 2.
Уровень 3 (DOM Level 3)
В 2009 году был официально объявлен стандарт DOM Level 3, но новые функциональные возможности третьего уровня пока ещё не поддерживаются браузерами.
Поддержка браузерами
В момент написания этих строк все браузеры прекрасно поддерживают DOM Level 2, кроме, разумеется, IE, хотя последние версии этого браузера (7, 8 и 9) всё ближе подбираются к стандартам. Довольно популярный ещё IE-6 в основном совместим с DOM Level 1, но практически не поддерживает DOM Level 2.
К счастью IE-6 поддерживает важный метод document.getElementById(id) из набора DOM Level 2, который позволяет получить ссылку на объект, построенный для элемента с заданным идентификатором id. Этот метод, кажется, поддерживает даже IE-5, хотя этот браузер сегодня можно списать со счетов.
Рассмотрение DOM начнём с ранней версии (Level 0) — её поддерживают все браузеры, и работу с этой моделью можно совмещать с интерфейсами моделей от W3C (уровня 1 и выше).
Уровень 0 (DOM Level 0) == ранняя версия DOM
В рамках ранней модели объект document имеет свойства, которые ссылаются на объекты, подобные массивам (их часто называют коллекциями): anchors, applets, forms, images и links. В настоящее время практическую ценность представляют только последние три коллекции.
Объект | Краткое описание коллекции |
---|---|
document.anchors |
Коллекция содержит объекты класса Anchor, представляющие якорные
элементы документа, то есть элементы вида:
Эти элементы используются (вернее, использовались) для внутристраничных переходов по ссылкам вида:
Таким образом, document.anchors[0] содержит ссылку на объект, соответствующий первому якорному элементу страницы. |
document.applets | Коллекция содержит объекты класса Applet, представляющие Java-апплеты документа. |
document.forms |
Коллекция содержит объекты класса Form, представляющие
элементы FORM
документа. Каждый объект Form обладает собственным
свойством-коллекцией elements, в котором представлены объекты,
построенные для элементов формы
(INPUT, SELECT и TEXTAREA).
Пусть первая форма задана в HTML следующим кодом:
Тогда:
Использовать индексы для доступа к объектам, построенным для элементов HTML-кода не слишком удобно. Но можно воспользоваться следующим правилом, которое действует для элементов FORM, IMG, APPLET (но не действует для элементов A): Установка атрибута name в открывающих тегах элементов FORM, IMG и APPLET позволяет обращаться к соответствующим объектам, как к именованным свойствам объекта document. Таким образом, возможны следующие формулы доступа:
|
document.images |
Коллекция содержит объекты класса Image, представляющие элементы IMG документа. Свойство src объекта Image содержит значение одноименного атрибута элемента IMG и доступно для чтения/записи.
Можно опускать имя коллекции в формулах доступа, если используется значение атрибута name и обращаться к именованным элементам как к свойствам объекта document:
|
document.links | Коллекция содержит объекты класса Link, представляющие гипертекстовые ссылки документа. Свойство href объекта Link соответствует значению одноименного атрибута элемента A. Например, document.links[0].href дает доступ к значению атрибута href первой ссылки на странице. |
Замечание 1. Заметим ещё раз, что именованный доступ вида document.name возможен только для элементов FORM, IMG и APPLET.
Замечание 2. Пусть имеется несколько элементов с одинаковыми значениями атрибута name, например, name="n". Тогда свойство document.n будет представлять собой не один объект, а массив объектов, сформированный для этих элементов, в порядке следования их в HTML-коде.
Поработайте со следующими примерами:
Пример | Комментарий |
---|---|
Пример 1 | Запустите пример и разберитесь в устройстве его кода. |
Пример 2 | Этот пример работает аналогично первому, но обращение к элементам формы выполняется не по индексам, а по именам. |
Пример 3 | Пример демонстрирует работу с коллекцией images. В нём создается картинка, чувствительная к указателю мыши. |
Обработка событий в ранней версии DOM
В разделе события приводится список событий (с указанием элементов, к которым события можно привязывать).
Привязка событий в ранней модели DOM выполняется:
- При помощи «событийных» атрибутов элементов HTML.
- При помощи соответствующих свойств объектов, построенных для элементов HTML.
Так, если нужно обработать щелчок мыши на картинке, привязать обработчик (например, функцию work) можно при помощи атрибута onclick в HTML-коде:
<IMG name="pic" onclick="work()"
src="prav30.gif" width=140 height=150 border=1
alt="Профессор" title="Профессор">
А можно воспользоваться свойством onclick объекта, построенного в DOM для элемента IMG с name="pic":
document.image["pic"].onclick = work;
Или так:
document.pic.onclick = work;
Заметим ещё раз, что именованный доступ к объекту, построенного для элемента с name="xyz" в виде document.xyz возможен только для элементов FORM, IMG и APPLET. Для других элементов в рамках ранней модели (например, для абзаца) остаётся только одна возможность привязать событие — при помощи событийного атрибута в открывающем теге самого элемента.
Ключевое слово this в обработчиках
Обработчик является методом объекта, построенного для некоторого элемента HTML.
Пусть, например, в HTML-коде есть элемент IMG:
<IMG name="pic"
src="prav30.gif" width=140 height=150 border=1
alt="Профессор" title="Профессор">
Этому элементу в DOM соответствует объект класса Image. Доступ к этому объекту можно получить так:
document.pic // Это ссылка на объект Image,
// построенный для IMG с name="pic"
Обработчик является методом этого объекта. Если мы записываем инструкцию
document.pic.onclick = work;
то тем самым определяем метод объекта document.pic. Функция work будет вызываться как метод объекта document.pic, значит, ключевое слово this в ней будет относиться к этому объекту.
Получаем правило:
Ключевое слово this в обработчике события относится к объекту, построенному для HTML-элемента, к которому это событие привязано.
Это правило работает и тогда, когда обработчик записан в виде событийного атрибута элемента HTML.
Таким образом, мы можем, например, для смены картинки под указателем мыши записать такой код:
<IMG src="prav30.gif" width=140 height=150 border=1
onmouseover = "this.src='prav31.gif'"
onmouseout = "this.src='prav30.gif'"
alt="Профессор" title="Профессор">
В этом коде строки, заданные как значения событийных атрибутов, неявно преобразуются в безымянные функции, ссылки на которые автоматически записываются в свойства onmouseover и onmouseout соответствующего объекта класса Image.
Поэтому ключевое слово this, фигурирующее в атрибутах, ссылается на объект Image, построенного для текущего элемента IMG. Соответственно, this.src ссылается на свойство, соответствующее одноименному атрибуту.
Отметим, что все атрибуты преобразуются в одноименные свойства построенного объекта. Например, свойство this.width для данного IMG имеет числовое значение 140, а значение свойства this.alt равно строке "Профессор".
Метод document.getElementById
Как мы видели, в ранней модели DOM регистрировать обработчики для всех элементов, кроме FORM, IMG и APPLET, можно только при помощи событийных атрибутов в коде HTML.
На сегодняшний день — это плохая практика. Нужно стремиться отделить поведение страницы от её содержания и представления. То есть весь JavaScript-код нужно стараться записывать в отдельном файле.
В рамках ранней модели DOM так не получится, ибо обработчик события, как свойство объекта, мы можем задать только для элементов FORM, IMG и APPLET, а, скажем, прикрепить обработчик к абзацу таким способом нельзя.
Однако, если к программному интерфейсу ранней модели DOM добавить метод getElementById объекта document (относящийся к DOM уровня 2), ситуация исправляется.
Метод getElementById имеет следующий формат:
document.getElementById(id)
- id — строка, значение соответствующего HTML-атрибута
Метод возвращает ссылку на объект, построенный в DOM для элемента с указанным идентификатором, или null, если такого элемента в HTML-коде нет.
К счастью, метод getElementById понимают все современные браузеры (и даже IE).
Пример | Комментарий |
---|---|
Пример 4 | В этом примере обработчик привязан к заголовку H1 с использованием метода getElementById. |
Свойство innerHTML
Это свойство не входит в стандарт W3C. Первоначально оно появилось в IE 4, а затем было реализовано во всех браузерах. То есть innerHTML понимают (и будут понимать) все современные браузеры.
При помощи метода document.getElementById(id) можно получить доступ к любому элементу на экране (вернее, к объекту, для него построенного, но это практически то же самое).
element = document.getElementById(id); // Доступ к элементу
// с идентификатором id
У каждого такого объекта есть свойство innerHTML, которое позволяет читать и менять содержимое элемента.
element.innerHTML // Строка, содержащая HTML-код внутри элемента
// (за исключением открывающего и закрывающего тега
// самого элемента).
// Запись в это свойство строки, содержащей HTML-код,
// приводит к изменению объектной модели и,
// соответственно, изменению представления документа
// на экране.
Метод document.getElementById и свойство element.innerHTML, добавленные к ранней модели DOM, позволяют достаточно комфортно работать, создавая интерактивные динамические документы.
Пример | Комментарий |
---|---|
Пример 5 | Исследуйте работу этой страницы и разберитесь в коде, который её обслуживает. Обратите внимание — заголовкам H1 и H2 назначены одни и те обработчики событий onmouseover и onmouseout. Обработчик определяет источник события по ключевому слову this. |
В разделе примеры приводятся ссылки на коды, иллюстрирующие заметку.
Раздел события содержит справочник по событиям, возникающим при работе HTML-кода.
В разделе задания собраны контрольные задания (с решениями).