Навигацию по дереву документа можно начинать с любого узла, для которого мы знаем идентификатор, присваиваемый ему в качестве значения атрибута ID. Ссылку на такой узел можно получить с помощью метода getElementById(). Следующая строка кода присваивает переменной oList ссылку на список:
var oList = document.getElementById("components")
Приведем пример кода внутри тега BODY:
<!-- пример pr28 -->
<p id="myP">Hello, World!</p>
<script type="text/javascript">
alert(document.getElementById("myP").innerHTML);
//выведет на экран фразу Hello World!
var str = "";
str += document.getElementById("myP").nodeName + '\n';
str += document.getElementById("myP").nodeValue + '\n';
str += document.getElementById("myP").nodeType + '\n';
alert(str);//выведет «P null 1»
</script>
На экран вывелось nodevalue, равное null, потому что на самом деле внутри узла <p> есть еще один текстовый узел, в котором содержится искомый текст «Hello, World!». Для того чтобы получить доступ к этому значению, используется следующая строка:
document.getElementById("myP").childNodes[0].nodeValue;
Стартуя с некоторого узла, можно бродить по дереву, используя свойства узлов. Так, узлы-элементы и текстовые узлы имеют свойство parentNode, которое возвращает ссылку на родительский узел. Возьмем для примера узел (объект) oList. Ссылку на родительский элемент DIV этого узла можно получить следующий образом:
var oParent = oList.parentNode
Узлы, являющиеся потомками некоторого узла, входят в состав коллекции childNodes этого узла. (Узлы-атрибуты составляют отдельную коллекцию attributes) К каждому из них можно обращаться по индексу массива. Например, строка кода
var oItem1 = oList.childNodes[1]
присваивает переменнойoItem1ссылку на элемент<LI>CSS</LI> нашего списка. Именно этот элемент представлен в DOM как узел childNodes[1]узла oList. Первый (childNodes[0]) и последний элементы коллекции имеют специальные имена: firstChild и lastChild. Эти имена являются свойствами родительского узла. Каждый из элементов коллекции имеет свойства previousSibling и nextSibling. Эти свойства хранят ссылку на ближайщих братков элемента - предыдущий и последующий элементы коллекции (возвращают null, когда братков нет). Так, элементchildNodes[1]является свойством nextSibling элемента childNodes[0] и свойствомpreviousSibling элемента childNodes[2]. Используя эти свойства, мы можем получить ссылку на узел childNodes[1]любым из следующих способов:
oList.firstChild.nextSiblingoList
.childNodes[2].previousSibling
Ссылка на более удаленные узлы как по горизонтали, так и по вертикали дерева формируется путем слияния ссылок на ближайших родственников по стандартным правилам объектно-ориентированного программирования. Так,
oList.childNodes[1].firstChild
является ссылкой на текст"CSS"элемента <LI>CSS</LI> нашего списка.
На следующей диаграмме приведены имена всех ближайших родственников некоторого узла oNode.
Заметим, что все описанные выше свойства узлов (parentNode, firstChild, lastChild, nextSibling и previousSibling), необходимые для навигации по дереву документа, являются свойствами только для чтения. Помимо них, узлы имеют еще ряд свойств, которые мы сейчас опишем.
Чтобы проиллюстрировать иерархию узлов DOM, приведем пример:
<!-- пример 29: иерархия узлов DOM-->
<table>
<tr id="firstRow">
<td id="firstCell"></td>
<td id="currentNode" width="10">
<span id="spanNode">
text</span>
<p id="pNode">text</p>
</td>
<td id="lastCell"></td>
</tr>
</table>
<script type="text/javascript">
alert(document.getElementById("currentNode").parentNode.id);
//выведет на экран firstRow
alert(document.getElementById(currentNode").childNodes[0].id);
//выведет на экран spanNode
alert(document.getElementById("currentNode").firstChild.id);
//выведет на экран spanNode
alert(document.getElementById("currentNode").lastChild.id);
//выведет на экран pNode
alert(document.getElementById("currentNode").previousSibling.id);
//выведет на экран firstCell
alert(document.getElementById("currentNode").nextSibling.id);
//выведет на экран lastCell
alert(document.getElementById("currentNode").attributes["width"].
value);
//выведет на экран 10
alert(document.getElementById("currentNode").ownerDocument.
nodeName);
//выведет на экран #document
</script>
Помимо метода getElementById(), существует несколько других, облегчающих доступ к необходимым элементам документа. Метод getElementsByName() возвращает коллекцию элементов с определенным атрибутом name, а метод getElementsByTagName() возвращает коллекцию элементов (тегов) с одинаковым именем. Оба метода принадлежат объекту document.
Создание новых узлов
DOM поддерживает следующие методы, связанные с созданием новых узлов:
createElement(tagName) – создает узел (тег) с именем, переданным в параметре;
createTextNode(string) – создает текстовый узел с содержанием, переданным в параметре.
createAttribute(name) – создает атрибут с именем, переданным в параметре;
createComment(string) – создает HTML-комментарий в виде <!--string -->, текст комментария передается в параметре;
createDocumentFragment() – создает новый документ для хранения новых узлов;
Все методы принадлежат объекту document.
Технику создания новых элементов обсудим на примере. Предположим, что мы хотим добавить к существующему списку элемент: <LI>XML</LI>. Этому элементу в DOM соответствуют два узла: узел-элемент<LI>и текстовый узел"XML". Следовательно, нужно создать два новых узла с помощью методов createElement()и createTextNode() объекта document.
var oItem = document.createElement("LI")
Метод возвращает ссылку на созданный им объект. Элемент <LI> находится в памяти, но пока не входит в состав текущего документа. Чтобы элемент стал частью документа, его надо добавить к существующим узлам с помощью методов insertBefore() или appendChild().
Метод createTextNode() используется для создания текстового узла. Строковый параметр задает значение свойства nodeValue текстового узла. Например:
var oText = document.createTextNode("XML")
Cтрока кода создает новый текстовый узел"XML". Метод возвращает ссылку на созданный им объект. Для того, чтобы cозданный текст стал частью текущего документа, его надо присоединить к существующим узлам документа с помощью методов appendChild(), replaceNode() или insertBefore().
Итак, мы создали два новых узла: узел-элемент<LI>и текстовый узел"XML". Теперь займемся встраиванием этих узлов в документ.
Добавление узлов в документ
Для добавления узлов в документ используются методы:
insertBefore(newChild, referenceChild);
appendChild(newChild).
Оба эти метода добавляют новый узел newChild к существующим в документе. Метод appendChild() добавляет новый узел после узла, который его активизировал. Например, строка кода:
oItem.appendChild(oText)
добавляет узел oText к узлу oItem. Отметим, что метод возвращает ссылку на объект, который он добавляет. В нашем случае это объект oItem.firstChild. Теперь мы имеет в памяти элемент (веточку дерева из двух узлов)
<LI>XML</LI>
Пора вставлять эту веточку в текущий документ. Если мы хотим вставить ее в самый конец нашего списка, то надо, как и выше, использовать метод appendChild():
oList.appendChild(oItem)
Поскольку узелoList, к которому мы присоединили узел oItem, является частью текущего документа, созданный нами элемент списка также становится частью документа. Теперь наш список выглядит так:
<UL ID="components">
<LI>HTML</LI>
<LI>CSS</LI>
<LI>Javascript</LI>
<LI>XML</LI>
</UL>
Обсудим теперь как можно вставить созданный нами элемент списка не в конец, а, скажем, после элемента списка<LI>HTML</LI>. Сделать это можно с помощью методаinsertBefore(). Метод insertBefore() добавляет новый узел перед дочерним узлом, указанным в параметре referenceChild.В отличие от метода appendChild(), методinsertBefore()позволяет указать, в какое место коллекции childNodes будущего родительского узла будет вставлен новый узел. Как следует из названия, метод требует ссылки на узел, перед которым он будет вставлен. Итак, код
var oBrother = oList.firstChild.nextSiblingoList.insertBefore(oItem, oBrother)
добавляет в коллекцию childNodes узла oList узел oItem сразу после узла childNodes[0]. В качестве первого параметра метод insertBefore()принимает ссылку на узел, который мы хотим добавить, а в качестве второго параметра - ссылку на узел, перед которым будет вставлен новый узел. Второй параметр метода является необязательным. Если родительский узел не имеет деток, то задавать его не следует. Если родительский узел имеет деток, а второй параметр не задан, то добавляемый узел становится самым последним среди деток родительского объекта. Метод insertBefore()возвращает ссылку на вставленный в документ объект.
Теперь наш первоначальный список выглядит так:
<UL ID="components">
<LI>HTML</LI>
<LI>XML</LI>
<LI>CSS</LI>
<LI>Javascript</LI>
</UL>
Пример:
<!-- пример pr30: -->
<html>
<head>
<title>A Simple Page</title>
<script type="text/javascript">
function modify() {
var newElem = document.createElement("p");
newElem.id = "newP";
var newText = document.createTextNode("This is the second paragraph.");
newElem.appendChild(newText);
document.body.appendChild(newElem);
document.getElementById("emphasis1").childNodes[0].nodeValue = "first ";
}
</script>
</head>
<body>
<button onClick="modify()">Add/Replace Text</button>
<p id="paragraph1">This is the <em id="emphasis1">one and only</em> paragraph on the
page.</p>
</body>
</html>
Продолжим обсуждение методов редактирования дерева документа.
Копирование: метод cloneNode()
В качестве параметра можно указать, должны ли копироваться все дочерние узлы, по умолчанию значение параметра false. Если оно равно false, то копируется только тот узел, который активизирует метод.
Если мы хотим скопировать некоторый узел вместе со всеми его атрибутами, то надо воспользоваться методом cloneNode(true). Например, строка кода:
var oClone = oList.cloneNode(true)
копирует в память всю ветвь дерева, начинающуюся на узле oList, то есть весь список целиком. Метод возвращает ссылку на копию узла.