Добро пожаловать!
Здесь вы можете найти ответ на интересующий вас вопрос в отрасли сайтостроения, познакомится ближе с web технологиями и web стандартами.

Статьи

Введение в DOM

Уровни Объектной Модели Документа(DOM) и их поддержка в браузерах

Краткая история вопроса. Когда возможность работы с Java Script была впервые представлена в браузерах, некоторые виды интерфейсов требовали разрешения от элементов на странице для доступа к ним посредством скриптов. Каждый производитель браузера представлял ее собственную реализацию, но де-факто назревала необходимость как-то стандартизировать основную для всех модель.

К примеру, большинство браузеров используют массив объектов Image для представления всех элементов <img /> на странице. Это дает возможность доступа к ним и управления ими с помощью Java Script. Простейшую подмену картинки можно сделать так:

document.images[3].src = "images/img2.gif"

Это устаревшая и ограниченная модель. Она дает доступ лишь к немногим типам элементов и атрибутов, например к изображениям(<img />), ссылкам(<a>) или формам(<form>).

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

Через некоторое время большинство производителей начали адаптировать свои браузеры (в основном это Internet Explorer, Netscape и Opera) к стандартам DOM, установленным консорциумом W3C.

Порядок обратной совместимости различных уровней стандартов DOM определен. Вы можете найти ссылки на DOM Level 0 ("DOM0"), которые соответствуют модели, используемой первыми браузерами, поддерживающими скрипты (в основном Internet Explorer и Netscape до 4 версии), например http://www.w3.org/TR/WD-DOM-19980318/. В 1998 году появился DOM1 и включил в себя возможности, представленные в 4 версии браузеров.

Браузеры, совместимые со стандартом

Большинство современных браузеров(начиная с 5 версии) поддерживают стандарт DOM2 или хотя бы часть его. Они также поддерживают более ранние уровни DOM, а также собственные ранее разработанные расширения для обеспечения работоспособности старых web-страниц.

Эта статья сосредоточена на стандарте DOM2. На момент написания статьи именно этот стандарт применяется к документам XML в целом и к документам HTML в частности.

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

Один из примеров — Netscape 6.0, который перестал поддерживать некоторые возможности Netscape 4 (например тэг <layer> и соответствующий ему объект Layer). Они не работают в версии 6, да и вообще никогда не соответствовали стандартам.

Еще пример — существующая и работающая в Internet Explorer конструкция document.all это его собственная возможность и никогда не соответствовала стандартам. Пока она может поддерживаться многими версиями IE, но как правило не работает в других браузерах.

Вы должны иметь в виду, что DOM кодирование тесно связано со стандартами HTML и CSS, так как DOM представляет элементы и атрибуты в соответствии с этими стандартами.

Дерево документа (Document Tree)

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

Узлы (Nodes)

Каждый их этих различных типов объектов имеет свои уникальные методы и свойства, а также обеспечивает взаимосвязь узлов (Nodes). Это общие установки методов и свойств, связанные с древообразной структурой документа. Чтобы лучше понять, как все это происходит, рассмотрим простое дерево узлов.

Пример дерева узлов

Каждый узел (Node) содержит свойства, отражающие эту структуру и позволяющие перемещаться по всем узлам дерева документа. Ниже показаны примеры взаимоотношений этих узлов:

  • NodeA.firstChild = NodeA1
  • NodeA.lastChild = NodeA3
  • NodeA.childNodes.length = 3
  • NodeA.childNodes[0] = NodeA1
  • NodeA.childNodes[1] = NodeA2
  • NodeA.childNodes[2] = NodeA3
  • NodeA1.parentNode = NodeA
  • NodeA1.nextSibling = NodeA2
  • NodeA3.previousSibling = NodeA2
  • NodeA3.nextSibling = null
  • NodeA.lastChild.firstChild = NodeA3a
  • NodeA3b.parentNode.parentNode = NodeA

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

  • insertBefore()
  • replaceChild()
  • removeChild()
  • appendChild()
  • cloneNode()

Это будет раскрыто чуть позже, а пока рассмотрим, как дерево документа отражает контент web-страницы.

Корень Документа (Document Root)

Объект document является основанием дерева документа. Он обслуживается тем же интерфейсом, что и узел (Node). У него есть дочерние узлы (child nodes), но отсутствуют родительский узел (parent node) и узлы одного с ним уровня, так как он начальный узел. В добавление к существующему Node-интерфейсу, он содержит Document-интерфейс.

Этот интерфейс содержит методы доступа к другим узлам и создания новых узлов в дереве документа. Вот некоторые из них:

  • getElementById()
  • getElementsByTagName()
  • createElement()
  • createAttribute()
  • createTextNode()

Эти методы не такие, как у других узлов. Они могут быть только у объекта document. Все указанные выше методы (кроме getElementsByTagName()) могут использоваться только объектом document, т.е. их синтаксис должен быть: document.methodName().

Объект document может содержать и некоторые другие свойства устанавливаемые более ранними версиями DOM. Например многие браузеры все еще поддерживают массивы document.images и document.links или свойства document.bgColor и document.fgColor, соответствовавшие атрибутам bgcolor и text тэга <body>.

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

Перемещение по Дереву Документа

Как уже было сказано, дерево документа отражает структуру HTML кода страницы. Каждый тэг или пара тэгов изображены как узел элемента, с узлами представляющими атрибуты или символьные данные (например, текст).

Формально, объект document имеет только один дочерний элемент (child element) устанавливаемый как document.documentElement. Для web-страниц он установлен тэгом <html>, который является корневым элементом дерева документа. У него есть дочерние элементы, установленные тэгами <head> и <body>, у которых в свою очередь, есть другие дочерние элементы.

Учитывая это и используя методы интерфейса Node можно перемещаться по дереву документа и обращаться к любому узлу этого дерева. Рассмотрим пример:

<html>
<head>
<title></title>
</head>
<body><p>Здесь какой-то текст.</p></body>
</html>

и этот код:

alert(document.documentElement.lastChild.firstChild.tagName);

который покажет "p", название тэга, представленного этим узлом. В этом коде:

  • document.documentElement - возвращает тэг <html>.
  • .lastChild - возвращает последний дочерний элемент для <html>, т.е. тэг <body>.
  • .firstChild - возвращает первый дочерний элемент внутри <body>.
  • .tagName - возвращает название тэга, в данном случае "p".

При этом всплывает очевидная проблема доступа к узлам. Достаточно изменить код документа, например, если добавить другие элементы, текст или изображения, то будет изменена структура дерева документа. И путь к этому узлу также может измениться.

Менее очевидна совместимость с доступом к узлам в некоторых браузерах. В приведенном выше примере между тэгами <body> и <p> нет ничего, даже пробелов, а теперь мы добавим между ними пару переводов строки до и после <p>:

<html>
<head>
<title></title>
</head>
<body>

<p>Здесь какой-то текст.</p>

</body>
</html>

В этом случае Netscape обнаружит в этих местах новые узлы, тогда как IE не станет этого делать. В Netscape вышенаписанный код JavaScript покажет "undefined", т.к. теперь в этом месте появился текстовый узел в виде пробела. Так как это не узел элемента, он не содержит теперь имени тэга. С другой стороны, IE не добавит узлов для таких пробелов, как здесь и по прежнему будет указывать на тэг "p".

Прямой доступ к элементам

Для этого существует удобный метод document.getElementById(). Для работы с ним необходимо добавить атрибут id тэгу "p" (да и любому другому тоже можно), тогда появляется возможность обращаться к элементу напрямую:

<p id="myP">Здесь какой-то текст.</p>

...

alert(document.getElementById("myP").tagName);

В этом случае можно не опасаться некоторой несовместимости браузеров, а также того, где в дереве документа размещен узел для тэга "p". Важно лишь помнить о том, что атрибут id должен быть уникальным в пределах этого документа.

Более сложный доступ к узлу элемента представлен методом document.getElementsByTagName(). Он возвращает массив узлов всех элементов документа, содержащих указанный HTML тэг. Для примера, сделать все ссылки на странице красными можно таким образом:

var nodeList = document.getElementsByTagName("a");
for (var i = 0; i < nodeList.length; i++)
nodeList[i].style.color = "#f00";

Типы узлов (Node Types)

Перед тем, как продолжить, более детально рассмотрим типы узлов. Как упоминалось ранее, в Объектной Модели Документа определены несколько типов узлов, но в разметке web-страницы в основном используются element, text и attribute.

Узел Element, как вы уже могли видеть, соответствует отдельному тэгу или паре тэгов в HTML коде. У него могут быть дочерние узлы (child node), которые могут быть элементами или текстовыми узлами.

Узел Text представляет обычный текст, или набор символов. У него предполагается наличие родительского узла (parent node), могут быть соседние узлы от того же родительского (sibling), но не может быть дочерних узлов (child node).

Узел Attribute отличается от вышеописанных. Он не участвует в построении дерева документа, у него нет ни родительских, ни дочерних, ни соседних узлов. Вместо этого он используется для доступа к атрибутам узла элемента. Он представляет атрибуты, определенные у HTML тэга элемента, например, атрибут href тэга <a> или src тэга <img />.

Обратите внимание, что значение атрибута всегда будет представлено текстовой строкой.

Атрибут, как узел Attribute

Существует несколько способов обращения к атрибутам элемента. Причина тому — стандарт DOM2, который был разработан для различных типов документов (т.е. XML), не только HTML. Таким образом он формально определяет тип узла для атрибута.

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

Метод document.createAttribute() дает возможность создать новый узел атрибута, которому можно присвоить значение, и применить его к узлу элемента:

var attr = document.createAttribute("myAttribute");
attr.value = "myValue";
var el = document.getElementById("myParagraph");
el.setAttributeNode(attr);

Однако, существует более простой способ доступа к атрибутам элемента, используя getAttribute() и setAttribute() методы элемента:

var el = document.getElementById("myParagraph");
el.setAttribute("myAttribute", "myValue");

Атрибуты элемента могут быть представлены и как свойства узла элемента. Другими словами, можно сделать и так:

var el = document.getElementById("myParagraph");
el.myAttribute = "myValue";

Следует обратить внимание, что Explorer 5.5 и более ранние версии не поддерживают тип узла Attribute и такой метод, как document.createAttribute() там не работает, в то время как element.getAttribute() уже как-то поддерживается. В этих браузерах получить доступ к атрибутам можно так: element.attributeName. А начиная с версии IE 6.0 уже поддерживаются узлы атрибутов, их методы и свойства.

Вы можете определять ваши атрибуты в HTML тэгах, например:

<p id="myParagraph" myAttribute="myValue">Здесь какой-то текст.</p>

...

alert(document.getElementById("myParagraph").getAttribute("myAttribute"));

увидите "myValue", а также обратите внимание: чтобы получить значение атрибута, следует использовать именно element.getAttribute(attributeName), а не element.attributeName, так как в последнем случае не все браузеры смогут определить ваши собственные атрибуты.

Атрибуты можно удалять из узла элемента, используя метод removeAttribute() или removeAttributeNode(), а также заменяя element.attributeName пустой строкой ("").

Изменение атрибутов — один из вариантов создания динамических эффектов. Например можно легко изменить выравнивание текста по правому или левому краю:

<p id="sample" align="left">Здесь какой-то текст.</p>

<p>
<a href="" onclick="document.getElementById('sample').setAttribute('align', 'left'); return false;">
Нале-во!
</a>
::
<a href="" onclick="document.getElementById('sample').setAttribute('align', 'right'); return false;">
Напра-во!
</a>
</p>

Атрибуты стилей

Большинство атрибутов для HTML тэгов примитивны, они могут определять значение свойства только конкретному тэгу. Применение стилей более интересно. Как известно, CSS может быть использовано для применения параметров стилей к одному тэгу, всем однотипным тэгам или назначено с помощью классов (class). Более того, некоторые элементы наследуют стили вышестоящих элементов.

Вы можете добавлять стили элементам. Для примера, можно изменить атрибут style или class HTML тэгу. Но этот метод добавит элементу все параметры стилей. Часто приходится только какой-нибудь один или несколько параметр стиля убрать или изменить, не трогая остальные.

Атрибут style узла элемента определен как объект со свойствами для всех возможных параметров стилей. Можно получить доступ и изменить каждый отдельный параметр стиля как угодно. Следующий пример похож на предыдущий:

Здесь какой-то текст.

Нале-во! :: Напра-во!

Но в этом случае выравнивание текста определено параметрами стилей вместо атрибута align. Вот фрагмент кода:

<p id="sample2" style="text-align:left">Здесь какой-то текст.</p>

<p>
<a href="" onclick="document.getElementById('sample1').style.textAlign = 'left'; return false;">
Нале-во!
</a>
::
<a href="" onclick="document.getElementById('sample1').style.textAlign = 'right'; return false;">
Напра-во!
</a>
</p>

Здесь следует обратить внимание на то, что названия свойств в CSS пишутся через дефис "-" (text-align), тогда как название свойства style здесь будет написано textAlign, т.е. убираем дефис и следующую за ним букву делаем прописной.

А кроме этого, если параметры стилей изначально не были присвоены элементу, им все-равно можно устанавливать значения используя DOM. Например, в коде выше атрибут style= тэга "p" можно было вообще не указывать.

Итак, ранее мы рассмотрели как можно получить доступ к любому атрибуту или свойствам стилей любого элемента на странице. Но как же динамически добавлять или удалять сами элементы и контент на странице? Или изменять контент?

Динамический контент

Изменить текстовое содержимое страницы довольно просто. Каждая непрерывная строка символов в теле HTML страницы представляется текстовым узлом. Свойство nodeValue содержит этот текст. Изменяя его значение можно соответственно изменять текст на странице.

Текстовые узлы (Text Nodes)

Следующий пример использует простейший тэг параграфа <p> и текст внутри него. Кликайте по ссылкам, чтобы изменить этот текст.

Вот текст, который будем изменять.

меняем раз :: меняем еще

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

<p id="sample2">Вот текст, который будем изменять.</p>

<p>
<a href="" 
   onclick="document.getElementById('sample2').firstChild.nodeValue = 
   'If something`s hard to do...'; return false;">меняем раз</a>
::
<a href="" 
   onclick="document.getElementById('sample2').firstChild.nodeValue = 
   '...then it`s not worth doing!'; return false;">меняем еще</a>
</p>

Ну и сразу важное замечание. У текстового узла отсутствует атрибут id, который может быть у узла элемента. Таким образом напрямую, используя метод document.getElementById() или document.getElementsByTagName(), к нему обращаться нельзя.

Зато получить доступ к текстовому узлу можно зная его родительский узел (parent node), в данном случае элемент параграфа с id="sample2". Этот узел элемента содержит один дочерний узел (child node), тот самый текстовый узел, который мы хотим изменить. Вот как это может быть изображено:

Простое дерево узлов

Итак, document.getElementById('sample2').firstChild.nodeValue используется для доступа к этому текстовому узлу и чтения или изменения его значения, т.е. текста внутри параграфа.

Важно помнить, что текстовый узел может содержать только текст. Даже простые тэги <b> и <i> внутри строки текста порождают дерево узлов элементов и текстовых узлов. Возьмем вышеописанный пример и, добавив тэги, сделаем слово "текст" полужирным.

<p id="sample3">Вот <b>текст</b>, который будем изменять.</p>

Таким образом элемент параграфа с id="sample3" теперь содержит три дочерних узла вместо одного. Это будет: текстовый узел "Вот", узел элемента для пары тэгов <b></b> и текстовый узел ", который будем изменять." Узел элемента b содержит один дочерний узел, это текстовый узел "текст". То, что получилось, можно изобразить так:

Дерево узлов изменилось

А теперь посмотрим, что получилось после изменения разметки, но если оставить скрипт из предыдущего примера без изменений.

Вот текст, который будем изменять.

меняем раз :: меняем еще

Изменение значения firstChild элемента "p" теперь приведет к замене только части текста "Вот". А если попытаетесь добавить разметку в значение текстового узла, браузер обработает ее как обычный текст, вот пример:

Вот текст, который будем изменять.

меняем раз :: меняем еще

Посмотрите на код этого примера:

<p id="sample4">Вот <b>текст</b>, который будем изменять.</p>

<p>
<a href="" 
   onclick="document.getElementById('sample4').firstChild.nodeValue = 
   '<b>If something`s</b> hard to do...'; 
   return false;">меняем раз</a>
::
<a href="" 
   onclick="document.getElementById('sample4').firstChild.nodeValue = 
   '...then it`s <i>not worth</i> doing!'; 
   return false;">меняем еще</a>
</p>

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

Свойство innerHTML

В Internet Explorer у узла элемента (element node) есть свойство innerHTML. Оно представляет собой символьные данные, между начальным и конечным тэгами и может включать другие HTML тэги. Netscape 6 тоже поддерживает это свойство, несмотря на то, что оно не входит в существующий стандарт DOM.

Используя это свойство, можно заменять все содержимое элемента параграфа из приведенного выше примера, включая HTML разметку, т.е. примерно так:

document.getElementById('sample5').innerHtml = "<b>If something`s</b> hard to do...";

Вот текст, который будем изменять.

меняем раз :: меняем еще

Пока это свойство поддерживается браузерами, его можно использовать, но следует помнить, что оно не включено в стандарт DOM.

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

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

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

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

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

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

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

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

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

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

<p id="sample6">Просто текст.</p>

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

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

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

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

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

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

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

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

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

<p id="sample7">Просто текст. новый текст 1 новый текст 2 новый текст 3 </p>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

el = document.getElementById("sample8");

if (el.hasChildNodes())
  el.removeChild(el.firstChild);

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

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

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

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

Работа с узлами элементов (Element Nodes)

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

Начнем. Вы создаете узел, используя метод document.createElement(), которому передаете название тэга, который хотите создать, например "p", "div", "table" и т.п. Этот параметр регистронезависимый, т.е. "div", "Div" и "DIV" будут означать один и тот же тэг. Только помните, браузер вернет имя тэга в верхнем регистре, если попытаетесь у него это спросить, попробуйте:

var el = document.createElement("div");
alert(el.tagName);

в результате увидите "DIV".

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

Но вновь созданный элемент — это просто пустой тэг. Поэтому ему неплохо добавить какие-нибудь атрибуты и текст. Следующий пример поможет это показать.

Этот текст внутри элемента DIV.

Добавить параграф.

Здесь при клике по ссылке создаем новый элемент P со своими дочерними узлами, который присоединяем к существующему элементу DIV.

<div id="sample4">Этот текст внутри элемента DIV.</div>

... код ссылки ...

var paraEl, boldEl;

paraEl = document.createElement("p");
boldEl = document.createElement("b");
paraEl.appendChild( document.createTextNode("Этот новый параграф с ") ); boldEl.appendChild(document.createTextNode("полужирным")); paraEl.appendChild(boldEl); paraEl.appendChild(document.createTextNode(" текстом, добавлен в DIV")); document.getElementById("sample9").appendChild(paraEl);

Сперва здесь создаем два новых элемента: тэги <p> и <b>. Затем элементу параграфа (P) добавляем новый текстовый узел со строкой "Этот новый параграф с ". Таким же образом добавляем "полужирным" элементу B. Затем добавляем этот элемент B (включая его дочерний текстовый узел) к параграфу. И следующий текстовый узел со строкой " текстом, добавлен в DIV" также добавляем к параграфу.

В данном случае элемент параграфа содержит три дочерних узла: текстовый узел (text node); узел элемента для тэга <b>; еще один текстовый узел. У элемента B только один текстовый узел. Завершающий этап — добавление вновь созданного параграфа существующему на странице тэгу <div>.

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

boldEl.style.color = "#ffff00";
paraEl.appendChild(boldEl);

и

paraEl.appendChild(boldEl);
boldEl.style.color = "#ffff00";

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

Источник: http://xhtml.ru