` (with Pete)?
diff --git a/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/solution.md b/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/solution.md
new file mode 100644
index 00000000..e962eb66
--- /dev/null
+++ b/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/solution.md
@@ -0,0 +1,4 @@
+1. Yes, true. The element `elem.lastChild` is always the last one, it has no `nextSibling`, so if there are children, then yes.
+2. No, wrong, because `elem.children[0]` is the first child among elements. But there may be non-element nodes before it. So `previousSibling` may be a text node.
+
+Please note that for both cases if there are no children, then there will be an error. For instance, if `elem.lastChild` is `null`, we can't access `elem.lastChild.nextSibling`.
diff --git a/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/task.md b/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/task.md
new file mode 100644
index 00000000..235e83a0
--- /dev/null
+++ b/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/task.md
@@ -0,0 +1,10 @@
+importance: 5
+
+---
+
+# The sibling question
+
+If `elem` -- is an arbitrary DOM element node...
+
+- Is it true that `elem.lastChild.nextSibling` is always `null`?
+- Is it true that `elem.children[0].previousSibling` is always `null` ?
diff --git a/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.md b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.md
new file mode 100644
index 00000000..f2aa8630
--- /dev/null
+++ b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.md
@@ -0,0 +1 @@
+We'll be using `rows` and `cells` properties to access diagonal table cells.
diff --git a/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.view/index.html b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.view/index.html
new file mode 100644
index 00000000..91e80566
--- /dev/null
+++ b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.view/index.html
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+ 1:1 |
+ 2:1 |
+ 3:1 |
+ 4:1 |
+ 5:1 |
+
+
+ 1:2 |
+ 2:2 |
+ 3:2 |
+ 4:2 |
+ 5:2 |
+
+
+ 1:3 |
+ 2:3 |
+ 3:3 |
+ 4:3 |
+ 5:3 |
+
+
+ 1:4 |
+ 2:4 |
+ 3:4 |
+ 4:4 |
+ 5:4 |
+
+
+ 1:5 |
+ 2:5 |
+ 3:5 |
+ 4:5 |
+ 5:5 |
+
+
+
+
+
diff --git a/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/source.view/index.html b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/source.view/index.html
new file mode 100644
index 00000000..ad835f9f
--- /dev/null
+++ b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/source.view/index.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+ 1:1 |
+ 2:1 |
+ 3:1 |
+ 4:1 |
+ 5:1 |
+
+
+ 1:2 |
+ 2:2 |
+ 3:2 |
+ 4:2 |
+ 5:2 |
+
+
+ 1:3 |
+ 2:3 |
+ 3:3 |
+ 4:3 |
+ 5:3 |
+
+
+ 1:4 |
+ 2:4 |
+ 3:4 |
+ 4:4 |
+ 5:4 |
+
+
+ 1:5 |
+ 2:5 |
+ 3:5 |
+ 4:5 |
+ 5:5 |
+
+
+
+
+
diff --git a/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/task.md b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/task.md
new file mode 100644
index 00000000..23be59fc
--- /dev/null
+++ b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/task.md
@@ -0,0 +1,18 @@
+importance: 5
+
+---
+
+# Select all diagonal cells
+
+Write the code to paint all diagonal table cells in red.
+
+You'll need to get all diagonal `` from the `` and paint them using the code:
+
+```js
+// td should be the reference to the table cell
+td.style.backgroundColor = 'red';
+```
+
+The result should be:
+
+[iframe src="solution" height=180]
diff --git a/2-ui/1-document/3-dom-navigation/article.md b/2-ui/1-document/3-dom-navigation/article.md
new file mode 100644
index 00000000..c4dc022c
--- /dev/null
+++ b/2-ui/1-document/3-dom-navigation/article.md
@@ -0,0 +1,284 @@
+libs:
+ - d3
+ - domtree
+
+---
+
+
+# DOM Navigation
+
+DOM allows to do anything with HTML-element and its contents, but first we need to reach it.
+
+All operations on DOM start with the `document` object. From it we can access any node.
+
+[cut]
+
+Here's a picture of links that allow to walk between DOM nodes:
+
+
+
+Let's discuss them in more detail.
+
+## On top: documentElement and body
+
+The topmost tree nodes are available directly as `document` properties:
+
+`` = `document.documentElement`
+: The topmost document node is `document.documentElement`. That's DOM node of `` tag.
+
+`` = `document.body`
+: Another widely used DOM node is the `` element -- `document.body`.
+
+`` = `document.head`
+: The `` tag is available as `document.head`.
+
+````warn header="There's a catch: `document.body` can be `null`"
+A script cannot access an element that doesn't exist at the moment of running.
+
+In particular, if a script is inside ``, then `document.body` is unavailable, because the browser did not reach it yet.
+
+So, in the example below `alert` will show `null`:
+
+```html run
+
+
+
+
+
+
+
+
+
+
+
+
+```
+````
+
+```smart header="In the DOM world `null` is actively used"
+In the DOM, the value meaning "no such node" is `null`, not `undefined`.
+```
+
+## Children: childNodes, firstChild, lastChild
+
+There are two tree terms that we'll use:
+
+- **Child nodes (or children)** -- elements that are nested exactly 1 level below the given one. For instance, `` and `` are children of `` element.
+- **Descendants** -- all elements that are nested in the given one, including children, their children and so on. That is: the DOM subtree.
+
+The `childNodes` collection provides access to all child nodes, including text nodes.
+
+The example below shows children of `document.body`:
+
+```html run
+
+
+ Begin
+
+
+
+ End
+
+
+ ...more stuff...
+
+
+```
+
+Please note an interesting detail here. If we run the example above, the last element shown is `
+ ...
+
+
+```
+
+## More links, tables [#dom-navigation-tables]
+
+Till now we described the basic navigation properties. Certain DOM element types may provide more, specific to their type, for better convenience.
+
+Tables are a great example and important particular case of that.
+
+`` elements support these properties:
+- `table.rows` -- the collection of `` elements of the table.
+- `table.caption/tHead/tFoot` -- references to elements ``, ``, ` `.
+- `table.tBodies` -- the collection of `` elements (can be many according to the standard).
+
+``, ``, `` elements provide:
+- `tbody.rows` -- the collection of `` inside them.
+
+` `:
+- `tr.cells` -- the collection of `` and ` | ` cells inside the given ` | `.
+- `tr.sectionRowIndex` -- the number of the given ` ` inside the enclosing `/ `.
+- `tr.rowIndex` -- the number of the `` in the table.
+
+`` and ` | `:
+- `td.cellIndex` -- the number of the cell inside the enclosing ` | `.
+
+An example of usage:
+
+```html run height=100
+
+
+ one | two |
+
+
+ three | four |
+
+
+
+
+```
+
+The specification: [tabular data](https://html.spec.whatwg.org/multipage/tables.html).
+
+There are also additional navigation properties for HTML forms. We'll look at them later when start working with forms.
+
+# Summary
+
+The main navigation sets are:
+
+- `parentNode`, `childNodes`, `firstChild`, `lastChild`, `previousSibling`, `nextSibling` -- for all nodes.
+- `parentElement`, `children`, `firstElementChild`, `lastElementChild`, `previousElementSibling`, `nextElementSibling` -- if we take only element nodes into account.
+
+Some types of DOM elements, e.g. tables, provide additional properties and collections to access their content.
diff --git a/2-ui/1-document/3-dom-navigation/dom-links-elements.png b/2-ui/1-document/3-dom-navigation/dom-links-elements.png
new file mode 100644
index 00000000..f7eef5d1
Binary files /dev/null and b/2-ui/1-document/3-dom-navigation/dom-links-elements.png differ
diff --git a/2-ui/1-document/3-dom-navigation/dom-links-elements@2x.png b/2-ui/1-document/3-dom-navigation/dom-links-elements@2x.png
new file mode 100644
index 00000000..cf4e220c
Binary files /dev/null and b/2-ui/1-document/3-dom-navigation/dom-links-elements@2x.png differ
diff --git a/2-ui/1-document/3-dom-navigation/dom-links.png b/2-ui/1-document/3-dom-navigation/dom-links.png
new file mode 100644
index 00000000..25b25b37
Binary files /dev/null and b/2-ui/1-document/3-dom-navigation/dom-links.png differ
diff --git a/2-ui/1-document/3-dom-navigation/dom-links@2x.png b/2-ui/1-document/3-dom-navigation/dom-links@2x.png
new file mode 100644
index 00000000..84cd33d4
Binary files /dev/null and b/2-ui/1-document/3-dom-navigation/dom-links@2x.png differ
diff --git a/2-ui/1-document/3-dom-navigation/head.html b/2-ui/1-document/3-dom-navigation/head.html
new file mode 100644
index 00000000..5d763505
--- /dev/null
+++ b/2-ui/1-document/3-dom-navigation/head.html
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/2-ui/1-document/5-searching-elements-dom/1-find-elements/solution.md b/2-ui/1-document/5-searching-elements-dom/1-find-elements/solution.md
new file mode 100644
index 00000000..9842595f
--- /dev/null
+++ b/2-ui/1-document/5-searching-elements-dom/1-find-elements/solution.md
@@ -0,0 +1,27 @@
+Есть много вариантов решения, вот некоторые из них:
+
+```js
+// 1
+document.getElementById('age-table').getElementsByTagName('label');
+
+// 2
+document.getElementById('age-table').getElementsByTagName('td')[0];
+// в современных браузерах можно одним запросом:
+var result = document.querySelector('#age-table td');
+
+// 3
+document.getElementsByTagName('form')[1];
+
+// 4
+document.querySelector('form[name="search"]');
+
+// 5
+document.querySelector('form[name="search"] input')
+
+// 6
+document.getElementsByName("info[0]")[0];
+
+// 7
+document.querySelector('form[name="search-person"] [name="info[0]"]');
+```
+
diff --git a/2-ui/1-document/5-searching-elements-dom/1-find-elements/table.html b/2-ui/1-document/5-searching-elements-dom/1-find-elements/table.html
new file mode 100644
index 00000000..3484bc0c
--- /dev/null
+++ b/2-ui/1-document/5-searching-elements-dom/1-find-elements/table.html
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2-ui/1-document/5-searching-elements-dom/1-find-elements/task.md b/2-ui/1-document/5-searching-elements-dom/1-find-elements/task.md
new file mode 100644
index 00000000..6cbdbfa9
--- /dev/null
+++ b/2-ui/1-document/5-searching-elements-dom/1-find-elements/task.md
@@ -0,0 +1,20 @@
+importance: 4
+
+---
+
+# Поиск элементов
+
+Ниже находится документ с таблицей и формой.
+
+Найдите (получите в переменную) в нём:
+
+1. Все элементы `label` внутри таблицы. Должно быть 3 элемента.
+2. Первую ячейку таблицы (со словом `"Возраст"`).
+3. Вторую форму в документе.
+4. Форму с именем `search`, без использования её позиции в документе.
+5. Элемент `input` в форме с именем `search`. Если их несколько, то нужен первый.
+6. Элемент с именем `info[0]`, без точного знания его позиции в документе.
+7. Элемент с именем `info[0]`, внутри формы с именем `search-person`.
+
+Используйте для этого консоль браузера, открыв страницу [table.html](table.html) в отдельном окне.
+
diff --git a/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.md b/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.md
new file mode 100644
index 00000000..615c88d7
--- /dev/null
+++ b/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.md
@@ -0,0 +1,18 @@
+Сделаем цикл по узлам ``:
+
+```js
+var lis = document.getElementsByTagName('li');
+
+for (i = 0; i < lis.length; i++) {
+ ...
+}
+```
+
+В цикле для каждого `lis[i]` можно получить текст, используя свойство `firstChild`. Ведь первым в `` является как раз текстовый узел, содержащий текст названия.
+
+Также можно получить количество потомков, используя `lis[i].getElementsByTagName('li')`.
+
+Напишите код с этой подсказкой.
+
+Если уж не выйдет -- тогда откройте решение.
+
diff --git a/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.view/index.html b/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.view/index.html
new file mode 100644
index 00000000..e9b5d644
--- /dev/null
+++ b/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.view/index.html
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+ - Животные
+
+ - Млекопитающие
+
+ - Коровы
+ - Ослы
+ - Собаки
+ - Тигры
+
+
+ - Другие
+
+ - Змеи
+ - Птицы
+ - Ящерицы
+
+
+
+
+ - Рыбы
+
+ - Аквариумные
+
+
+
+ - Морские
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2-ui/1-document/5-searching-elements-dom/2-tree-info/source.view/index.html b/2-ui/1-document/5-searching-elements-dom/2-tree-info/source.view/index.html
new file mode 100644
index 00000000..2f45460c
--- /dev/null
+++ b/2-ui/1-document/5-searching-elements-dom/2-tree-info/source.view/index.html
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+ - Животные
+
+ - Млекопитающие
+
+ - Коровы
+ - Ослы
+ - Собаки
+ - Тигры
+
+
+ - Другие
+
+ - Змеи
+ - Птицы
+ - Ящерицы
+
+
+
+
+ - Рыбы
+
+ - Аквариумные
+
+
+
+ - Морские
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2-ui/1-document/5-searching-elements-dom/2-tree-info/task.md b/2-ui/1-document/5-searching-elements-dom/2-tree-info/task.md
new file mode 100644
index 00000000..c1fdc1db
--- /dev/null
+++ b/2-ui/1-document/5-searching-elements-dom/2-tree-info/task.md
@@ -0,0 +1,15 @@
+importance: 5
+
+---
+
+# Дерево
+
+Есть дерево из тегов `/- `.
+
+Напишите код, который для каждого элемента `
- ` выведет:
+
+1. Текст непосредственно в нём (без подразделов).
+2. Количество вложенных в него элементов `
- ` -- всех, с учётом вложенных.
+
+[demo src="solution"]
+
diff --git a/2-ui/1-document/5-searching-elements-dom/article.md b/2-ui/1-document/5-searching-elements-dom/article.md
new file mode 100644
index 00000000..4f4bf3f2
--- /dev/null
+++ b/2-ui/1-document/5-searching-elements-dom/article.md
@@ -0,0 +1,323 @@
+# Searching: getElement*, querySelector* and others
+
+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?
+
+There are additional searching methods for that.
+[cut]
+
+## document.getElementById or just id
+
+If an element has the `id` attribute, then there's a global variable by the name from that `id`.
+
+We can use it to access the element, like this:
+
+```html run
+
+
+
+```
+
+The behavior is described [in the specification](http://www.whatwg.org/specs/web-apps/current-work/#dom-window-nameditem), but it is supported mainly for compatibility, because relies on global variables. The browser tries to help us by mixing namespaces of JS and DOM, but there may be conflicts.
+
+The better alternative is to use a special method `document.getElementById(id)`.
+
+For instance:
+
+```html run
+
+
+
+```
+
+```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`.
+
+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.
+```
+
+I will often use `id` to directly reference an element in examples, but that's only to keep things short. In real life `document.getElementById` is definitely the preferred method.
+
+## getElementsBy*
+
+There are also other methods of this kind:
+
+`elem.getElementsByTagName(tag)` looks for elements with the given tag and returns the collection of them. The `tag` can also be `*` for any.
+
+For instance:
+```js
+// get all divs in the document
+let divs = document.getElementsByTagName('div');
+```
+
+Unlike `getElementById` that can be called only on `document`, this method can look inside any element.
+
+Let's find all `input` inside the table:
+
+```html run height=50
+
+
+
+```
+
+```warn header="Don't forget the `\"s\"` letter!"
+Novice developers sometimes forget the letter `"s"`. That is, they try to call `getElementByTagName` instead of
getElementsByTagName .
+
+The `"s"` letter is only absent in `getElementById`, because we look for a single element. But `getElementsByTagName` returns a collection.
+```
+
+````warn header="It returns a collection, not an element!"
+Another widespread novice mistake is to write like:
+
+```js
+// doesn't work
+document.getElementsByTagName('input').value = 5;
+```
+
+That won't work, because we take a *collection* of inputs and assign the value to it, rather to elements inside it.
+
+We should either iterate over the collection or get an element by the number, and then assign, like this:
+
+```js
+// should work (if there's an input)
+document.getElementsByTagName('input')[0].value = 5;
+```
+````
+
+Other methods:
+
+- `document.getElementsByName(name)` returns elements with the given `name` attribute. Rarely used.
+- `elem.getElementsByClassName(className)` returns elements that have the given CSS class. Elements may have other classes too.
+
+For instance:
+
+```html run height=50
+
+
+
+```
+
+## querySelectorAll [#querySelectorAll]
+
+Now the heavy artillery.
+
+The call to `elem.querySelectorAll(css)` returns all elements inside `elem` matching the given CSS selector. That's the most often used and powerful method.
+
+Here we look for all ` - ` elements that are last children:
+
+```html run
+
+
+
+```
+
+```smart header="Can use pseudo-classes as well"
+Pseudo-classes in the CSS selector like `:hover` and `:active` are also supported. For instance, `document.querySelectorAll(':hover')` will return the collection with elements that the pointer is over now (in nesting order: from the outmost `` to the most nested one).
+```
+
+## querySelector [#querySelector]
+
+The call to `elem.querySelector(css)` returns the first element for the given CSS selector.
+
+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.
+
+## matches
+
+Previous methods were searching the DOM.
+
+The [elem.matches(css)](http://dom.spec.whatwg.org/#dom-element-matches) does not look for anything, it merely checks if `elem` fits the CSS-selector. It returns `true` or `false`.
+
+The method comes handy when we are walking over elements (like in array or something) and trying to filter those that interest us.
+
+For instance:
+
+```html run
+...
+...
+
+
+```
+
+## closest
+
+The method `elem.closest(css)` looks the nearest ancestor (parent or his parent and so on) that matches the CSS-selector. The `elem` itself is also included in the search.
+
+In other words, the method `closest` goes up from the element and checks each of them. If it matches, then stops the search and returns it.
+
+For instance:
+
+```html run
+
+ - Chapter I
+
+ - Chapter 1.1
+ - Chapter 1.2
+
+
+
+
+
+```
+
+## XPath в современных браузерах
+
+Для полноты картины рассмотрим ещё один способ поиска, который обычно используется в XML. Это язык запросов XPath.
+
+Он очень мощный, во многом мощнее CSS, но сложнее. Например, запрос для поиска элементов `H2`, содержащих текст `"XPath"`, будет выглядеть так: `//h2[contains(., "XPath")]`.
+
+Все современные браузеры, кроме IE, поддерживают XPath с синтаксисом, близким к [описанному в MDN](https://developer.mozilla.org/en/XPath).
+
+Найдем заголовки с текстом `XPath` в текущем документе:
+
+```js run no-beautify
+var result = document.evaluate("//h2[contains(., 'XPath')]", document.documentElement, null,
+ XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+
+for (var i = 0; i < result.snapshotLength; i++) {
+ alert( result.snapshotItem(i).outerHTML );
+}
+```
+
+IE тоже поддерживает XPath, но эта поддержка не соответствует стандарту и работает только для XML-документов, например, полученных с помощью `XMLHTTPRequest` (AJAX). Для обычных же HTML-документов XPath в IE не поддерживается.
+
+Так как XPath сложнее и длиннее CSS, то используют его очень редко.
+
+## Итого
+
+Есть 6 основных методов поиска элементов DOM:
+
+
+
+Метод |
+Ищет по... |
+Ищет внутри элемента? |
+Поддержка |
+
+
+
+
+getElementById |
+id |
+- |
+везде |
+
+
+getElementsByName |
+name |
+- |
+везде |
+
+
+getElementsByTagName |
+тег или '*' |
+✔ |
+везде |
+
+
+getElementsByClassName |
+классу |
+✔ |
+кроме IE8- |
+
+
+querySelector |
+CSS-селектор |
+✔ |
+везде |
+
+
+querySelectorAll |
+CSS-селектор |
+✔ |
+везде |
+
+
+
+
+Практика показывает, что в 95% ситуаций достаточно `querySelector/querySelectorAll`. Хотя более специализированные методы `getElement*` работают чуть быстрее, но разница в миллисекунду-другую редко играет роль.
+
+Кроме того:
+
+- Есть метод `elem.matches(css)`, который проверяет, удовлетворяет ли элемент CSS-селектору. Он поддерживается большинством браузеров в префиксной форме (`ms`, `moz`, `webkit`).
+- Метод `elem.closest(css)` ищет ближайший элемент выше по иерархии DOM, подходящий под CSS-селектор css. Сам элемент тоже включается в поиск.
+- Язык запросов XPath поддерживается большинством браузеров, кроме IE, даже 9-й версии, но `querySelector` удобнее. Поэтому XPath используется редко.
diff --git a/contributors.md b/contributors.md
new file mode 100644
index 00000000..ee3c4661
--- /dev/null
+++ b/contributors.md
@@ -0,0 +1,13 @@
+
+The file lists people who made significant contributions to the project:
+
+
+- Alexey Maximov @amaxcz (admin)
+- Alexey Shisterov (tutorial)
+- Anton Vernogor @smmurf (markup)
+- Artem Beztsenny @bezart (design)
+- Илья Кантор @iliakan (tutorial, code)
+- Юрий Ткаченко @tyv (markup)
+
+
+The project exists for a long time, I might have missed someone. If you expect to find yourself in the list, but you're not -- please mail me at mk@javascript.ru.
diff --git a/figures.sketch b/figures.sketch
index e5ef8b74..baf67eee 100644
Binary files a/figures.sketch and b/figures.sketch differ
|