СтатьиВведение в DOMУровни Объектной Модели Документа(DOM) и их поддержка в браузерахКраткая история вопроса. Когда возможность работы с Java Script была впервые представлена в браузерах, некоторые виды интерфейсов требовали разрешения от элементов на странице для доступа к ним посредством скриптов. Каждый производитель браузера представлял ее собственную реализацию, но де-факто назревала необходимость как-то стандартизировать основную для всех модель. К примеру, большинство браузеров используют массив объектов
Это устаревшая и ограниченная модель. Она дает доступ лишь к немногим типам элементов и атрибутов, например к изображениям( Когда появлялись новые версии браузеров, в них появлялись новые возможности модели. Но и разница в ее реализации увеличивалась. Основной проблемой совместимости браузеров от различных производителей было добавление новых возможностей, присущих только этому браузеру. Через некоторое время большинство производителей начали адаптировать свои браузеры (в основном это Internet Explorer, Netscape и Opera) к стандартам DOM, установленным консорциумом W3C. Порядок обратной совместимости различных уровней стандартов DOM определен. Вы можете найти ссылки на DOM Level 0 ("DOM0"), которые соответствуют модели, используемой первыми браузерами, поддерживающими скрипты (в основном Internet Explorer и Netscape до 4 версии), например http://www.w3.org/TR/WD-DOM-19980318/. В 1998 году появился DOM1 и включил в себя возможности, представленные в 4 версии браузеров. Браузеры, совместимые со стандартомБольшинство современных браузеров(начиная с 5 версии) поддерживают стандарт DOM2 или хотя бы часть его. Они также поддерживают более ранние уровни DOM, а также собственные ранее разработанные расширения для обеспечения работоспособности старых web-страниц. Эта статья сосредоточена на стандарте DOM2. На момент написания статьи именно этот стандарт применяется к документам XML в целом и к документам HTML в частности. Можно надеяться, что более новые версии браузеров будут полностью следовать стандартам. Сейчас же существует огромное количество трудностей, с которыми приходится сталкиваться при написании web-документов, полностью совместимых как с современными, так и более ранними браузерами. Один из примеров — Netscape 6.0, который перестал поддерживать некоторые возможности Netscape 4 (например тэг Еще пример — существующая и работающая в Internet Explorer конструкция Вы должны иметь в виду, что DOM кодирование тесно связано со стандартами HTML и CSS, так как DOM представляет элементы и атрибуты в соответствии с этими стандартами. Дерево документа (Document Tree)Когда браузер загружает страницу, он создает иерархическое отображение ее содержимого похожее на ее HTML структуру. Это результат древообразной организации узлов, каждый из которых содержит элемент, атрибут, текстовый или любой другой объект. Узлы (Nodes)Каждый их этих различных типов объектов имеет свои уникальные методы и свойства, а также обеспечивает взаимосвязь узлов ( Каждый узел (Node) содержит свойства, отражающие эту структуру и позволяющие перемещаться по всем узлам дерева документа. Ниже показаны примеры взаимоотношений этих узлов:
Интерфейс узлов содержит методы для динамического добавления, обновления или удаления узлов, например:
Это будет раскрыто чуть позже, а пока рассмотрим, как дерево документа отражает контент web-страницы. Корень Документа (Document Root)Объект Этот интерфейс содержит методы доступа к другим узлам и создания новых узлов в дереве документа. Вот некоторые из них:
Эти методы не такие, как у других узлов. Они могут быть только у объекта Объект Эти свойства предназначены для обеспечения обратной совместимости, чтобы web-страницы, созданные для старых браузеров, могли правильно отображаться в новых браузерах. Они все еще используются в скриптах, но их не стоит применять, т.к. в будущем они могут больше не поддерживаться. Перемещение по Дереву ДокументаКак уже было сказано, дерево документа отражает структуру HTML кода страницы. Каждый тэг или пара тэгов изображены как узел элемента, с узлами представляющими атрибуты или символьные данные (например, текст). Формально, объект Учитывая это и используя методы интерфейса <html> <head> <title></title> </head> <body><p>Здесь какой-то текст.</p></body> </html> и этот код:
который покажет
При этом всплывает очевидная проблема доступа к узлам. Достаточно изменить код документа, например, если добавить другие элементы, текст или изображения, то будет изменена структура дерева документа. И путь к этому узлу также может измениться. Менее очевидна совместимость с доступом к узлам в некоторых браузерах. В приведенном выше примере между тэгами <html> <head> <title></title> </head> <body> <p>Здесь какой-то текст.</p> </body> </html> В этом случае Netscape обнаружит в этих местах новые узлы, тогда как IE не станет этого делать. В Netscape вышенаписанный код JavaScript покажет "undefined", т.к. теперь в этом месте появился текстовый узел в виде пробела. Так как это не узел элемента, он не содержит теперь имени тэга. С другой стороны, IE не добавит узлов для таких пробелов, как здесь и по прежнему будет указывать на тэг Прямой доступ к элементамДля этого существует удобный метод <p id="myP">Здесь какой-то текст.</p> ... alert(document.getElementById("myP").tagName); В этом случае можно не опасаться некоторой несовместимости браузеров, а также того, где в дереве документа размещен узел для тэга Более сложный доступ к узлу элемента представлен методом var nodeList = document.getElementsByTagName("a"); for (var i = 0; i < nodeList.length; i++) nodeList[i].style.color = "#f00"; Типы узлов (Node Types)Перед тем, как продолжить, более детально рассмотрим типы узлов. Как упоминалось ранее, в Объектной Модели Документа определены несколько типов узлов, но в разметке web-страницы в основном используются Узел Узел Узел Обратите внимание, что значение атрибута всегда будет представлено текстовой строкой. Атрибут, как узел AttributeСуществует несколько способов обращения к атрибутам элемента. Причина тому — стандарт DOM2, который был разработан для различных типов документов (т.е. XML), не только HTML. Таким образом он формально определяет тип узла для атрибута. Но для всех документов он обеспечивает несколько схожих методов для доступа к атрибутам, добавления новых или изменения существующих. Как это происходит, смотрите дальше. Метод var attr = document.createAttribute("myAttribute"); attr.value = "myValue"; var el = document.getElementById("myParagraph"); el.setAttributeNode(attr); Однако, существует более простой способ доступа к атрибутам элемента, используя var el = document.getElementById("myParagraph"); el.setAttribute("myAttribute", "myValue"); Атрибуты элемента могут быть представлены и как свойства узла элемента. Другими словами, можно сделать и так: var el = document.getElementById("myParagraph"); el.myAttribute = "myValue";
Следует обратить внимание, что Explorer 5.5 и более ранние версии не поддерживают тип узла Вы можете определять ваши атрибуты в HTML тэгах, например: <p id="myParagraph" myAttribute="myValue">Здесь какой-то текст.</p> ... alert(document.getElementById("myParagraph").getAttribute("myAttribute")); увидите "myValue", а также обратите внимание: чтобы получить значение атрибута, следует использовать именно Атрибуты можно удалять из узла элемента, используя метод Изменение атрибутов — один из вариантов создания динамических эффектов. Например можно легко изменить выравнивание текста по правому или левому краю: <p id="sample" align="left">Здесь какой-то текст.</p> <p> <a href="" onclick="document.getElementById('sample').setAttribute('align', 'left'); return false;"> Нале-во! </a> :: <a href="" onclick="document.getElementById('sample').setAttribute('align', 'right'); return false;"> Напра-во! </a> </p> Атрибуты стилейБольшинство атрибутов для HTML тэгов примитивны, они могут определять значение свойства только конкретному тэгу. Применение стилей более интересно. Как известно, CSS может быть использовано для применения параметров стилей к одному тэгу, всем однотипным тэгам или назначено с помощью классов ( Вы можете добавлять стили элементам. Для примера, можно изменить атрибут Атрибут Но в этом случае выравнивание текста определено параметрами стилей вместо атрибута <p id="sample2" style="text-align:left">Здесь какой-то текст.</p> <p> <a href="" onclick="document.getElementById('sample1').style.textAlign = 'left'; return false;"> Нале-во! </a> :: <a href="" onclick="document.getElementById('sample1').style.textAlign = 'right'; return false;"> Напра-во! </a> </p> Здесь следует обратить внимание на то, что названия свойств в CSS пишутся через дефис А кроме этого, если параметры стилей изначально не были присвоены элементу, им все-равно можно устанавливать значения используя DOM. Например, в коде выше атрибут Итак, ранее мы рассмотрели как можно получить доступ к любому атрибуту или свойствам стилей любого элемента на странице. Но как же динамически добавлять или удалять сами элементы и контент на странице? Или изменять контент? Динамический контентИзменить текстовое содержимое страницы довольно просто. Каждая непрерывная строка символов в теле HTML страницы представляется текстовым узлом. Свойство Текстовые узлы (Text Nodes)Следующий пример использует простейший тэг параграфа Вот текст, который будем изменять. А теперь рассмотрим код этого примера: <p id="sample2">Вот текст, который будем изменять.</p> <p> <a href="" onclick="document.getElementById('sample2').firstChild.nodeValue = 'If something`s hard to do...'; return false;">меняем раз</a> :: <a href="" onclick="document.getElementById('sample2').firstChild.nodeValue = '...then it`s not worth doing!'; return false;">меняем еще</a> </p> Ну и сразу важное замечание. У текстового узла отсутствует атрибут Зато получить доступ к текстовому узлу можно зная его родительский узел ( Итак, Важно помнить, что текстовый узел может содержать только текст. Даже простые тэги <p id="sample3">Вот <b>текст</b>, который будем изменять.</p> Таким образом элемент параграфа с А теперь посмотрим, что получилось после изменения разметки, но если оставить скрипт из предыдущего примера без изменений. Вот текст, который будем изменять. Изменение значения Вот текст, который будем изменять. Посмотрите на код этого примера: <p id="sample4">Вот <b>текст</b>, который будем изменять.</p> <p> <a href="" onclick="document.getElementById('sample4').firstChild.nodeValue = '<b>If something`s</b> hard to do...'; return false;">меняем раз</a> :: <a href="" onclick="document.getElementById('sample4').firstChild.nodeValue = '...then it`s <i>not worth</i> doing!'; return false;">меняем еще</a> </p> Вы избежите проблему, рассмотренную выше, поняв, что текстовые узлы это обычные строки символов, размещенные между любыми двумя HTML тэгами, причем не обязательно парными. Свойство innerHTMLВ Internet Explorer у узла элемента ( Используя это свойство, можно заменять все содержимое элемента параграфа из приведенного выше примера, включая HTML разметку, т.е. примерно так: document.getElementById('sample5').innerHtml = "<b>If something`s</b> hard to do..."; Вот текст, который будем изменять. Пока это свойство поддерживается браузерами, его можно использовать, но следует помнить, что оно не включено в стандарт DOM. Добавление узловДобавление новых узлов также не представляет особых трудностей. Ранее мы рассмотрели, как изменять узлы атрибутов и применять их к элементам, а также, как изменять текстовые узлы в дереве документа (свойство Первый шаг к созданию узла объекта того типа, который вам нужен — это один из вариантов: Использование текстовых узловНачнем с текстового узла. Этот пример кода показывает как создать текстовый узел и присвоить ему какое-то значение: var myTextNode = document.createTextNode("ваш текст"); Теперь у вас есть текстовый узел. Но он не является частью дерева документа. Чтобы он появился на странице, его нужно сделать дочерним (child) по отношению к какому-нибудь уже существующему внутри дерева узлу. Его нельзя присоединить к другому текстовому узлу, так как текстовые узлы не могут содержать дочерние узлы. Узлы атрибутов не являются частью дерева документа, поэтому и к ним присоединить текстовый узел нельзя. Тогда в нашем распоряжении остаются узлы элементов. Узел элемента может содержать несколько дочерних узлов, поэтому есть несколько методов, определяющих как и куда добавить новый узел к уже существующим дочерним узлам. Это лучше показать на примерах. Метод Просто текст. А теперь рассмотрим этот фрагмент кода: <p id="sample6">Просто текст.</p> ... вызов функции добавления узла ... var text = document.createTextNode(" новый текст " + (++counter6)); var el = document.getElementById("sample6"); el.appendChild(text); ... вызов функции удаления последнего (lastChild) узла ... var el = document.getElementById("sample6"); if (el.hasChildNodes()) el.removeChild(el.lastChild); Добавление текста — это просто: надо создать новый текстовый узел, определить узел элемента параграфа и вызвать метод Удаление текста происходит также просто: Стоит обрать внимание на метод Соединение и разделение текстовых узловВ вышеприведенном примере текстовые узлы добавлялись как самостоятельные дочерние узлы. Но если вписать текст в HTML-код, <p id="sample7">Просто текст. новый текст 1 новый текст 2 новый текст 3 </p> в DOM это будет одним дочерним текстовым узлом элемента параграфа. Другими словами, дерево узлов, собираемое динамическим добавлением контента, будет отличаться от дерева узлов, собранного из статического HTML-кода. Оно не всегда может быть тем, что вы хотели получить. Иногда вам может понадобиться комбинировать текстовые узлы, таким образом, чтобы новый, динамически добавляемый контент включался в существующий статический HTML-код. Такую возможность предоставляет метод Совместимость браузеров
Пример нормализации параграфа, который разберем далее, не будет работать в Internet Explorer 5.5 и более ранних версиях, т.к. этот браузер не поддерживает метод Этот пример похож на разобранный ранее, в нем мы сможем увидеть количество дочерних узлов параграфа до и после нормализации. Какой-то текст внутри параграфа. Добавить текст :: Удалить текст :: Количество дочерних узлов :: Нормализовать элемент Здесь вы можете видеть, как после добавления текста увеличивается количество текстовых узлов, но после нормализации все добавленные узлы объединяются в единый текстовый узел. Вот код для этих ссылок: ... элемент для нормализации ... el = document.getElementById("sample7"); el.normalize(); ... показываем количество дочерних элементов ... el = document.getElementById("sample7"); alert(el.childNodes.length); Можно разделить текстовый узел на два отдельных, используя метод Рассмотрим следующий пример, где кликнув по ссылке удалим первый дочерний элемент параграфа. Сперва возьмем целое предложение. Кликнув по ссылке "отделить слово", отделим первое слово в тексте, а кликнув после по ссылке "удалить первый узел", уберем только это слово из предложения. Кликнув по ссылке "сбросить" возвращаемся в исходное состояние. Какой-то текст внутри параграфа. Вот как это делается: ... отделяем первое слово ... el = document.getElementById("sample8"); if (el.hasChildNodes()) { text = el.firstChild; i = text.nodeValue.indexOf(" "); if (i >= 0) text.splitText(i + 1); } ... удаляем первый текстовый узел ... el = document.getElementById("sample8"); if (el.hasChildNodes()) el.removeChild(el.firstChild); ... возвращаем пример в исходное состояние ... el = document.getElementById("sample8"); while (el.hasChildNodes()) el.removeChild(el.firstChild); text = document.createTextNode("Какой-то текст внутри параграфа."); el.appendChild(text); Теперь пара замечаний: во-первых, для текстового узла Во-вторых, в коде для возврата в исходное состояние просто удаляются все дочерние узлы элемента параграфа, а затем добавляется исходный текст как единый текстовый узел. Работа с узлами элементов (Element Nodes)Добавление и удаление узлов элементов в основном похоже на действия с текстовыми узлами. Различие по-существу только в создании узла и размещении внутри него контента. Начнем. Вы создаете узел, используя метод var el = document.createElement("div"); alert(el.tagName); в результате увидите "DIV". Как и с текстовыми узлами, после создания узла элемента его надо добавить какому-нибудь существующему узлу элемента в дереве документа, чтобы затем его можно было увидеть на странице. Но вновь созданный элемент — это просто пустой тэг. Поэтому ему неплохо добавить какие-нибудь атрибуты и текст. Следующий пример поможет это показать. Этот текст внутри элемента DIV.
Здесь при клике по ссылке создаем новый элемент <div id="sample4">Этот текст внутри элемента DIV.</div> ... код ссылки ... var paraEl, boldEl; paraEl = document.createElement("p"); Сперва здесь создаем два новых элемента: тэги В данном случае элемент параграфа содержит три дочерних узла: текстовый узел ( Можно установить какой-нибудь атрибут любому из этих новых элементов. Не имеет значения когда его устанавливать, до или после добавления элемента в дерево документа. Например, boldEl.style.color = "#ffff00"; paraEl.appendChild(boldEl); и paraEl.appendChild(boldEl); boldEl.style.color = "#ffff00"; сделают полужирный текст красным. Другими словами, Источник: http://xhtml.ru |
||