# Node properties: type, tag and contents Let's get a more in-depth look at DOM nodes. In this chapter we'll see more into what they are and their most used properties. ## DOM node classes DOM nodes have different properties depending on their class. For instance, an element node corresponding to tag `` has link-related properties, and the one corresponding to `` has input-related properties and so on. Text nodes are not the same as element nodes. But there are also common properties and methods between all of them, because all classes of DOM nodes form a single hierarchy. Each DOM node belongs to the corresponding built-in class. The root of the hierarchy is [EventTarget](https://dom.spec.whatwg.org/#eventtarget), that is inherited by [Node](http://dom.spec.whatwg.org/#interface-node), and other DOM nodes inherit from it. Here's the picture, explanations to follow: ![](dom-class-hierarchy.png) The classes are: - [EventTarget](https://dom.spec.whatwg.org/#eventtarget) -- is the root "abstract" class. Objects of that class are never created. It serves as a base, so that all DOM nodes support so-called "events", we'll study them later. - [Node](http://dom.spec.whatwg.org/#interface-node) -- is also an "abstract" class, serving as a base for DOM nodes. It provides the core tree functionality: `parentNode`, `nextSibling`, `childNodes` and so on (they are getters). Objects of `Node` class are never created. But there are concrete node classes that inherit from it, namely: `Text` for text nodes, `Element` for element nodes and more exotic ones like `Comment` for comment nodes. - [Element](http://dom.spec.whatwg.org/#interface-element) -- is a base class for DOM elements. It provides element-level navigation like `nextElementSibling`, `children` and searching methods like `getElementsByTagName`, `querySelector`. In the browser there may be not only HTML, but also XML and SVG documents. The `Element` class serves as a base for more specific classes: `SVGElement`, `XMLElement` and `HTMLElement`. - [HTMLElement](https://html.spec.whatwg.org/multipage/dom.html#htmlelement) -- is finally the basic class for all HTML elements. It is inherited by various HTML elements: - [HTMLInputElement](https://html.spec.whatwg.org/multipage/forms.html#htmlinputelement) -- the class for `` elements, - [HTMLBodyElement](https://html.spec.whatwg.org/multipage/semantics.html#htmlbodyelement) -- the class for `` elements, - [HTMLAnchorElement](https://html.spec.whatwg.org/multipage/semantics.html#htmlanchorelement) -- the class for `` elements - ...and so on, each tag has its own class that may provide specific properties and methods. So, the full set of properties and methods of a given node comes as the result of the inheritance. For example, let's consider the DOM object for an `` element. It belongs to [HTMLInputElement](https://html.spec.whatwg.org/multipage/forms.html#htmlinputelement) class. It gets properties and methods as a superposition of: - `HTMLInputElement` -- this class provides input-specific properties, and inherits from... - `HTMLElement` -- it provides common HTML element methods (and getters/setters) and inherits from... - `Element` -- provides generic element methods and inherits from... - `Node` -- provides common DOM node properties and inherits from... - `EventTarget` -- gives the support for events (to be covered), - ...and finally it inherits from `Object`, so "pure object" methods like `hasOwnProperty` are also available. To see the DOM node class name, we can recall that an object usually has the `constructor` property. It references to the class constructor, and `constructor.name` is its name: ```js run alert( document.body.constructor.name ); // HTMLBodyElement ``` ...Or we can just `toString` it: ```js run alert( document.body ); // [object HTMLBodyElement] ``` We also can use `instanceof` to check the inheritance: ```js run alert( document.body instanceof HTMLBodyElement ); // true alert( document.body instanceof HTMLElement ); // true alert( document.body instanceof Element ); // true alert( document.body instanceof Node ); // true alert( document.body instanceof EventTarget ); // true ``` As we can see, DOM nodes are regular JavaScript objects. They use prototype-based classes for inheritance. That's also easy to see by outputting an element with `console.dir(elem)` in a browser. There in the console you can see `HTMLElement.prototype`, `Element.prototype` and so on. ```smart header="`console.dir(elem)` versus `console.log(elem)`" Most browsers support two commands in their developer tools: `console.log` and `console.dir`. They output their arguments to the console. For JavaScript objects these commands usually do the same. But for DOM elements they are different: - `console.log(elem)` shows the element DOM tree. - `console.dir(elem)` shows the element as a DOM object, good to explore its properties. Try it on `document.body`. ``` ````smart header="IDL in the spec" In the specification, classes are described not using JavaScript, but a special [Interface description language](https://en.wikipedia.org/wiki/Interface_description_language) (IDL), that is usually easy to understand. In IDL all properties are prepended with their types. For instance, `DOMString`, `boolean` and so on. Here's an excerpt from it, with comments: ```js // Define HTMLInputElement *!* // The colon ":" means that HTMLInputElement inherits from HTMLElement */!* interface HTMLInputElement: HTMLElement { // here go properties and methods of elements *!* // "DOMString" means that these properties are strings */!* attribute DOMString accept; attribute DOMString alt; attribute DOMString autocomplete; attribute DOMString value; *!* // boolean property (true/false) attribute boolean autofocus; */!* ... *!* // now the method: "void" means that that returns no value */!* void select(); ... } ``` Other classes are somewhat similar. ```` ## The "nodeType" property The `nodeType` property provides an old-fashioned way to get the "type" of a DOM node. It has a numeric value: - `elem.nodeType == 1` for element nodes, - `elem.nodeType == 3` for text nodes, - `elem.nodeType == 9` for the document object, - there are few other values in [the specification](https://dom.spec.whatwg.org/#node). For instance: ```html run ``` In modern scripts, we can use `instanceof` and other class-based tests to see the node type, but sometimes `nodeType` may be simpler. We can only read `nodeType`, not change it. ## Tag: nodeName and tagName Given a DOM node, we can read its tag name from `nodeName` or `tagName` properties: For instance: ```js run alert( document.body.nodeName ); // BODY alert( document.body.tagName ); // BODY ``` Is there any difference between tagName and nodeName? Sure, the difference is reflected in their names, but is indeed a bit subtle. - The `tagName` property exists only for `Element` nodes. - The `nodeName` is defined for any `Node`: - for elements it means the same as `tagName`. - for other node types (text, comment, etc.) it has a string with the node type. In other words, `tagName` is only supported by element nodes (as it originates from `Element` class), while `nodeName` can say something about other node types. For instance, let's compare `tagName` and `nodeName` for the `document` and a comment node: ```html run ``` If we only deal with elements, then `tagName` is the only thing we should use. ```smart header="The tag name is always uppercase except XHTML" The browser has two modes of processing documents: HTML and XML. Usually the HTML-mode is used for webpages. XML-mode is enabled when the browser receives an XML-document with the header: `Content-Type: application/xml+xhtml`. In HTML mode `tagName/nodeName` is always uppercased: it's `BODY` either for `` or ``. In XML mode the case is kept "as is". Nowadays XML mode is rarely used. ``` ## innerHTML: the contents The [innerHTML](https://w3c.github.io/DOM-Parsing/#widl-Element-innerHTML) property allows to get the HTML inside the element as a string. We can also modify it. So it's one of most powerful ways to change the page. The example shows the contents of `document.body` and then replaces it completely: ```html run

A paragraph

A div
``` We can try to insert invalid HTML, the browser will fix our errors: ```html run ``` ```smart header="Scripts don't execute" If `innerHTML` inserts a ` ``` **Beware: unlike `innerHTML`, writing to `outerHTML` does not change the element. Instead, it replaces it as a whole in the outer context.** Yeah, sounds strange, and strange it is, that's why we make a separate note about it here. Take a look. Consider the example: ```html run
Hello, world!
``` In the line `(*)` we take the full HTML of `
...
` and replace it by `

...

`. In the outer document we can see the new content instead of the `
`. But the old `div` variable is still the same. The `outerHTML` assignment does not modify the DOM element, but extracts it from the outer context and inserts a new piece of HTML instead of it. Novice developers sometimes make an error here: they modify `div.outerHTML` and then continue to work with `div` as if it had the new content in it. That's possible with `innerHTML`, but not with `outerHTML`. We can write to `outerHTML`, but should keep in mind that it doesn't change the element we're writing to. It creates the new content on its place instead. We can get a reference to new elements by querying DOM. ## nodeValue/data: text node content The `innerHTML` property is only valid for element nodes. Other node types have their counterpart: `nodeValue` and `data` properties. These two are almost the same for practical use, there are only minor specification differences. So we'll use `data`, because it's shorter. We can read it, like this: ```html run height="50" Hello ``` For text nodes we can imagine a reason to read or modify them, but why comments? Usually, they are not interesting at all, but sometimes developers embed information into HTML in them, like this: ```html
Welcome, Admin!
``` ...Then JavaScript can read it and process embedded instructions. ## textContent: pure text The `textContent` provides access to the *text* inside the element: only text, minus all ``. For instance: ```html run

Headline!

Martians attack people!

``` As we can see, only text is returned, as if all `` were cut out, but the text in them remained. In practice, reading such text is rarely needed. **Writing to `textContent` is much more useful, because it allows to write text the "safe way".** Let's say we have an arbitrary string, for instance entered by a user, and want to show it. - With `innerHTML` we'll have it inserted "as HTML", with all HTML tags. - With `textContent` we'll have it inserted "as text", all symbols are treated literally. Compare the two: ```html run
``` 1. The first `
` gets the name "as HTML": all tags become tags, so we see the bold name. 2. The second `
` gets the name "as text", so we literally see `Winnie-the-pooh!`. In most cases, we expect the text from a user, and want to treat it as text. We don't want unexpected HTML in our site. An assignment to `textContent` does exactly that. ## The "hidden" property The "hidden" attribute and the DOM property specifies whether the element is visible or not. We can use it in HTML or assign using JavaScript, like this: ```html run height="80"
Both divs below are hidden
JavaScript assigned the property "hidden"
``` Technically, `hidden` works the same as `style="display:none"`. But it's shorter to write. Here's a blinking element: ```html run height=50
A blinking element
``` ## More properties DOM elements also have additional properties, many of them provided by the class: - `value` -- the value for ``, `