# Свойства узлов: тип, тег и содержимое В этой главе мы познакомимся с основными, самыми важными свойствами, которые отвечают за тип DOM-узла, тег и содержимое. [cut] ## Классы, иерархия DOM Самое главное различие между DOM-узлами -- разные узлы являются объектами различных классов. Поэтому, к примеру, у узла, соответствующего тегу `` -- одни свойства, у `
` -- другие, у `` -- третьи. Есть и кое-что общее, за счёт наследования. Классы DOM образуют иерархию. Основной объект в ней: [Node](http://dom.spec.whatwg.org/#interface-node), от которого наследуют остальные: На рисунке выше изображены основные классы: Узнать класс узла очень просто -- достаточно привести его к строке, к примеру, вывести: ```js //+ run alert( document.body ); // [object HTMLBodyElement] ``` Детальное описание свойств и методов каждого DOM-класса дано в [спецификации](http://www.whatwg.org/specs/web-apps/current-work/multipage/). Например, [The input element](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#the-input-element) описывает класс, соответствующий ``, включая [interface HTMLInputElement](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#htmlinputelement), который нас как раз и интересует. Вот из него выдержка: ```js interface HTMLInputElement : HTMLElement { attribute DOMString accept; attribute DOMString alt; attribute DOMString autocomplete; attribute boolean autofocus; ... attribute DOMString value; ... void select(); ... } ``` При описании свойств и методов используется не JavaScript, а специальный язык [IDL](https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D1%8F_%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81%D0%BE%D0%B2) (Interface Definition Language), который достаточно легко понять "с ходу". В частности, выше мы видим, что: Далее в этом разделе мы поговорим о самых главных свойствах узлов DOM, которые используются наиболее часто. ## Тип: nodeType Тип узла содержится в его свойстве `nodeType`. Как правило, мы работаем всего с двумя типами узлов: На самом деле типов узлов гораздо больше. Строго говоря, их 12, и они описаны в спецификации с древнейших времён, см. DOM Уровень 1: ```js interface Node { // NodeType const unsigned short ELEMENT_NODE = 1; const unsigned short ATTRIBUTE_NODE = 2; const unsigned short TEXT_NODE = 3; const unsigned short CDATA_SECTION_NODE = 4; const unsigned short ENTITY_REFERENCE_NODE = 5; const unsigned short ENTITY_NODE = 6; const unsigned short PROCESSING_INSTRUCTION_NODE = 7; const unsigned short COMMENT_NODE = 8; const unsigned short DOCUMENT_NODE = 9; const unsigned short DOCUMENT_TYPE_NODE = 10; const unsigned short DOCUMENT_FRAGMENT_NODE = 11; const unsigned short NOTATION_NODE = 12; ... } ``` В частности, тип "Элемент" `ELEMENT_NODE` имеет номер 1, а "Текст" `TEXT_NODE` -- номер 3. Например, выведем все узлы-потомки `document.body`, *являющиеся элементами*: ```html
Читатели:
``` Тип узла можно только читать, изменить его невозможно. ## Тег: nodeName и tagName Существует целых два свойства: `nodeName` и `tagName`, которые содержат название(тег) элемента узла. **Название HTML-тега всегда находится в верхнем регистре.** Например, для `document.body`: ```js //+ run alert( document.body.nodeName ); // BODY alert( document.body.tagName ); // BODY ``` [smart header="В XHTML `nodeName` может быть не в верхнем регистре"] У браузера есть два режима обработки документа: HTML и XML-режим. Обычно используется режим HTML. XML-режим включается, когда браузер получает XML-документ через `XMLHttpRequest`(технология AJAX) или при наличии заголовка `Content-Type: application/xml+xhtml`. В XML-режиме сохраняется регистр и `nodeName` может выдать "body" или даже "bOdY" -- в точности как указано в документе. XML-режим используют очень редко. [/smart] ### Какая разница между tagName и nodeName ? Разница отражена в названиях свойств, но неочевидна. Таким образом, при помощи `tagName` мы можем работать только с элементами, а `nodeName` может что-то сказать и о других типах узлов. Например, сравним `tagName` и `nodeName` на примере узла-комментария и объекта `document`: ```html ``` При работе с элементами, как это обычно бывает, имеет смысл использовать свойство `tagName` -- оно короче. ## innerHTML: содержимое элемента Свойство `innerHTML` описано в спецификации HTML 5 -- embedded content. Оно позволяет получить HTML-содержимое элемента в виде строки. В `innerHTML` можно и читать и писать. Пример выведет на экран все содержимое `document.body`, а затем заменит его на другое: ```html

Параграф

Div
``` Значение, возвращаемое `innerHTML` -- всегда валидный HTML-код. При записи можно попробовать записать что угодно, но браузер исправит ошибки: ```html ``` Свойство `innerHTML` -- одно из самых часто используемых. ### Тонкости innerHTML `innerHTML` не так прост, как может показаться, и таит в себе некоторые тонкости, которые могут сбить с толку новичка, а иногда и опытного программиста. Ознакомьтесь с ними. Даже если этих сложностей у вас *пока* нет, эта информация отложится где-то в голове и поможет, когда проблема появится. [warn header="Для таблиц в IE9- -- `innerHTML` только для чтения"] В Internet Explorer версии 9 и ранее, innerHTML доступно только для чтения для элементов `COL`, `COLGROUP`, `FRAMESET`, `HEAD`, `HTML`, `STYLE`, `TABLE`, `TBODY`, `TFOOT`, `THEAD`, `TITLE`, `TR`. В частности, в IE9- запрещена запись в `innerHTML` для любых табличных элементов, кроме ячеек (`TD/TH`). [/warn] [warn header="Добавление `innerHTML+=` осуществляет перезапись"] Синтаксически, можно добавить текст к `innerHTML` через `+=`: ```js chatDiv.innerHTML += "
Привет !
"; chatDiv.innerHTML += "Как дела?"; ``` На практике этим следует пользоваться с большой осторожностью, так как фактически происходит не добавление, а перезапись:
  1. Удаляется старое содержание
  2. На его место становится новое значение `innerHTML`.
Так как новое значение записывается с нуля, то **все изображения и другие ресурсы будут перезагружены**. В примере выше вторая строчка перезагрузит `smile.gif`, который был до неё. Если в `chatDiv` много текста, то эта перезагрузка будет очень заметна. Есть и другие побочные эффекты, например если существующий текст был выделен мышкой, то в большинстве браузеров это выделение пропадёт. Если в HTML был ``, в который посетитель что-то ввёл, то введённое значение пропадёт. И тому подобное. К счастью, есть и другие способы добавить содержимое, не использующие `innerHTML`. [/warn] [warn header="Скрипты не выполняются"] Если в `innerHTML` есть тег `script` -- он не будет выполнен. К примеру: ```html
``` В примере закрывающий тег `` разбит на две строки, т.к. иначе браузер подумает, что это конец скрипта. Вставленный скрипт не выполнится. Исключение -- IE9-, в нем вставляемый скрипт выполняются, если у него есть атрибут `defer`. Но это нестандартная возможность, которой не следует пользоваться. [/warn] [warn header="IE8- обрезает `style` и `script` в начале `innerHTML`"] Если в начале `innerHTML` находятся стили `