This commit is contained in:
Ilya Kantor 2017-03-13 00:21:00 +03:00
parent 8360ebbe90
commit dbf5c7587c
31 changed files with 635 additions and 455 deletions

View file

@ -6,11 +6,13 @@ libs:
# DOM tree
When we look at HTML we see nested tags, right? According to Document Object Model (DOM), every HTML-tag is an object. Nested tags are his "children". And the text inside it is an object as well. All these objects are accessible using Javascript.
The essential part of HTML is tags, right?
According to Document Object Model (DOM), every HTML-tag is an object. Nested tags are called "children". And the text inside it is an object as well. All these objects are accessible using Javascript, we'll see that now.
## An example of DOM
For instance, let's see the DOM tree for this document:
For instance, let's explore the DOM for this document:
```html run no-beautify
<!DOCTYPE HTML>
@ -24,37 +26,40 @@ For instance, let's see the DOM tree for this document:
</html>
```
Here's how it looks:
The DOM represents HTML as a tree structure of tags. Here's how it looks:
<div class="domtree"></div>
<script>
var node = {"name":"HTML","nodeType":1,"children":[{"name":"HEAD","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"\n "},{"name":"TITLE","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"About elks"}]},{"name":"#text","nodeType":3,"content":"\n "}]},{"name":"#text","nodeType":3,"content":"\n "},{"name":"BODY","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"\n The truth about elks."}]}]}
drawHtmlTree(node, 'div.domtree', 690, 300);
drawHtmlTree(node, 'div.domtree', 690, 320);
</script>
There are two types of tree nodes in the example:
1. Tags are called *element nodes* (or just elements). Naturally, nested tags become children of the enclosing ones. Because of that we have a tree.
2. The text inside elements forms *text nodes*, labelled as `#text`. A text node contains only a string. It may not have children and is always a leaf of the tree.
```online
**On the picture above element nodes you can click on element nodes. Their children will open/collapse.**
On the picture above element nodes you can click on element nodes. Their children will open/collapse.
```
Tags are called *element nodes* (or just elements). Nested tags become children of the enclosing ones. As a result we have a tree of elements: `<html>` is at the root, then `<head>` and `<body>` are its children etc.
The text inside elements forms *text nodes*, labelled as `#text`. A text node contains only a string. It may not have children and is always a leaf of the tree.
For instance, the `<title>` tag has the text `"About elks"`.
Please note the special characters in text nodes:
- a newline: `↵` (in Javascript known as `\n`)
- a space: `␣`
**Spaces and newlines -- are all valid characters, they form text nodes and become a part of the DOM.**
Spaces and newlines -- are totally valid characters, they form text nodes and become a part of the DOM. So, for instance, in the example above the `<head>` tag contains come spaces before `<title>`, and that text becomes a `#text` node (it contains a newline and some spaces only).
For instance, in the example above `<html>` contains not only elements `<head>` and `<body>`, but also the `#text` (spaces, line breaks) between them.
There are only two top-level exclusions:
1. Spaces and newlines before `<head>` are ignored for historical reasons,
2. If we put something after `</body>`, then that is automatically moved inside the `body`, at the end, as HTML spec requires that all content must be inside `<body>`. So there may be no spaces after `</body>`.
However, on the topmost level there are exclusions of that rule: spaces and newlines before `<head>` are ignored for historical reasons, and if we put something after `</body>`, then it is considered a malformed HTML, and that text is moved inside the `body`, at the end (there may be nothing after the `body`).
In other cases everything's honest -- if there are spaces (just like any character) in the document, then they text nodes in DOM, and if we remove them, then there won't be any.
In other cases everything's honest -- if there are spaces (just like any character) in the document, then they text nodes in DOM, and if we remove them, then there won't be any in DOM, like here:
Here are no space-only text nodes:
```html no-beautify
<!DOCTYPE HTML>
@ -69,10 +74,12 @@ var node = {"name":"HTML","nodeType":1,"children":[{"name":"HEAD","nodeType":1,"
drawHtmlTree(node, 'div.domtree', 690, 210);
</script>
```smart header="Starting/ending spaces and line breaks are usually not shown in DOM tools"
Tools working with DOM usually do not show spaces at start/end of the text and line-breaks between nodes. That's because they are mainly used to decorate HTML, and do not affect (in most cases) how it is shown.
```smart header="Edge spaces and in-between empty text are usually hidden in tools"
Browser tools (to be covered soon) that work with DOM usually do not show spaces at start/end of the text and empty text nodes (line-breaks) between tags. .
On our DOM pictures we'll omit them too where they are not important, to keep things short.
That's because they are mainly used to decorate HTML, and do not affect (in most cases) how it is shown.
On further DOM pictures we'll sometimes omit them where they are irrelevant, to keep things short.
```
@ -82,9 +89,18 @@ If the browser encounters malformed HTML, it automatically corrects it when maki
For instance, the top tag is always `<html>`. Even if it doesn't exist in the document -- it will be in DOM, the browser will create it. The same about `<body>`.
Like, if the HTML file is a single word `"Hello"`, the browser will wrap it into `<html>` and `<body>`.
As an example, if the HTML file is a single word `"Hello"`, the browser will wrap it into `<html>` and `<body>`, add the required `<head>`, and the DOM will be:
**While generating DOM, browser automatically processes errors in the document, closes tags and so on.**
<div class="domtree"></div>
<script>
var node = {"name":"HTML","nodeType":1,"children":[{"name":"HEAD","nodeType":1,"children":[]},{"name":"BODY","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"Hello"}]}]}
drawHtmlTree(node, 'div.domtree', 690, 150);
</script>
While generating DOM, browser automatically processes errors in the document, closes tags and so on.
Such an "invalid" document:
@ -106,7 +122,7 @@ drawHtmlTree(node, 'div.domtree', 690, 360);
</script>
````warn header="Tables always have `<tbody>`"
An interesting "special case" is tables. By the DOM specification they must have `<tbody>`, but HTML text may omit it. Then the browser creates `<tbody>` on it's own.
An interesting "special case" is tables. By the DOM specification they must have `<tbody>`, but HTML text may (officially) omit it. Then the browser creates `<tbody>` in DOM automatically.
For the HTML:
@ -154,22 +170,22 @@ var node = {"name":"HTML","nodeType":1,"children":[{"name":"HEAD","nodeType":1,"
drawHtmlTree(node, 'div.domtree', 690, 500);
</script>
Here we see a new tree node type -- *comment node*.
Here we see a new tree node type -- *comment node*, labeled as `#comment`.
We may think -- why a comment is added to the DOM? It doesn't affect the visual representation anyway. But there's a rule -- if something's in HTML, then it also must be in the DOM tree.
We may think -- why a comment is added to the DOM? It doesn't affect the visual representation in any way. But there's a rule -- if something's in HTML, then it also must be in the DOM tree.
**Everything in HTML, even comments, becomes a part of DOM.**
Even the `<!DOCTYPE...>` directive at the very beginning of HTML is also a DOM node. It's in the DOM tree right before `<html>`. We are not going to touch that node, but it's there.
Even the `<!DOCTYPE...>` directive at the very beginning of HTML is also a DOM node. It's in the DOM tree right before `<html>`. We are not going to touch that node, we even don't draw it on diagrams for that reason, but it's there.
The `document` object that represents the whole document is, formally, a DOM node as well.
There are [12 node types](https://dom.spec.whatwg.org/#node). In practice we mainly work with 4 of them:
There are [12 node types](https://dom.spec.whatwg.org/#node). In practice we usually work with 4 of them:
1. `document` -- the "entry point" into DOM.
2. element nodes -- HTML-tags, the tree building blocks.
3. text nodes -- they contain text.
4. comments -- sometimes we can put the information there, that won't be shown, but JS can read it from DOM.
3. text nodes -- contain text.
4. comments -- sometimes we can put the information there, it won't be shown, but JS can read it from DOM.
## See it yourself
@ -185,49 +201,57 @@ Should look like this:
![](elks.png)
So you can see the DOM, click on elements, see the details about them and so on.
You can see the DOM, click on elements, see their details and so on.
Please note that the DOM structure show in developer tools is simplified. Text nodes are shown just as text. And there are no "blank" (space only) text nodes at all. That's fine, because most of time we are interested in element nodes.
Please note that the DOM structure in developer tools is simplified. Text nodes are shown just as text. And there are no "blank" (space only) text nodes at all. That's fine, because most of time we are interested in element nodes.
Clicking the <span class="devtools" style="background-position:-328px -124px"></span> button allows to choose a node from the webpage using a mouse (or alike) and "inspect" it. Works great when we have a huge HTML page and would like to see the DOM of a particular place in it.
Clicking the <span class="devtools" style="background-position:-328px -124px"></span> button in the left-upper corner allows to choose a node from the webpage using a mouse (or other pointer device) and "inspect" it (scroll to it in the elements tab). Works great when we have a huge HTML page and would like to see the DOM of a particular place in it.
Another way to do it would be just right-clicking on a webpage and selecting "Inspect element" in the context menu.
Another way to do it would be just right-clicking on a webpage and selecting "Inspect" in the context menu.
![](inspect.png)
The right part has tabs:
- Styles -- to see CSS applied to the current element rule by rule, including built-in rules (gray). Almost everything can be edited at-place including the dimensions/margins/paddings of the box below.
At the right part of the tools there are following subtabs:
- Styles -- we can see CSS applied to the current element rule by rule, including built-in rules (gray). Almost everything can be edited at-place including the dimensions/margins/paddings of the box below.
- Computed -- to see CSS applied to the element by property: for each property we can see a rule that gives it (including CSS inheritance and such).
- ...there are other less used tabs as well.
- Event Listeners -- to see event listeners attached to DOM elements (we'll cover them in the next part of the tutorial).
- ...and so on.
The best way to study them is to click around. Again, please note that most values are in-place editable.
The best way to study them is to click around. Most values are in-place editable.
## Interaction with console
As we explore the DOM, open/close nodes, we also may want to apply Javascript to it. Like get a node and some code on it, to see how it works. There are few tips to travel between nodes in Elements tab and the console.
As we explore the DOM, we also may want to apply Javascript to it. Like: get a node and run some code to modify it, to see how it looks. Here are few tips to travel between the Elements tab and the console.
Press `key:Esc` -- it will open console right below the Elements tab.
- Select the first `<li>` in the Elements tab.
- Press `key:Esc` -- it will open console right below the Elements tab.
Now, the most recently selected element is available as `$0`, the previous one as `$1` etc.
Now the last selected element is available as `$0`, the previously selected is `$1` etc.
We can run commands on them, like `$0.style.background = 'red'` here:
We can run commands on them. For instance, `$0.style.background = 'red'` makes the selected list item red, like this:
![](domconsole0.png)
From the other side, if we're in console and have a node in a variable, then we can use the command `inspect(node)` to see it in the Elements pane. Or we can just output it and explore "at-place".
From the other side, if we're in console and have a variable referencing a DOM node, then we can use the command `inspect(node)` to see it in the Elements pane.
Or we can just output it in the console and explore "at-place", like `document.body` below:
![](domconsole1.png)
From the next chapter on we'll study how to access and modify the DOM using Javascript. The browser developer tools are the great help in debugging things.
That's for debugging purposes of course. From the next chapter on we'll access and modify DOM using Javascript.
The browser developer tools are a great help in development: we can explore DOM, try things and see what goes wrong.
## Summary
An HTML/XML document are represented inside the browser as the DOM tree.
An HTML/XML document is represented inside the browser as the DOM tree.
- Tags become element nodes and form the structure.
- Text becomes text nodes.
- ...etc, everything in HTML has its place in DOM, even comments.
We can use developer tools to inspect DOM and modify it manually. There's an extensive documentation about Chrome developer tools at <https://developers.google.com/web/tools/chrome-devtools>, but the best way to learn it is to click here and there, see various menus: most options are obvious. And then later, when you know most stuff, read the docs and pick up the rest.
We can use developer tools to inspect DOM and modify it manually.
DOM nodes have properties and methods that allow to modify them. We'll get down to it in further chapters.
Here we covered the basics, most used and important actions to start with. There's an extensive documentation about Chrome developer tools at <https://developers.google.com/web/tools/chrome-devtools>. The best way to learn the tools is to click here and there, read menus: most options are obvious. Later, when you know them in general, read the docs and pick up the rest.
DOM nodes have properties and methods that allow to travel between them, modify, move around the page and more. We'll get down to them in the next chapters.