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 ```js
// 1 // 1. The table with `id="age-table"`.
document.getElementById('age-table').getElementsByTagName('label'); let table = document.getElementById('age-table')
// 2 // 2. All label elements inside that table
document.getElementById('age-table').getElementsByTagName('td')[0]; table.getElementsByTagName('label')
// в современных браузерах можно одним запросом: // or
var result = document.querySelector('#age-table td'); document.querySelectorAll('#age-table label')
// 3 // 3. The first td in that table (with the word "Age").
document.getElementsByTagName('form')[1]; table.rows[0].cells[0]
// or
table.getElementsByTagName('td')[0]
// or
table.querySelector('td')
// 4 // 4. The form with the name "search".
document.querySelector('form[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 // 5. The first input in that form.
document.querySelector('form[name="search"] input') form.getElementsByTagName('input')
// or
form.querySelector('input')
// 6 // 6. The last input in that form.
document.getElementsByName("info[0]")[0]; // there's no direct query for that
let inputs = form.querySelectorAll('input') // search all
// 7 inputs[inputs.length-1] // take last
document.querySelector('form[name="search-person"] [name="info[0]"]');
``` ```

View file

@ -1,37 +1,32 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head>
<meta charset="utf-8">
</head>
<body> <body>
<form name="search"> <form name="search">
<label>Поиск по сайту: <label>Search the site:
<input type="text" name="search"> <input type="text" name="search">
</label> </label>
<input type="submit" value="Искать!"> <input type="submit" value="Search!">
</form> </form>
<hr> <hr>
<form name="search-person"> <form name="search-person">
Поиск по посетителям: Search the visitors:
<table id="age-table"> <table id="age-table">
<tr> <tr>
<td>Возраст:</td> <td>Age:</td>
<td id="age-list"> <td id="age-list">
<label> <label>
<input type="radio" name="age" value="young">до 18</label> <input type="radio" name="age" value="young">less than 18</label>
<label> <label>
<input type="radio" name="age" value="mature">18-50</label> <input type="radio" name="age" value="mature">18-50</label>
<label> <label>
<input type="radio" name="age" value="senior">более 50</label> <input type="radio" name="age" value="senior">more than 50</label>
</td> </td>
</tr> </tr>
<tr> <tr>
<td>Дополнительно:</td> <td>Additionally:</td>
<td> <td>
<input type="text" name="info[0]"> <input type="text" name="info[0]">
<input type="text" name="info[1]"> <input type="text" name="info[1]">
@ -41,8 +36,7 @@
</table> </table>
<input type="submit" value="Искать!"> <input type="submit" value="Search!">
</form> </form>
</body> </body>
</html>
</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 элемента. 1. The table with `id="age-table"`.
2. Первую ячейку таблицы (со словом `"Возраст"`). 2. All `label` elements inside that table (there should be 3 of them).
3. Вторую форму в документе. 3. The first `td` in that table (with the word "Age").
4. Форму с именем `search`, без использования её позиции в документе. 4. The `form` with the name `search`.
5. Элемент `input` в форме с именем `search`. Если их несколько, то нужен первый. 5. The first `input` in that form.
6. Элемент с именем `info[0]`, без точного знания его позиции в документе. 6. The last `input` in that form.
7. Элемент с именем `info[0]`, внутри формы с именем `search-person`.
Используйте для этого консоль браузера, открыв страницу [table.html](table.html) в отдельном окне.
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> </script>
``` ```
```smart header="There must be only one" ```smart header="There can 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`. 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. 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> </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 <div>Second div</div>
var result = document.evaluate("//h2[contains(., 'XPath')]", document.documentElement, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < result.snapshotLength; i++) { <script>
alert( result.snapshotItem(i).outerHTML ); *!*
} 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> <table>
<thead> <thead>
<tr> <tr>
<td>Метод</td> <td>Method</td>
<td>Ищет по...</td> <td>Finds by...</td>
<td>Ищет внутри элемента?</td> <td>Can call on element?</td>
<td>Поддержка</td> <td>Live?</td>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -279,45 +302,44 @@ IE тоже поддерживает XPath, но эта поддержка не
<td><code>getElementById</code></td> <td><code>getElementById</code></td>
<td><code>id</code></td> <td><code>id</code></td>
<td>-</td> <td>-</td>
<td>везде</td> <td>-</td>
</tr> </tr>
<tr> <tr>
<td><code>getElementsByName</code></td> <td><code>getElementsByName</code></td>
<td><code>name</code></td> <td><code>name</code></td>
<td>-</td> <td>-</td>
<td>везде</td> <td></td>
</tr> </tr>
<tr> <tr>
<td><code>getElementsByTagName</code></td> <td><code>getElementsByTagName</code></td>
<td>тег или <code>'*'</code></td> <td>tag or <code>'*'</code></td>
<td></td>
<td></td> <td></td>
<td>везде</td>
</tr> </tr>
<tr> <tr>
<td><code>getElementsByClassName</code></td> <td><code>getElementsByClassName</code></td>
<td>классу</td> <td>class</td>
<td></td>
<td></td> <td></td>
<td>кроме IE8-</td>
</tr> </tr>
<tr> <tr>
<td><code>querySelector</code></td> <td><code>querySelector</code></td>
<td>CSS-селектор</td> <td>CSS-selector</td>
<td></td> <td></td>
<td>везде</td> <td>-</td>
</tr> </tr>
<tr> <tr>
<td><code>querySelectorAll</code></td> <td><code>querySelectorAll</code></td>
<td>CSS-селектор</td> <td>CSS-selector</td>
<td></td> <td></td>
<td>везде</td> <td>-</td>
</tr> </tr>
</tbody> </tbody>
</table> </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`). - There is `elem.matches(css)` to check if `elem` matches the given CSS selector.
- Метод `elem.closest(css)` ищет ближайший элемент выше по иерархии DOM, подходящий под CSS-селектор css. Сам элемент тоже включается в поиск. - There is `elem.closest(css)` to look for a nearest ancestor that matches the given CSS-selector. The `elem` itself is also checked.
- Язык запросов XPath поддерживается большинством браузеров, кроме IE, даже 9-й версии, но `querySelector` удобнее. Поэтому XPath используется редко.