Введение в Объектную Модель Документа 5

Добавление узлов
Использование текстовых узлов
Соединение и разделение текстовых узлов

Добавление узлов

Добавление новых узлов также не представляет особых трудностей. Ранее мы рассмотрели, как изменять узлы атрибутов и применять их к элементам, а также, как изменять текстовые узлы в дереве документа (свойство innerHTML в расчет не берем).

Первый шаг к созданию узла объекта того типа, который вам нужен — это один из вариантов: document.createElement(), document.createAttribute() или document.createTextNode(). Однако для атрибутов вы можете захотеть создать узел элемента и сразу определить ему атрибут (помните, что IE стал поддерживать createAttribute() только начиная с 6 версии).

Использование текстовых узлов

Начнем с текстового узла. Этот пример кода показывает как создать текстовый узел и присвоить ему какое-то значение:

var myTextNode = document.createTextNode("ваш текст");

Теперь у вас есть текстовый узел. Но он не является частью дерева документа. Чтобы он появился на странице, его нужно сделать дочерним (child) по отношению к какому-нибудь уже существующему внутри дерева узлу. Его нельзя присоединить к другому текстовому узлу, так как текстовые узлы не могут содержать дочерние узлы. Узлы атрибутов не являются частью дерева документа, поэтому и к ним присоединить текстовый узел нельзя. Тогда в нашем распоряжении остаются узлы элементов.

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

Метод appendChild() можно использовать, чтобы добавить новый текст (текстовый узел) в узел параграфа. При этом удалить последний из добавленных узлов можно с помощью метода removeChild().

Просто текст.

Добавить текстовый узел :: Удалить текстовый узел

А теперь рассмотрим этот фрагмент кода:

Просто текст.



... вызов функции добавления узла ...

var text = document.createTextNode(" новый текст " + (++counter1));
var el = document.getElementById("sample1");
el.appendChild(text);

... вызов функции удаления последнего (lastChild) узла ...

var el = document.getElementById("sample1");
if (el.hasChildNodes())
el.removeChild(el.lastChild);

Добавление текста — это просто: надо создать новый текстовый узел, определить узел элемента параграфа и вызвать метод appendChild(), чтобы добавить текстовый узел в конец его массива дочерних узлов (childNodes). Глобальную переменную counter добавляем в текст чтобы отличить каждый новый текстовый узел в окне браузера.

Удаление текста происходит также просто: removeChildNode(). Только в отличие от добавления обязательно нужно указывать какой из дочерних узлов должен быть удален. Здесь мы используем свойство элемента lastChild, которое всегда указывает на последний узел в массиве дочерних узлов элемента (childNodes). Таким способом можно удалить даже текст, который мог уже существовать в HTML-коде внутри тэга

еще до добавления новых текстовых узлов.

Стоит обрать внимание на метод hasChildNodes(), который просто возвращает true или false, показывая, содержит ли данный узел какие-нибудь дочерние узлы. Его следует использовать, чтобы избежать ошибок при вызове removeChild когда у узла может не быть дочерних узлов.

Соединение и разделение текстовых узлов

В вышеприведенном примере текстовые узлы добавлялись как самостоятельные дочерние узлы. Но если вписать текст в HTML-код,

Просто текст. новый текст 1 новый текст 2 новый текст 3

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

Оно не всегда может быть тем, что вы хотели получить. Иногда вам может понадобиться комбинировать текстовые узлы, таким образом, чтобы новый, динамически добавляемый контент включался в существующий статический HTML-код.

Такую возможность предоставляет метод normalize(). Вызов этого метода "подчищает" дерево узлов, собирая соседние текстовые узлы в единый текстовый узел и удаляя пустые.

Совместимость браузеров

Пример нормализации параграфа, который разберем далее, не будет работать в Internet Explorer 5.5 и более ранних версиях, т.к. этот браузер не поддерживает метод normalize(). Поддержка это метода включена только начиная с 6 версии IE.

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

Какой-то текст внутри параграфа.

Добавить текст :: Удалить текст :: Количество дочерних узлов :: Нормализовать элемент

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

... элемент для нормализации ...

el = document.getElementById("sample2");
el.normalize();

... показываем количество дочерних элементов ...

el = document.getElementById("sample2");
alert(el.childNodes.length);

Можно разделить текстовый узел на два отдельных, используя метод splitText(). Он пригодится, если вы захотите динамически изменить слово или фразу или вставить какой-нибудь элемент в текстовую строку.

Рассмотрим следующий пример, где кликнув по ссылке удалим первый дочерний элемент параграфа. Сперва возьмем целое предложение. Кликнув по ссылке "отделить слово", отделим первое слово в тексте, а кликнув после по ссылке "удалить первый узел", уберем только это слово из предложения. Кликнув по ссылке "сбросить" возвращаемся в исходное состояние.

Какой-то текст внутри параграфа.

Отделить слово :: Удалить первый узел :: Сбросить

Вот как это делается:

... отделяем первое слово ...

el = document.getElementById("sample3");
if (el.hasChildNodes()) {
text = el.firstChild;
i = text.nodeValue.indexOf(" ");
if (i >= 0)
text.splitText(i + 1);
}

... удаляем первый текстовый узел ...

el = document.getElementById("sample3");
if (el.hasChildNodes())
el.removeChild(el.firstChild);

... возвращаем пример в исходное состояние ...

el = document.getElementById("sample3");
while (el.hasChildNodes())
el.removeChild(el.firstChild);
text = document.createTextNode(
"Какой-то текст внутри параграфа.");
el.appendChild(text);

Теперь пара замечаний: во-первых, для текстового узла nodeValue это просто строка. Метод splitText() полагается на начальное значение, которое покажет откуда можно начинать разбиение. Метод indexOf() используется для поиска в строке первого от ее начала пробела, чтобы передать его методу splitText().

Во-вторых, в коде для возврата в исходное состояние просто удаляются все дочерние узлы элемента параграфа, а затем добавляется исходный текст как единый текстовый узел.



Много комментариев (3) к “Введение в Объектную Модель Документа 5”

  1. Ekho :

    Было бы неплохо ещё упомянуть про insertBefore()


  2. ZZZubec :

    Спасибки, очень полезно.


  3. Plus :

    С insertBefore работать так:

    var b = document.createElement(”FONT”);
    b.color = “green”;
    b.appendChild(document.createTextNode(”зелёный”));

    var a = document.createElement(”DIV”);
    a.appendChild(document.createTextNode(”\”Вставленный текст “));
    var c = document.createTextNode(”\”");
    a.appendChild(c);
    a.insertBefore(b, c);

    В результате “зелёный” вставится перед замыкающими кавычками.