JavaScript: Перемещение по узлам DOM-дерева

2011-01-31

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

Для облегчения понимания, изобразить эти свойства можно примерно так:

  
               parentNode
                   |
previousSibling - node - nextSibling
                  /  \
        firstChild    lastChild
 


Описание:

node.parentNode; // родительский узел
node.previousSibling; // предыдущий, на этом же уровне, узел
node.nextSibling; // следующий, на этом же уровне, узел
node.firstChild; // первый дочерний элемент
node.lastChild; // последний дочерний элемент

Пример:
Допустим у нас есть html-фрагмент такой структуры:

<h1>Список</h1>
<div>
<ul id="myList">
<li>запись 1</li>
<li>запись 2</li>
<li>запись 3</li>
<li>запись 4</li>
</ul>
<em>Комментарий к списку</em>
</div>


// найдем список, по его идентификатору
var myList = document.getElementById("myList");
// !!! Следующий код не рабочий.
// !!! Он является всего лишь демонстрационным.
// !!! (см. примечание ниже - *)
// получим 2-ю запись в списке
var secondLi = myList.firstChild.nextSibling;
// получим заголовок <h1/>
var listH1 = myList.parentNode.previousSibling;

Таким вот нехитрым способом мы можем обойти всё DOM-дерево.

* Примечание: Этот код был бы работоспособным в том случае, если бы между тегами не было лишних пробелов, энтеров, табуляций. Красивое форматирование html-кода привело к тому, что между тегами появились текстовые узлы, состоящие из пустого пространства.
Решить эту проблему можно несколькими путями:
— учитывать (игнорировать) все текстовые узлы при обходе;
— генерировать html-код без таких узлов;
— рекурсивно удалить все пустые текстовые узлы с фрагмента html-кода, перед началом работы с ним.

Теговые узлы отличаются от текстовых узлов свойством nodeType. Для тега nodeType = 1, а для текстового узла nodeType = 3.

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

// аналог parentNode
function parentTag(node) {
return node.parentNode;
}
// аналог previousSibling
function previousTag(node) {
var node = node.previousSibling;
return (node && node.nodeType!=1) ? previousTag(node) : node;
}
// аналог nextSibling
function nextTag(node) {
var node = node.nextSibling;
return (node && node.nodeType!=1) ? nextTag(node) : node;
}
// аналог firstChild
function firstChildTag(node) {
var node = node.firstChild;
return (node && node.nodeType!=1) ? nextTag(node) : node;
}
// аналог lastChild
function lastChildTag(node) {
var node = node.lastChild;
return (node && node.nodeType!=1) ? previousTag(node) : node;
}

Аналогичный пример, но с применением данных функций:

var myList = document.getElementById("myList");
// получим 2-ю запись в списке
var secondLi = nextTag(firstChildTag(myList));
// получим заголовок <h1/>
var listH1 = previousTag(parentTag(myList));

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



3 комментария на «JavaScript: Перемещение по узлам DOM-дерева»

  1. Георгий:

    Спасибо за статью! Очень классно и просто показано перемещение по узлам. В интернет-магазине для прикрутки одной функции именно это было нужно. Мне очень помогло это простое и понятное объяснение! Спасибо ещё раз! :)

  2. Айнур:

    спасибо!

  3. Елена:

    Огромное спасибо!

Добавить комментарий