This commit is contained in:
Ilya Kantor 2017-02-02 23:27:13 +03:00
parent d991a8e1cd
commit 0c0487b630
4 changed files with 105 additions and 82 deletions

View file

@ -1,27 +1,36 @@
Есть много вариантов решения, вот некоторые из них:
There are many ways to do it.
Here are some of them:
```js
// 1
document.getElementById('age-table').getElementsByTagName('label');
// 1. The table with `id="age-table"`.
let table = document.getElementById('age-table')
// 2
document.getElementById('age-table').getElementsByTagName('td')[0];
// в современных браузерах можно одним запросом:
var result = document.querySelector('#age-table td');
// 2. All label elements inside that table
table.getElementsByTagName('label')
// or
document.querySelectorAll('#age-table label')
// 3
document.getElementsByTagName('form')[1];
// 3. The first td in that table (with the word "Age").
table.rows[0].cells[0]
// or
table.getElementsByTagName('td')[0]
// or
table.querySelector('td')
// 4
document.querySelector('form[name="search"]');
// 4. The form with the name "search".
// assuming there's only one element with name="search"
let form = document.getElementsByName('search')[0]
// or, form specifically
document.querySelector('form[name="search"]')
// 5
document.querySelector('form[name="search"] input')
// 5. The first input in that form.
form.getElementsByTagName('input')
// or
form.querySelector('input')
// 6
document.getElementsByName("info[0]")[0];
// 7
document.querySelector('form[name="search-person"] [name="info[0]"]');
// 6. The last input in that form.
// there's no direct query for that
let inputs = form.querySelectorAll('input') // search all
inputs[inputs.length-1] // take last
```

View file

@ -1,37 +1,32 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form name="search">
<label>Поиск по сайту:
<label>Search the site:
<input type="text" name="search">
</label>
<input type="submit" value="Искать!">
<input type="submit" value="Search!">
</form>
<hr>
<form name="search-person">
Поиск по посетителям:
Search the visitors:
<table id="age-table">
<tr>
<td>Возраст:</td>
<td>Age:</td>
<td id="age-list">
<label>
<input type="radio" name="age" value="young">до 18</label>
<input type="radio" name="age" value="young">less than 18</label>
<label>
<input type="radio" name="age" value="mature">18-50</label>
<label>
<input type="radio" name="age" value="senior">более 50</label>
<input type="radio" name="age" value="senior">more than 50</label>
</td>
</tr>
<tr>
<td>Дополнительно:</td>
<td>Additionally:</td>
<td>
<input type="text" name="info[0]">
<input type="text" name="info[1]">
@ -41,8 +36,7 @@
</table>
<input type="submit" value="Искать!">
<input type="submit" value="Search!">
</form>
</body>
</html>

View file

@ -2,19 +2,17 @@ importance: 4
---
# Поиск элементов
# Search for elements
Ниже находится документ с таблицей и формой.
Here's the document with the table and form.
Найдите (получите в переменную) в нём:
How to find?
1. Все элементы `label` внутри таблицы. Должно быть 3 элемента.
2. Первую ячейку таблицы (со словом `"Возраст"`).
3. Вторую форму в документе.
4. Форму с именем `search`, без использования её позиции в документе.
5. Элемент `input` в форме с именем `search`. Если их несколько, то нужен первый.
6. Элемент с именем `info[0]`, без точного знания его позиции в документе.
7. Элемент с именем `info[0]`, внутри формы с именем `search-person`.
Используйте для этого консоль браузера, открыв страницу [table.html](table.html) в отдельном окне.
1. The table with `id="age-table"`.
2. All `label` elements inside that table (there should be 3 of them).
3. The first `td` in that table (with the word "Age").
4. The `form` with the name `search`.
5. The first `input` in that form.
6. The last `input` in that form.
Open the page [table.html](table.html) in a separate window and make use of browser tools for that.

View file

@ -43,8 +43,8 @@ For instance:
</script>
```
```smart header="There must be only one"
By the specification the value of `id` must be unique. There may be only one element in the document with the given `id`.
```smart header="There can be only one"
By the specification the value of `id` must be unique. There can be only one element in the document with the given `id`.
If there are multiple elements with the same `id`, then the behavior is unpredictable. The browser may return any of them at random. So please stick to the rule and keep `id` unique.
```
@ -239,39 +239,62 @@ For instance:
</script>
```
## XPath в современных браузерах
## Live collections
Для полноты картины рассмотрим ещё один способ поиска, который обычно используется в XML. Это <a href="http://www.w3.org/TR/xpath/">язык запросов XPath</a>.
All methods `getElementsBy*` return a *live* collection. They always reflect the current state of the document.
Он очень мощный, во многом мощнее CSS, но сложнее. Например, запрос для поиска элементов `H2`, содержащих текст `"XPath"`, будет выглядеть так: `//h2[contains(., "XPath")]`.
For instance, here in the first script the length is `1`, because the browser only processed the first div. Then later it's 2:
Все современные браузеры, кроме IE, поддерживают XPath с синтаксисом, близким к [описанному в MDN](https://developer.mozilla.org/en/XPath).
```html run
<div>First div</div>
Найдем заголовки с текстом `XPath` в текущем документе:
<script>
let divs = document.getElementsByTagName('div');
alert(divs.length); // 1
</script>
```js run no-beautify
var result = document.evaluate("//h2[contains(., 'XPath')]", document.documentElement, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
<div>Second div</div>
for (var i = 0; i < result.snapshotLength; i++) {
alert( result.snapshotItem(i).outerHTML );
}
<script>
*!*
alert(divs.length); // 2
*/!*
</script>
```
IE тоже поддерживает XPath, но эта поддержка не соответствует стандарту и работает только для XML-документов, например, полученных с помощью `XMLHTTPRequest` (AJAX). Для обычных же HTML-документов XPath в IE не поддерживается.
In contrast, `querySelectorAll` returns a *static* collection. It's like a fixed array of elements.
Так как XPath сложнее и длиннее CSS, то используют его очень редко.
If we use it instead, then both scripts output `1`:
## Итого
Есть 6 основных методов поиска элементов DOM:
```html run
<div>First div</div>
<script>
let divs = document.querySelectorAll('div');
alert(divs.length); // 1
</script>
<div>Second div</div>
<script>
*!*
alert(divs.length); // 1
*/!*
</script>
```
## Summary
There are 6 main methods to search for nodes in DOM:
<table>
<thead>
<tr>
<td>Метод</td>
<td>Ищет по...</td>
<td>Ищет внутри элемента?</td>
<td>Поддержка</td>
<td>Method</td>
<td>Finds by...</td>
<td>Can call on element?</td>
<td>Live?</td>
</tr>
</thead>
<tbody>
@ -279,45 +302,44 @@ IE тоже поддерживает XPath, но эта поддержка не
<td><code>getElementById</code></td>
<td><code>id</code></td>
<td>-</td>
<td>везде</td>
<td>-</td>
</tr>
<tr>
<td><code>getElementsByName</code></td>
<td><code>name</code></td>
<td>-</td>
<td>везде</td>
<td></td>
</tr>
<tr>
<td><code>getElementsByTagName</code></td>
<td>тег или <code>'*'</code></td>
<td>tag or <code>'*'</code></td>
<td></td>
<td></td>
<td>везде</td>
</tr>
<tr>
<td><code>getElementsByClassName</code></td>
<td>классу</td>
<td>class</td>
<td></td>
<td></td>
<td>кроме IE8-</td>
</tr>
<tr>
<td><code>querySelector</code></td>
<td>CSS-селектор</td>
<td>CSS-selector</td>
<td></td>
<td>везде</td>
<td>-</td>
</tr>
<tr>
<td><code>querySelectorAll</code></td>
<td>CSS-селектор</td>
<td>CSS-selector</td>
<td></td>
<td>везде</td>
<td>-</td>
</tr>
</tbody>
</table>
Практика показывает, что в 95% ситуаций достаточно `querySelector/querySelectorAll`. Хотя более специализированные методы `getElement*` работают чуть быстрее, но разница в миллисекунду-другую редко играет роль.
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.
Кроме того:
Besides:
- Есть метод `elem.matches(css)`, который проверяет, удовлетворяет ли элемент CSS-селектору. Он поддерживается большинством браузеров в префиксной форме (`ms`, `moz`, `webkit`).
- Метод `elem.closest(css)` ищет ближайший элемент выше по иерархии DOM, подходящий под CSS-селектор css. Сам элемент тоже включается в поиск.
- Язык запросов XPath поддерживается большинством браузеров, кроме IE, даже 9-й версии, но `querySelector` удобнее. Поэтому XPath используется редко.
- There is `elem.matches(css)` to check if `elem` matches the given CSS selector.
- There is `elem.closest(css)` to look for a nearest ancestor that matches the given CSS-selector. The `elem` itself is also checked.