Навигация по DOM-элементам

Все операции с DOM начинаются с объекта document. Это главная «точка входа» в DOM.

Основные ссылки, по которым можно переходить между узлами DOM:

 

documentElement и body

Самые верхние элементы дерева доступны напрямую из document.

<HTML> = document.documentElement

Первая точка входа – document.documentElement. Это свойство ссылается на DOM-объект для тега <html>.

<BODY> = document.body

Вторая точка входа – document.body, который соответствует тегу <body>.

В современных браузерах (кроме IE8-) также есть document.head – прямая ссылка на <head>

 

Дети: childNodes, firstChild, lastChild

Псевдо-массив childNodes хранит все дочерние элементы, включая текстовые.

Пример ниже последовательно выведет дочерние элементы document.body:

<!DOCTYPE HTML>
<html>

<body>
  <div>Начало</div>

  <ul>
    <li>Информация</li>
  </ul>

  <div>Конец</div>

  <script>
    for (var i = 0; i < document.body.childNodes.length; i++) {
      alert( document.body.childNodes[i] ); // Text, DIV, Text, UL, ..., SCRIPT
    }
  </script>
  ...
</body>

</html>
Обратим внимание на маленькую деталь. Если запустить пример выше, то последним будет выведен элемент <script>. На самом-то деле в документе есть ещё текст (обозначенный троеточием), но на момент выполнения скрипта браузер ещё до него не дошёл.

Свойства firstChild и lastChild обеспечивают быстрый доступ к первому и последнему элементу.

При наличии дочерних узлов всегда верно:

elem.childNodes[0] === elem.firstChild
elem.childNodes[elem.childNodes.length - 1] === elem.lastChild

 

Коллекции – не массивы

DOM-коллекции, такие как childNodes и другие, которые мы увидим далее, не являются JavaScript-массивами.

В них нет методов массивов, таких как forEach, map, push, pop и других.

var elems = document.documentElement.childNodes;

elems.forEach(function(elem) { // нет такого метода!
  /* ... */
});

Именно поэтому childNodes и называют «коллекция» или «псевдомассив».

Можно для перебора коллекции использовать обычный цикл for(var i=0; i<elems.length; i++) …

Применить метод массива через call/apply:

var elems = document.documentElement.childNodes;

[].forEach.call(elems, function(elem) {
  alert( elem ); // HEAD, текст, BODY
});

При помощи Array.prototype.slice сделать из коллекции массив:

var elems = document.documentElement.childNodes;
elems = Array.prototype.slice.call(elems); // теперь elems - массив

elems.forEach(function(elem) {
  alert( elem.tagName ); // HEAD, текст, BODY
});

 

Навигация только по элементам

Для того, чтобы в навигации по DOM-дереву не попадались текстовые узлы есть ссылки:

Зачем parentElement? Неужели бывают родители не-элементы?
Свойство elem.parentNode возвращает родитель элемента.
Оно всегда равно parentElement, кроме одного исключения:

alert( document.documentElement.parentNode ); // document
alert( document.documentElement.parentElement ); // null

 

Особые ссылки для таблиц

TABLE

  • table.rows – коллекция строк TR таблицы.
  • table.caption/tHead/tFoot – ссылки на элементы таблицы CAPTION, THEAD, TFOOT.
  • table.tBodies – коллекция элементов таблицы TBODY, по спецификации их может быть несколько.

THEAD/TFOOT/TBODY

  • tbody.rows – коллекция строк TR секции.

TR

  • tr.cells – коллекция ячеек TD/TH
  • tr.sectionRowIndex – номер строки в текущей секции THEAD/TBODY
  • tr.rowIndex – номер строки в таблице

TD/TH

  • td.cellIndex – номер ячейки в строке

Пример использования:

<table>
  <tr>
    <td>один</td> <td>два</td>
  </tr>
  <tr>
    <td>три</td>  <td>четыре</td>
  </tr>
</table>

<script>
var table = document.body.children[0];

alert( table.rows[0].cells[0].innerHTML ) // "один"
</script>

Спецификация: HTML5: tabular data.

Источник: https://learn.javascript.ru/traversing-dom