SNK Software
Web Studio Монополия Metaproducts Утилиты Игры
Монополию Web Studio Библиотека
Вебмастер Дельфи Работа на ПК Самоучитель
Для PHP Для Delphi
Веб-дизайн Программирование Компьютеры Девайсы Заметки
SNK Software Индустрия hardware Индустрия software
О студии Портфолио Сопровождение сайтов

Новые материалы

Девайсы:
Сравнительный обзор Nokia Lumia 920 и HTC 8X
Девайсы:
Обзор Nokia Lumia 820 – смартфона на WP8
Вебмастеру:
Настройка Apache, PHP и MySQL для Linux-VPS
Вебмастеру:
VPS на домашнем ПК: настройка сети в VM VirtualBox и Debian
Вебмастеру:
VPS на домашнем ПК: устанавливаем Linux Debian 6
Вебмастеру:
VPS на домашнем ПК: установка VM VirtualBox
Работа на компьютере:
Иные возможности текстового процессора Word
Работа на компьютере:
Вставка объектов
Работа на компьютере:
Таблицы в Word
Работа на компьютере:
Печать и сохранение документов
Работа на компьютере:
Сноски, колонтитулы, оглавление и указатели в Word

DOM в деталях

В этой главе:

  1. Интерфейсы ядра DOM
  2. Интерфейсы DOM HTML
  3. Интерфейсы DOM CSS

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

Интерфейсы ядра DOM

Рассмотренные нами ранее свойства и методы, в основном, относились к HTML-части DOM (см. таблицу 4.17). Исключение составили лишь методы getElementsByTagName и getElementById, причем последний «перекочевал» из HTML-подраздела в ядро только во 2-й версии DOM.

Преимущества методов ядра, прежде всего, заключаются в том, что они могут работать не только в HTML, но и в XML-документах. Кроме того, методы DOM для HTML в чем-то уникальны для каждого элемента, и нередко в них бывает трудно разобраться. Тем не менее, мы рассмотрим и их, а пока обратим свое внимание на основные свойства и методы ядра DOM, относящиеся как к документу в целом (интерфейс Document), так и к его отдельным элементам (интерфейс Element), для чего обратимся к таблице 4.18.

Таблица 4.18. Некоторые атрибуты интерфейсов Document и Element
АтрибутПримечаниеОписание
doctypeСвойство DocumentИнформация о типе документа. Фактически ссылается на определение DOCTYPE!. В MSIE всегда возвращает null
documentURIСвойство DocumentПолный адрес (URL) документа (DOM 3)
locationСвойство Document, нестандартноеАналогично documentURI, но не определенно в стандарте DOM
documentElementСвойство DocumentСсылается на корневой элемент документа, для HTML/XHTML-документов это HTML
createElementМетод DocumentСоздает новый элемент указанного типа, возвращает ссылку на созданный элемент
getElementByIdМетод DocumentВозвращает ссылку на элемент с указанным идентификатором
getElementsByTagNameМетод DocumentВозвращает массив (список) всех элементов указанного типа, имеющихся в документе
tagNameСвойство ElementВозвращает имя тега элемента
getAttributeМетод ElementВозвращает значение указанного атрибута
setAttributeМетод ElementУстанавливает значение указанного атрибута (и при необходимости добавляет сам атрибут к элементу)
removeAttributeМетод ElementУдаляет указанный атрибут. Если для атрибута имеется значение по умолчанию, то оно будет выставлено
hasAttributeМетод Element, не поддерживается MSIE 6-7Проверяет наличие атрибута. Возвращает true, если такой атрибут есть или если для него определено значение по умолчанию

Список приведенных в таблице 4.18 свойств и методов не являются исчерпывающим. Более того, некоторые свойств (например, doctype) сами являются интерфейсами, и, в свою очередь, тоже имеют собственные атрибуты. Тем не менее, даже приведенных сведений достаточно, чтобы оперировать документом: можно как изменять существующие, так и создавать новые элементы в документе:

el = document.createElement("input");

Правда, если написать такой код, то ничего нового в документе не появится. Дело в том, что, поскольку все элементы в DOM должны иметь строгую иерархию (т.е. быть наследниками каких-либо других элементов), то непосредственно для добавления созданного элемента в сам документ потребуется еще и указать, в какой элемент он должен быть вложен. Таким элементом может быть любой другой уже имеющийся элемент, допускающий вложение. Например, для INPUT это, скорее всего, будет форма (FORM):

inp = MyForm.appendChild(el); // MyForm – ссылка на объект-форму HTML

ПРИМЕЧАНИЕ
Метод appendChild относится к еще одному базовому интерфейсу ядра DOM – Node. Данный интерфейс, в общем-то, являются основополагающим для всей объектной модели, однако сам по себе используется довольно редко, особенно в сценариях для HTML-документов.

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

inp.setAttribute("type","button");

В данном случае мы изменили вид элемента INPUT с секстового поля (значение по умолчанию) на кнопку. Более полный пример, иллюстрирующий так же подавление ошибок браузера на случай отсутствия поддержки в нем тех или иных интерфейсов при помощи операторов обработки исключений try…catch, можно посмотреть в файле core.html.

Интерфейсы DOM HTML

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

Среди всех интерфейсов DOM HTML, прежде всего, следует выделить интерфейс HTMLDocument, являющийся исходной точкой иерархии всех прочих объектов на странице. Собственно говоря, это именно к нему относятся рассмотренные нами методы и свойства title, URL, body, links, images, forms, open, close, write и т.д. Помимо него, существует еще один общий интерфейс – HTMLElement, который определяет все основные атрибуты для HTML-элементов, а именно id, title, lang, dir и className. На его основе определено еще свыше 50 интерфейсов – свой для каждого тега, например, HTMLFormElement или HTMLTableElement. Все они, фактически, представляют собой оболочку для атрибутов соответствующего HTML-элемента. Например, интерфейс HTMLFontElement имеет атрибуты color, face и size, т.е. те же, что и у элемента FONT в языке HTML.

Очевидно, что, скажем, в документе типа HTML 4.0 Strict или XHTML 1.1 интерфейс HTMLFontElement использовать не следует, поскольку связанного с ним элемента FONT в таких документах быть не должно. В то же время, ряд других интерфейсов регулярно используются, упрощая написание сценариев. В первую очередь это относится к интерфейсам, представляющим элементы форм (хотя и тут не все однозначно: скажем, в XHTML 2 будут использоваться отличные от HTML формы «XFORMS»), а так же к доставшимся от DOM 0 массивам элементов. Действительно, будет несколько проще и нагляднее установить значение текстового поля формы, воспользовавшись свойством value, чем назначать значение атрибута VALUE средствами ядра DOM:

MyInput.value = "Строка"; // DOM HTML MyInput.setAttribute("value", "Строка"); // DOM Core

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

MyInput = document.forms["Form1"].elements["Input1"]; // DOM HTML MyInput = document.forms.Form1.Input1; // 2-й вариант DOM HTML MyInput = document.getElementById("Input1"); // DOM Core

Таким образом, вопрос стоит не в том, что надо использовать те или иные методы, а как правильно их сочетать для собственного удобства – с одной стороны, и для обеспечения максимальной совместимости – с другой. В данном случае было бы предпочтительно использовать метод ядра для выбора элемента, а для установки значения – метод HTML (опять-таки, более простая запись плюс отсутствие проблем с установкой атрибутов для INPUT в MSIE):

document.getElementById("Input1").value = "Строка";

В то же время, в данном случае вполне можно предпочесть и вариант «только HTML», т.е. все можно представить примерно такой строкой:

document.forms.Form1.Input1.value = "Строка";

Вообще же исторически сложилось так, что методы JavaScript, в первую очередь, доля взаимодействия с формами и предназначались. Благодаря этому методы HTML, введенные еще во времена Netscape 2, чаще всего и используются ввиду своей универсальности и простоты применения. Например, чтобы сослаться из одного элемента формы на другой элемент в этой же форме, достаточно указать только его имя (идентификатор):

<form> <input type="Text" id="Edit1" value="" /> <input type="Button" value="Жми!" onclick="Edit1.value='Новый текст'" /> </form>

ПРИМЕЧАНИЕ Чтобы сослаться на сам элемент, используют ключевое слово this, например, «alert(this.value)». А для получения ссылки на родительский элемент (скажем, на саму форму), можно воспользоваться методом parentNode интерфейса Node, например: «ProcessFormFunc(this.parentNode);».

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

В MSIE 4 слои, в принципе, ничем не отличаются от остальных элементов HTML уровня блока, и работать с ними можно через document.all. В Netscape 4 для слоев был предусмотренспециальный массив – document.layers, а в Netscape 6, 7 и Mozilla слои не имеют такой исключительности, и доступ к ним можно получить через функцию document.getElementById, как, впрочем, и в MSIE 5 и выше или в Opera. Поэтому, если требуется создать сценарий, который должен работать сразу со всеми версиями браузеров, придется предусмотреть три варианта. Например, для того, чтобы сделать некий слой «Layer1» невидимым, надо написать:

document.all.Layer1.visibility='hidden' //MSIE 4, подойдет и для MSIE 5/6 document.layers.Layer1.visibility='hidden' //для Netscape 4 document.getElementById('Layer1').visibility='hidden' //для новых браузеров

А теперь представьте, что вам придется создавать сразу три варианта программы! К счастью, используя объектную модель самого языка JavaScript, можно существенно упростить работу. Для этого достаточно один раз присвоить некоторой переменной ссылку на объект, и в дальнейшем уже работать со ссылкой, а не указывать каждый раз сам объект. Для этого можно создать функцию, которая проверяла бы браузер на наличие того или иного варианта определения объекта (т.е., скажем, имеется ли в браузере объект document.layers или document.all), и возвращала ссылку на нужный элемент в документе:

function GetLayer(id) { if (document.layers) { return document.layers[id]; // Netscape 4.x } else if (document.all) { return document.all(id); // MSIE, Opera } else { return document.getElementById(id); // Mozilla и др. } }

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

L1 = GetLayer("Layer1"); L1.style.left="400px";

Фактически, в последней строке выражение будет воспринято интерпретатором каждого браузера по-своему, как «родное». Т.е. для MSIE она будет равнозначна такой записи:

document.all("Layer1").style.left="400px";

В то же время, для Netscape или Mozilla она будет выглядеть иначе – через массив Layers в Netscape и через getElementById – в Mozilla:

document.layers["Layer1"].style.left="400px"; document.getElementById("Layer1").style.left="400px";

Работающий пример можно посмотреть в файле layers.html, но при всем этом следует отметить, что приведенный пример скорее иллюстрирует возможности ветвления программы на JavaScript, нежели практическую ценность, поскольку столь старые версии браузеров сегодня «в живой природе», к счастью, уже не встречаются. Поэтому при выполнении реальной задачи можно обойтись только последним, т.е. стандартным вариантом с использованием getElementById.

СОВЕТ
Еще один, причем довольно интересный пример, вы можете найти на компакт-диске в файле Part4\DOM\rotate_layers.html. В нем так же рассмотрен способ использования тех или иных объектов и методов с использованием идентификации по производителю и номеру версии браузера.

Интерфейсы DOM CSS

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

// установка красного цвета для элемента с id=Heading: document.getElementById("Heading").style.color = "red"; // установка смещения для позиционированного элемента: document.getElementById("AbsDiv").style.left = "300px"; // установка свойства видимости для рисунка: document.images[0].style.visibility = "hidden";

Все современные браузеры допускают назначение таким образом любых свойств CSS (вернее, тех из них, которые данным браузером поддерживаются). При этом следует учитывать, что если название свойства CSS состоит более, чем из одного слова (т.е. пишется через черточку, например, text-align), то в DOM оно должно писаться слитно, а второе слово – начинаться с прописной буквы:

// установка расположения фонового изображения (background-position): document.body.style.backgroundPosition = "center";

Другим способом изменения стиля того или иного элемента является назначение ему атрибута Style с необходимыми параметрами CSS. В таком случае получается полная аналогия со встроенными (inline) стилями, с той лишь разницей, что при помощи DOM и JavaScript значение атрибута можно изменять в процессе работы пользователя со страницей.

Так или иначе, но оба рассмотренных метода действуют только для отдельных элементов. Для смены всех стилей документа сразу можно воспользоваться интерфейсом StyleSheet, представляющим собой оболочку для предопределенной таблицы стилей. Список доступных таблиц стилей хранится в объекте styleSheets. Например, чтобы получить информацию о расположении текущей таблицы стилей, можно использовать следующее выражение:

document.styleSheets[0].href;

ПРИМЕЧАНИЕ
Если таблица стилей находится в самом файле, то Mozilla вернет URL текущего документа, а MSIE – пустую строку. Что касается Opera, то этот браузер, к сожалению, не поддерживает данного интерфейса.

Поскольку каждый элемент массива styleSheets является отдельной таблицей стилей, представленную, как уже было отмечено, через интерфейс StyleSheet. Помимо свойства href для него предусмотрен ряд иных свойств, в том числе type, media и title. Все они по своему значению соответствуют одноименным атрибутам элемента STYLE (или LINK, использованного в контексте подключения таблицы стилей). Все эти атрибуты доступны только для чтения, то есть можно узнать, скажем, адрес или расположения стилей, но не изменить их. Но помимо этих свойств, для интерфейса StyleSheets имеется еще одно – disabled, при помощи которого можно подключать или отключать отдельные таблицы стилей. Допустим, у нас имеется документ, к которому подключено 2 файла CSS, описывающих стили для одних и тех же элементов, но отличающихся по их оформлению. В таком случае можно дать пользователю возможность подключить тот или иной стиль не только через интерфейс браузера (тем более что такая функция отсутствует в MSIE), но и при помощи сценария на странице. В листинге 4.8 приведен возможный вариант реализации такого сценария.

Листинг 4.8. Управление таблицами стилей

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"> <html> <html> <head> <title>Управление таблицами стилей</title> <link rel="stylesheet" type="text/css" title="Красный" href="reds.css" /> <link rel="stylesheet" type="text/css" title="Синий" href="blues.css" /> <script type="text/JavaScript"><!-- function SetStyle(id) { for (var i=0; i<document.styleSheets.length; i++) { document.styleSheets[i].disabled = (id!==i); }; } //--></script> </head> <body onload="SetStyle(-1);"> <h2>Можно изменять оформление этого документа, подключая ту или иную таблицу стилей</h2> <form id="StyleForm"> <select id="StyleSel" onchange="SetStyle(this.selectedIndex)"> <option>Красный</option> <option>Синий</option> <option selected="selected">Без стиля</option> </select> </form> </body> </html>

Прежде всего, в заголовке документа имеются ссылки на 2 таблицы стилей – «Красную» и «Синюю». В нем же расположен сценарий, в котором определена функция SetStyle, которая отключает все таблицы стилей, кроме указанной путем сравнения порядкового номера таблицы в массиве styleSheets с полученным функцией аргументом. В части тела документа расположена форма, состоящая из списка с тремя вариантами, 2 из которых соответствуют определенным таблицам стилей, а 3-й, выбранный по умолчанию, предназначен для отключения всех стилей. Когда пользователь изменит состояние списка (событие ONCHANGE) путем выбора какого-либо варианта, будет вызвана функция SetStyle с номером выбранного пункта в качестве параметра. Таким образом, если выбрать 1-й вариант – Красный, будет подключена 1-я таблица (reds.css), а 2-я – отключена. Для 2-го варианта ситуация обратная, а для 3-го (Без стилей) будут отключены оба файла.

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

var List = document.getElementById("StyleSel"); for (var i=0; i<document.styleSheets.length; i++) { opt = document.createElement("option"); List.appendChild(opt); txt = document.createTextNode(document.styleSheets[i].title); opt.appendChild(txt); }

Сначала здесь выбирается отправная точка – сам список. Затем начинается цикл по всем таблицам стилей документа. В нем создаются новые элементы OPTION, которые добавляются к списку, и в которые, в свою очередь, вставляется текст из заголовков стилей (атрибут TITLE элемента LINK). Но чтобы сделать список полностью аналогичным рассмотренному ранее, нам потребуется еще один проход цикла – для добавления пункта «Без стиля». Для этого понадобится немного изменить условие цикла – заменит сравнение «меньше» на «меньше или равно»:

for (var i=0; i<=document.styleSheets.length; i++)

Теперь цикл будет выполнен на 1 раз больше, чем есть таблиц стилей в действительности. Поэтому, чтобы избежать ошибки, связанной с попыткой доступа к несуществующему элементу массива styleSheets, а заодно вставить нужный текст в последний пункт, придется модернизировать и тело цикла:

opt = document.createElement("option"); List.appendChild(opt); if (i<document.styleSheets.length) { txt = document.createTextNode(document.styleSheets[i].title); } else { txt = document.createTextNode("Без стиля"); opt.selected=true; }; opt.appendChild(txt);

Здесь мы добавили проверку на то, что текущее значение счетчика цикла не превышает числа элементов в списке стилей. Если же оно больше, то в качестве текстовой подписи для OPTION используется не заголовок стиля, а строка «Без стиля». Кроме того, это (последний) пункт отмечается как выбранный по умолчанию (при помощи свойства selected). Полностью модернизированный пример можно посмотреть в файле style.html.

2011-08-04 // Есть вопросы, предложения, замечания? Вы можете обсудить это на форуме !

Избранное

SNK GSCP
SNK GSCP - новая библиотека для PHP 5!
Web Studio
Web Studio и Visual Workshop
Библиотека:
Стандарты на web-технологии
Монополия
Монополия v. 2.0.2
Загрузки:
скачать программы
Продукция:
программы и книги
Техподдержка / Связаться с нами
Copyright © 1999-2013 SNK. Все права защищены.
При использовании материалов с сайта ссылка на источник обязательна.
Рейтинг@Mail.ru