Родительские и дочерние элементы древовидного элемента управления
Любой элемент в элементе управления деревом (CTreeCtrl) может содержать список дочерних элементов, которые называются дочерними элементами, связанными с ним. Элемент с одним или несколькими дочерними элементами называется родительским элементом. Дочерний элемент отображается под родительским элементом и отступен, чтобы указать, что он подчинен родительскому элементу. Элемент, не имеющий родительского элемента, находится в верхней части иерархии и называется корневым элементом.
В любое время состояние списка дочерних элементов родительского элемента может быть развернуто или свернуто. При развертывании состояния дочерние элементы отображаются под родительским элементом. При сворачивании дочерние элементы не отображаются. Список автоматически переключается между развернутыми и свернутыми состояниями, когда пользователь дважды щелкает родительский элемент или, если родительский элемент имеет стиль TVS_HASBUTTONS , когда пользователь нажимает кнопку, связанную с родительским элементом. Приложение может развернуть или свернуть дочерние элементы с помощью функции «Развернуть «.
Элемент управления «Дерево» добавляется путем вызова функции-члена InsertItem . Эта функция возвращает дескриптор типа HTREEITEM , который однозначно идентифицирует элемент. При добавлении элемента необходимо указать дескриптор родительского элемента нового элемента. Если указать значение NULL или значение TVI_ROOT вместо родительского элемента в структуре TVINSERTSTRUCT или параметре hParent , элемент добавляется в качестве корневого элемента.
Элемент управления деревом отправляет сообщение TVN_ITEMEXPANDING уведомления, когда список дочерних элементов родительского элемента будет развернут или свернут. Уведомление дает возможность предотвратить изменение или задать любые атрибуты родительского элемента, зависящие от состояния списка дочерних элементов. После изменения состояния списка элемент управления деревом отправляет сообщение TVN_ITEMEXPANDED уведомления.
При развертывании списка дочерних элементов он отступит относительно родительского элемента. Можно задать количество отступов с помощью функции-члена SetIndent или получить текущую сумму с помощью функции-члена GetIndent.
Что такое дочерние элементы html
Селекторы дочерних элементов отличаются от селекторов потомков тем, что позволяют выбрать элементы только первого уровня вложенности. Например:
Заголовок
Текст
Хотя вложенными в элемент body элементами являются целых три — h2, div, p, но дочерними из них являются только два — div и h2, так как они находятся в первом уровне вложенности. А элемент p находится на втором уровне вложенности, так как вложен внутрь элемента div, а не просто элемента body.
Для обращения к дочерним элементам используется знак угловой скобки:
Селекторы атрибутов в CSS3 .article > pАннотация к статье
Текст статьи
В блоке с классом article есть два параграфа. Селектор .article > p выбирает только те параграфы, который находятся непосредственно в блоке article:
Если бы мы использовали другой селектор без символа >
.article p
Тогда стиль бы применялся ко всем параграфам на всех уровнях вложенности:
Навигация по DOM-элементам
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице https://learn.javascript.ru/dom-navigation.
DOM позволяет делать что угодно с HTML-элементом и его содержимым, но для этого нужно сначала нужный элемент получить.
Доступ к DOM начинается с объекта document . Из него можно добраться до любых узлов.
Так выглядят основные ссылки, по которым можно переходить между узлами DOM:

Посмотрим на них повнимательнее.
Сверху documentElement и body
Самые верхние элементы дерева доступны напрямую из document .
= document.documentElement Первая точка входа – document.documentElement . Это свойство ссылается на DOM-объект для тега . = document.body Вторая точка входа – document.body , который соответствует тегу .
В современных браузерах (кроме IE8-) также есть document.head – прямая ссылка на
Есть одна тонкость: document.body может быть равен null
Нельзя получить доступ к элементу, которого ещё не существует в момент выполнения скрипта.
В частности, если скрипт находится в , то в нём недоступен document.body .
Поэтому в следующем примере первый alert выведет null :
В DOM активно используется null
В мире DOM в качестве значения, обозначающего «нет такого элемента» или «узел не найден», используется не undefined , а null .
Дети: childNodes, firstChild, lastChild
Здесь и далее мы будем использовать два принципиально разных термина.
- Дочерние элементы (или дети) – элементы, которые лежат непосредственно внутри данного. Например, внутри обычно лежат и .
- Потомки – все элементы, которые лежат внутри данного, вместе с их детьми, детьми их детей и так далее. То есть, всё поддерево DOM.
Псевдо-массив childNodes хранит все дочерние элементы, включая текстовые.
Пример ниже последовательно выведет дочерние элементы document.body :
Обратим внимание на маленькую деталь. Если запустить пример выше, то последним будет выведен элемент . На самом-то деле в документе есть ещё текст (обозначенный троеточием), но на момент выполнения скрипта браузер ещё до него не дошёл.
Пробельный узел будет в итоговом документе, но его ещё нет на момент выполнения скрипта.
Список детей – только для чтения!
Скажем больше – все навигационные свойства, которые перечислены в этой главе – только для чтения. Нельзя просто заменить элемент присвоением childNodes[i] = . .
Изменение DOM осуществляется другими методами, которые мы рассмотрим далее, все навигационные ссылки при этом обновляются автоматически.
Свойства 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 и называют «коллекция» или «псевдомассив».
Это возможно, основных варианта два:
-
Применить метод массива через call/apply :
var elems = document.documentElement.childNodes; [].forEach.call(elems, function(elem) < alert( elem ); // HEAD, текст, BODY >);
var elems = document.documentElement.childNodes; elems = Array.prototype.slice.call(elems); // теперь elems - массив elems.forEach(function(elem) < alert( elem.tagName ); // HEAD, текст, BODY >);
Нельзя перебирать коллекцию через for..in
Ранее мы говорили, что не рекомендуется использовать для перебора массива цикл for..in .
Коллекции – наглядный пример, почему нельзя. Они похожи на массивы, но у них есть свои свойства и методы, которых в массивах нет.
К примеру, код ниже должен перебрать все дочерние элементы . Их, естественно, два: и . Максимум, три, если взять ещё и текст между ними.
Но в примере ниже alert сработает не три, а целых 5 раз!
var elems = document.documentElement.childNodes; for (var key in elems) < alert( key ); // 0, 1, 2, length, item >
Цикл for..in выведет не только ожидаемые индексы 0 , 1 , 2 , по которым лежат узлы в коллекции, но и свойство length (в коллекции оно enumerable), а также функцию item(n) – она никогда не используется, возвращает n-й элемент коллекции, проще обратиться по индексу [n] .
В реальном коде нам нужны только элементы, мы же будем работать с ними, а служебные свойства – не нужны. Поэтому желательно использовать for(var i=0; i
Соседи и родитель
Доступ к элементам слева и справа данного можно получить по ссылкам previousSibling / nextSibling .
Родитель доступен через parentNode . Если долго идти от одного элемента к другому, то рано или поздно дойдёшь до корня DOM, то есть до document.documentElement , а затем и document .
Навигация только по элементам
Навигационные ссылки, описанные выше, равно касаются всех узлов в документе. В частности, в childNodes сосуществуют и текстовые узлы и узлы-элементы и узлы-комментарии, если есть.
Но для большинства задач текстовые узлы нам не интересны.
Поэтому посмотрим на дополнительный набор ссылок, которые их не учитывают:

Эти ссылки похожи на те, что раньше, только в ряде мест стоит слово Element :
- children – только дочерние узлы-элементы, то есть соответствующие тегам.
- firstElementChild , lastElementChild – соответственно, первый и последний дети-элементы.
- previousElementSibling , nextElementSibling – соседи-элементы.
- parentElement – родитель-элемент.
Зачем parentElement ? Неужели бывают родители не-элементы?
Свойство elem.parentNode возвращает родитель элемента.
Оно всегда равно parentElement , кроме одного исключения:
alert( document.documentElement.parentNode ); // document alert( document.documentElement.parentElement ); // null
Иногда это имеет значение, если хочется перебрать всех предков и вызвать какой-то метод, а на документе его нет.
Модифицируем предыдущий пример, применив children вместо childNodes .
Теперь он будет выводить не все узлы, а только узлы-элементы:
Всегда верны равенства:
elem.firstElementChild === elem.children[0] elem.lastElementChild === elem.children[elem.children.length - 1]
В IE8- поддерживается только children
Других навигационных свойств в этих браузерах нет. Впрочем, как мы увидим далее, можно легко сделать полифил, и они, всё же, будут.
В IE8- в children присутствуют узлы-комментарии
С точки зрения стандарта это ошибка, но IE8- также включает в children узлы, соответствующие HTML-комментариям.
Это может привести к сюрпризам при использовании свойства children , поэтому HTML-комментарии либо убирают либо используют фреймворк, к примеру, jQuery, который даёт свои методы перебора и отфильтрует их.
Особые ссылки для таблиц
У конкретных элементов DOM могут быть свои дополнительные ссылки для большего удобства навигации.
Здесь мы рассмотрим таблицу, так как это важный частный случай и просто для примера.
В списке ниже выделены наиболее полезные:
- table.rows – коллекция строк TR таблицы.
- table.caption/tHead/tFoot – ссылки на элементы таблицы CAPTION , THEAD , TFOOT .
- table.tBodies – коллекция элементов таблицы TBODY , по спецификации их может быть несколько.
- tbody.rows – коллекция строк TR секции.
- tr.cells – коллекция ячеек TD/TH
- tr.sectionRowIndex – номер строки в текущей секции THEAD/TBODY
- tr.rowIndex – номер строки в таблице
- td.cellIndex – номер ячейки в строке
один два три четыре
Даже если эти свойства не нужны вам прямо сейчас, имейте их в виду на будущее, когда понадобится пройтись по таблице.
Конечно же, таблицы – не исключение.
Аналогичные полезные свойства есть у HTML-форм, они позволяют из формы получить все её элементы, а из них – в свою очередь, форму. Мы рассмотрим их позже.
Интерактивное путешествие
Для того, чтобы убедиться, что вы разобрались с навигацией по DOM-ссылкам – вашему вниманию предлагается интерактивное путешествие по DOM.
Ниже вы найдёте документ (в ифрейме), и кнопки для перехода по нему.
Изначальный элемент – . Попробуйте по ссылкам найти «информацию». Или ещё чего-нибудь.
Вы также можете открыть документ в отдельном окне и походить по нему в браузерной консоли разработчика, чтобы лучше понять разницу между показанным там DOM и реальным.
Свойство children
Свойство children хранит в себе псевдомассив дочерних элементов. Дочерними элементами считаются все теги, которые непосредственно расположены внутри блока.
Синтаксис
элемент.children;
Пример
Давайте переберем в цикле всех потомков элемента и выведем их содержимое:
1
2
3
4
5
let parent = document.querySelector(‘#parent’); let elems = parent.children; for (let elem of elems) < console.log(elem.textContent); >
Смотрите также
- свойство childNodes ,
содержащее в себе псевдомассив узлов
