Skip to content

Commit d4bdde5

Browse files
committed
up
1 parent 0c0487b commit d4bdde5

File tree

12 files changed

+581
-10
lines changed

12 files changed

+581
-10
lines changed
-366 Bytes
Loading

2-ui/1-document/5-searching-elements-dom/article.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Searching: getElement*, querySelector* and others
1+
# Searching with getElement*, querySelector* and others
22

33
DOM navigation properties are great when elements are close to each other. What if they are not? How to get an arbitrary element of the page?
44

@@ -111,7 +111,7 @@ Another widespread novice mistake is to write like:
111111
document.getElementsByTagName('input').value = 5;
112112
```
113113

114-
That won't work, because we take a *collection* of inputs and assign the value to it, rather to elements inside it.
114+
That won't work, because it takes a *collection* of inputs and assigns the value to it, rather to elements inside it.
115115

116116
We should either iterate over the collection or get an element by the number, and then assign, like this:
117117

@@ -121,7 +121,7 @@ document.getElementsByTagName('input')[0].value = 5;
121121
```
122122
````
123123
124-
Other methods:
124+
There are also other rarely used methods of this kind:
125125
126126
- `document.getElementsByName(name)` returns elements with the given `name` attribute. Rarely used.
127127
- `elem.getElementsByClassName(className)` returns elements that have the given CSS class. Elements may have other classes too.
@@ -179,7 +179,7 @@ Pseudo-classes in the CSS selector like `:hover` and `:active` are also supporte
179179
180180
The call to `elem.querySelector(css)` returns the first element for the given CSS selector.
181181
182-
In other words, the result is the same as `elem.querySelectorAll(css)[0]`, but that's looking for *all* elements and picking the first, much slower than only looking for the first one.
182+
In other words, the result is the same as `elem.querySelectorAll(css)[0]`, but the latter is looking for *all* elements and picking one, while `elem.querySelector` just looks for one. So it's faster.
183183
184184
## matches
185185
@@ -241,9 +241,11 @@ For instance:
241241
242242
## Live collections
243243
244-
All methods `getElementsBy*` return a *live* collection. They always reflect the current state of the document.
244+
All methods `"getElementsBy*"` return a *live* collection. Such collections always reflect the current state of the document.
245245
246-
For instance, here in the first script the length is `1`, because the browser only processed the first div. Then later it's 2:
246+
For instance, here in the first script the length is `1`, because the browser only processed the first div.
247+
248+
Then later after the second `div` it's 2:
247249
248250
```html run
249251
<div>First div</div>
@@ -284,6 +286,10 @@ If we use it instead, then both scripts output `1`:
284286
</script>
285287
```
286288
289+
Now we can easily see the difference. The static collection did not increase after the appearance of a new `div` in the document.
290+
291+
Here we used separate scripts to illustrate how the element addition affects the collection. Soon we'll see more ways to alter DOM.
292+
287293
## Summary
288294
289295
There are 6 main methods to search for nodes in DOM:
@@ -292,8 +298,8 @@ There are 6 main methods to search for nodes in DOM:
292298
<thead>
293299
<tr>
294300
<td>Method</td>
295-
<td>Finds by...</td>
296-
<td>Can call on element?</td>
301+
<td>Searches by...</td>
302+
<td>Can call on an element?</td>
297303
<td>Live?</td>
298304
</tr>
299305
</thead>
@@ -337,9 +343,11 @@ There are 6 main methods to search for nodes in DOM:
337343
</tbody>
338344
</table>
339345
340-
Please note that methods `getElementById` and `getElementsByName` can only be called in the context of the document: `document.getElementById(...)`. Other methods can be called on elements, like `elem.querySelectorAll(...)` -- and will search in their subtrees.
346+
Please note that methods `getElementById` and `getElementsByName` can only be called in the context of the document: `document.getElementById(...)`. But not on an element: `elem.getElementById(...)` would cause an error.
347+
348+
Other methods can be called on elements too. For instance `elem.querySelectorAll(...)` will search inside `elem` (in the DOM subtree).
341349
342-
Besides:
350+
Besides that:
343351
344352
- There is `elem.matches(css)` to check if `elem` matches the given CSS selector.
345353
- There is `elem.closest(css)` to look for a nearest ancestor that matches the given CSS-selector. The `elem` itself is also checked.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
There's a catch here.
2+
3+
At the time of `<script>` execution the last DOM node is exactly `<script>`, because the browser did not process the rest of the page yet.
4+
5+
So the result is `1` (element node).
6+
7+
```html run height=60
8+
<html>
9+
10+
<body>
11+
<script>
12+
alert(document.body.lastChild.nodeType);
13+
</script>
14+
</body>
15+
16+
</html>
17+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
importance: 5
2+
3+
---
4+
5+
# What's in the nodeType?
6+
7+
What the script shows?
8+
9+
```html
10+
<html>
11+
12+
<body>
13+
<script>
14+
alert(document.body.lastChild.nodeType);
15+
</script>
16+
</body>
17+
18+
</html>
19+
```
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
The answer: **`BODY`**.
2+
3+
```html run
4+
<script>
5+
let body = document.body;
6+
7+
body.innerHTML = "<!--" + body.tagName + "-->";
8+
9+
alert( body.firstChild.data ); // BODY
10+
</script>
11+
```
12+
13+
What's going on step by step:
14+
15+
1. The content of `<body>` is replaced with the comment. The comment is <code>&lt;!--BODY--&gt;</code>, because `body.tagName == "BODY"`. As we remember, `tagName` is always uppercase in HTML.
16+
2. The comment is now the only child node, so we get it in `body.firstChild`.
17+
3. The `data` property of the comment is its contents (inside `<!--...-->`): `"BODY"`.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
importance: 3
2+
3+
---
4+
5+
# Tag in comment
6+
7+
What this code shows?
8+
9+
```html
10+
<script>
11+
let body = document.body;
12+
13+
body.innerHTML = "<!--" + body.tagName + "-->";
14+
15+
alert( body.firstChild.data ); // what's here?
16+
</script>
17+
```
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
We can see which class it belongs by outputting it, like:
3+
4+
```js run
5+
alert(document); // [object HTMLDocument]
6+
```
7+
8+
Or:
9+
10+
```js run
11+
alert(document.constructor.name); // HTMLDocument
12+
```
13+
14+
So, `document` is an instance of `HTMLDocument` class.
15+
16+
What's its place in the hierarchy?
17+
18+
Yeah, we could browse the specification, but it would be faster to figure out manually.
19+
20+
Let's traverse the prototype chain via `__proto__`.
21+
22+
As we know, methods of a class are in the `prototype` of the constructor. For instance, `HTMLDocument.prototype` has methods for documents.
23+
24+
Also, there's a reference to the constructor function inside the `prototype`:
25+
26+
```js run
27+
alert(HTMLDocument.prototype.constructor === HTMLDocument); // true
28+
```
29+
30+
For built-in classes in all prototypes there's a `constructor` reference, and we can get `constructor.name` to see the name of the class. Let's do it for all objects in the `document` prototype chain:
31+
32+
```js run
33+
alert(HTMLDocument.prototype.constructor.name); // HTMLDocument
34+
alert(HTMLDocument.prototype.__proto__.constructor.name); // Document
35+
alert(HTMLDocument.prototype.__proto__.__proto__.constructor.name); // Node
36+
```
37+
38+
We also could examine the object using `console.dir(document)` and see these names by opening `__proto__`. The console takes them from `constructor` internally.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
importance: 4
2+
3+
---
4+
5+
# Where's the "document" in the hierarchy?
6+
7+
Which class the `document` belongs to?
8+
9+
What's its place in the DOM hierarchy?
10+
11+
Does it inherit from `Node` or `Element`?

0 commit comments

Comments
 (0)