`
+2. Write properties directly into `style`: `
`.
+
+[cut]
+
+CSS is always the preferred way, both in HTML and Javascript. We should only use `style` if classes "can't handle it".
+
+For instance, `style` is acceptable if we calculated coordinates for an element dynamically and want to set them from Javascript, like here:
+
+```js
+let top = /* complex calculations */;
+let left = /* complex calculations */;
+elem.style.left = left; // e.g '123px'
+elem.style.top = top; // e.g '456px'
+```
+
+For other cases, like making the text red, adding a background icon -- describe that in CSS and then apply the class. That's more flexible and easier to support.
+
+## className and classList
+
+Changing a class is one of the most often actions in scripts.
+
+In the ancient time, there was a limitation in Javascript: a reserved word like `"class"` could not be an object property. That limitation does not exist now, but at that time it was impossible to use `elem.class`.
+
+So instead of `elem.class` we have `elem.className` property. It's the string with all classes, the same value as in the `"class"` attribute.
+
+For instance:
+
+```html run
+
+
+
+```
+
+Adding/removing a class is a widespread operation. Using a string for such purpose is cumbersome, so there's another property for that: `elem.classList`.
+
+The `elem.classList` is a special object with methods to `add/remove/toggle` classes.
+
+For instance:
+
+```html run
+
+
+
+```
+
+So we can operate both on the full class string using `className` or on individual classes using `classList`. What we choose depends on our needs.
+
+Methods of `classList`:
+
+- `elem.classList.add/remove("class")` -- adds/removes the class.
+- `elem.classList.toggle("class")` -- if the class exists, then removes it, otherwise adds it.
+- `elem.classList.contains("class")` -- returns `true/false`, checks for the given class.
+
+Besides that, `classList` is iterable, so we can list all classes like this:
+
+```html run
+
+
+
+```
+
+## Element style
+
+The property `elem.style` is an object that corresponds to what's written in the `"style"` attribute. Setting `elem.style.width="100px"` works as if we had in the attribute `style="width:100px"`.
+
+For multi-word property the camelCase is used:
+
+```js no-beautify
+background-color => elem.style.backgroundColor
+z-index => elem.style.zIndex
+border-left-width => elem.style.borderLeftWidth
+```
+
+For instance:
+
+```js run
+document.body.style.backgroundColor = prompt('background color?', 'green');
+```
+
+````smart header="Prefixed properties"
+Browser-prefixed properties like `-moz-border-radius`, `-webkit-border-radius` also follow the same rule, for instance:
+
+```js
+button.style.MozBorderRadius = '5px';
+button.style.WebkitBorderRadius = '5px';
+```
+
+That is: a dash `"-"` becomes an uppercase.
+````
+
+## Resetting the style
+
+To "reset" the style property, we should assign an empty line to it. For instance, if we set a `width` and now want to remove it, then `elem.style.width=""`.
+
+For instance, to hide an element, we can set `elem.style.display = "none"`.
+
+And to show it back, we should not set another `display` like `elem.style.display = "block"`. To return the "default" `display`: `elem.style.display = ""`.
+
+```js run
+// if we run this code, the would "blink"
+document.body.style.display = "none";
+
+setTimeout(() => document.body.style.display = "", 1000);
+```
+
+If we set `display` to an empty string, then the browser applies CSS classes and its built-in styles normally, as if there were no such `style` property.
+
+````smart header="Full rewrite with `style.cssText`"
+Normally, `style.*` assign individual style properties. We can't set the full style like `div.style="color: red; width: 100px"`, because `div.style` is an object.
+
+To set the full style as a string, there's a special property `style.cssText`:
+
+```html run
+
Button
+
+
+```
+
+We rarely use it, because such a setting removes all existing styles: not adds, but rather replaces them. But still can be done for new elements when we know we don't delete something important.
+
+The same can be accomplished by setting an attribute: `div.setAttribute('style', "color: red...")`.
+````
+
+## Mind the units
+
+CSS units must exist in values. We should not set `elem.style.top` to `10`, but rather to `10px`. Otherwise it wouldn't work.
+
+For instance:
+
+```html run height=100
+
+
+
+```
+
+Please note how the browser "unpacks" the property `style.margin` and infers `style.marginLeft` and `style.marginTop` (and other partial margins) from it.
+
+## Computed styles: getComputedStyle
+
+Modifying a style is easy. But how to *read* it?
+
+For instance, we want to know the size, margins, the color of an element. How to do it?
+
+**The `style` property contains only the style in the `"style"` attribute, without any CSS cascade.**
+
+So we can't read anything that comes from CSS classes.
+
+For instance, here `style` won't see the margin:
+
+```html run height=60 no-beautify
+
+
+
+
+
+ The red text
+
+
+```
+
+...But what if we need, say, increase the margin by 20px? We want the current value for that.
+
+There's another method for that: `getComputedStyle`.
+
+The syntax is:
+
+```js
+getComputedStyle(element[, pseudo])
+```
+
+element
+: Element to read the value for.
+
+pseudo
+: A pseudo-element if required, for instance `::before`. An empty string or no argument mean the element itself.
+
+The result is an object with style properties, like `elem.style`, but now with respect to all CSS classes.
+
+For instance:
+
+```html run height=100
+
+
+
+
+
+
+
+
+```
+
+```smart header="Computed and resolved values"
+There are two concepts in [CSS](https://drafts.csswg.org/cssom/#resolved-values):
+
+1. A *computed* style value is the one after all CSS rules and CSS inheritance is applied. If can look like `width: auto` or `font-size: 125%`.
+2. A *resolved* style value is the one finally applied to the element. The browser takes the computed value and makes all units fixed and absolute, for instance: `width: 212px` or `font-size: 16px`. In some browsers values can have a floating point.
+
+Long time ago `getComputedStyle` was created to get computed values, but it turned out that resolved values are much more convenient.
+
+So nowadays `getComputedStyle` actually returns the final, resolved value.
+```
+
+````warn header="`getComputedStyle` requires the full property name"
+We should always ask for the exact property that we want, like `paddingLeft` or `marginTop` or `borderTopWidth`. Otherwise the correct result is not guaranteed.
+
+For instance, if properties `paddingLeft/paddingTop` come from the different CSS classes, then what should we get for `getComputedStyle(elem).padding`?
+
+Some browsers (Chrome) show `10px` in the document below, and some of them (Firefox) -- do not:
+
+```html run
+
+
+```
+````
+
+```smart header="\"Visited\" links styles are hidden!"
+Visited links may be colored using `:visited` CSS pseudoclass.
+
+But `getComputedStyle` does not give access to that color, because otherwise an arbitrary page could find out whether the user visited a link by creating it on the page and checking the styles.
+
+Javascript we may not see the styles applied by `:visited`. And also, there's a limitation in CSS that forbids to apply geometry-changing styles in `:visited`. That's to guarantee that there's no side way for an evil page to see if a link was visited and hence to break the privacy.
+```
+
+## Summary
+
+To manage classes, there are two DOM properties:
+- `className` -- the string value, good to manage the whole set of classes.
+- `classList` -- the object with methods `add/remove/toggle/contains`, good for individual classes.
+
+To change the styles:
+
+- The `style` property is an object with camelCased styles. Reading and writing to it has the same meaning as modifying individual properties in the `"style"` attribute. To see how to apply `important` and other rare stuff -- there's a list of methods at [MDN](mdn:api/CSSStyleDeclaration).
+
+- The `style.cssText` property corresponds to the whole `"style"` attribute, the full string of styles.
+
+To read the resolved styles (after all CSS is applied and final values are calculated):
+
+- The `getComputedStyles(elem[, pseudo])` returns the style-like object with them. Read-only.
diff --git a/2-ui/1-document/14-styles-and-classes/getiecomputedstyle.view/getiecomputedstyle.js b/2-ui/1-document/14-styles-and-classes/getiecomputedstyle.view/getiecomputedstyle.js
new file mode 100644
index 00000000..12a7e04c
--- /dev/null
+++ b/2-ui/1-document/14-styles-and-classes/getiecomputedstyle.view/getiecomputedstyle.js
@@ -0,0 +1,18 @@
+function getIEComputedStyle(elem, prop) {
+ var value = elem.currentStyle[prop] || 0;
+
+ // we use 'left' property as a place holder so backup values
+ var leftCopy = elem.style.left;
+ var runtimeLeftCopy = elem.runtimeStyle.left;
+
+ // assign to runtimeStyle and get pixel value
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ elem.style.left = (prop === "fontSize") ? "1em" : value;
+ value = elem.style.pixelLeft + "px";
+
+ // restore values for left
+ elem.style.left = leftCopy;
+ elem.runtimeStyle.left = runtimeLeftCopy;
+
+ return value;
+}
\ No newline at end of file
diff --git a/2-ui/1-document/14-styles-and-classes/getiecomputedstyle.view/index.html b/2-ui/1-document/14-styles-and-classes/getiecomputedstyle.view/index.html
new file mode 100644
index 00000000..a757f39f
--- /dev/null
+++ b/2-ui/1-document/14-styles-and-classes/getiecomputedstyle.view/index.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
Тестовый элемент с margin 1%
+
+
+
+
+
\ No newline at end of file
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
index 615c88d7..5bb2effa 100644
--- 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
@@ -1,18 +1,19 @@
-Сделаем цикл по узлам `
`:
+Let's make a loop over ``:
```js
-var lis = document.getElementsByTagName('li');
-
-for (i = 0; i < lis.length; i++) {
+for (let li of document.querySelector('li')) {
...
}
```
-В цикле для каждого `lis[i]` можно получить текст, используя свойство `firstChild`. Ведь первым в `` является как раз текстовый узел, содержащий текст названия.
+In the loop we need to get the text inside every `li`. We can read it directly from the first child node, that is the text node:
-Также можно получить количество потомков, используя `lis[i].getElementsByTagName('li')`.
+```js
+for (let li of document.querySelector('li')) {
+ let title = li.firstChild.data;
-Напишите код с этой подсказкой.
-
-Если уж не выйдет -- тогда откройте решение.
+ // title is the text in before any other nodes
+}
+```
+Then we can get the number of descendants `li.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
index e9b5d644..d712bb9d 100644
--- 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
@@ -1,44 +1,38 @@
-
-
-
-
-
- - Животные
+
- Animals
- - Млекопитающие
+
- Mammals
- - Коровы
- - Ослы
- - Собаки
- - Тигры
+ - Cows
+ - Donkeys
+ - Dogs
+ - Tigers
- - Другие
+
- Other
- - Змеи
- - Птицы
- - Ящерицы
+ - Snakes
+ - Birds
+ - Lizards
- - Рыбы
+
- Fishes
- - Аквариумные
+
- Aquarium
- - Гуппи
- - Скалярии
+ - Guppy
+ - Angelfish
-
- - Морские
+
- Sea
- - Морская форель
+ - Sea trout
@@ -46,21 +40,18 @@
-
-
\ 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
index 2f45460c..fbfacaa8 100644
--- 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
@@ -1,44 +1,38 @@
-
-
-
-
-
- - Животные
+
- Animals
- - Млекопитающие
+
- Mammals
- - Коровы
- - Ослы
- - Собаки
- - Тигры
+ - Cows
+ - Donkeys
+ - Dogs
+ - Tigers
- - Другие
+
- Other
- - Змеи
- - Птицы
- - Ящерицы
+ - Snakes
+ - Birds
+ - Lizards
- - Рыбы
+
- Fishes
- - Аквариумные
+
- Aquarium
- - Гуппи
- - Скалярии
+ - Guppy
+ - Angelfish
-
- - Морские
+
- Sea
- - Морская форель
+ - Sea trout
@@ -46,9 +40,8 @@
-
-
\ 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
index c1fdc1db..f2d9edc6 100644
--- 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
@@ -2,14 +2,13 @@ importance: 5
---
-# Дерево
+# Count descendants
-Есть дерево из тегов `/- `.
+There's a tree structured as nested `ul/li`.
-Напишите код, который для каждого элемента `
- ` выведет:
+Write the code that for each `
- ` shows:
-1. Текст непосредственно в нём (без подразделов).
-2. Количество вложенных в него элементов `
- ` -- всех, с учётом вложенных.
+1. What's the text inside it (without the subtree)
+2. The number of nested `
- ` -- all descendants, including the deeply nested ones.
[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
index 0b64a684..acd77093 100644
--- a/2-ui/1-document/5-searching-elements-dom/article.md
+++ b/2-ui/1-document/5-searching-elements-dom/article.md
@@ -215,27 +215,20 @@ In other words, the method `closest` goes up from the element and checks each of
For instance:
```html run
-
- - Chapter I
-
- - Chapter 1.1
- - Chapter 1.2
-
-
+Contents
+
+
```
diff --git a/2-ui/1-document/9-attributes-and-properties/1-get-user-attribute/task.md b/2-ui/1-document/9-attributes-and-properties/1-get-user-attribute/task.md
index 9d0e7fd8..0d11ff97 100644
--- a/2-ui/1-document/9-attributes-and-properties/1-get-user-attribute/task.md
+++ b/2-ui/1-document/9-attributes-and-properties/1-get-user-attribute/task.md
@@ -11,7 +11,7 @@ Write the code to select the element with `data-widget-name` attribute from the
- Выберите жанр
+ Choose the genre
diff --git a/2-ui/1-document/9-attributes-and-properties/2-set-class-links/task.md b/2-ui/1-document/9-attributes-and-properties/2-yellow-links/task.md
similarity index 72%
rename from 2-ui/1-document/9-attributes-and-properties/2-set-class-links/task.md
rename to 2-ui/1-document/9-attributes-and-properties/2-yellow-links/task.md
index 8caf2047..732e3dc9 100644
--- a/2-ui/1-document/9-attributes-and-properties/2-set-class-links/task.md
+++ b/2-ui/1-document/9-attributes-and-properties/2-yellow-links/task.md
@@ -2,21 +2,17 @@ importance: 3
---
-# Add the class to external links
+# Make external links yellow
-Make all external links yellow by adding them the class `"external"`.
+Make all external links yellow by altering their `style` property.
A link is external if:
- It's `href` has `://` in it
- But doesn't start with `http://internal.com`.
-```html run
-
+Example:
+```html run
the list
+
+
```
The result should be:
diff --git a/2-ui/1-document/9-attributes-and-properties/article.md b/2-ui/1-document/9-attributes-and-properties/article.md
index f97b4c3a..0d17db15 100644
--- a/2-ui/1-document/9-attributes-and-properties/article.md
+++ b/2-ui/1-document/9-attributes-and-properties/article.md
@@ -1,4 +1,4 @@
-# DOM: attributes and properties
+# DOM: attributes and properties
The browser "reads" HTML text and generates DOM objects from it. For element nodes most standard HTML attributes automatically become properties of DOM objects.
@@ -204,7 +204,18 @@ DOM properties are not always strings. For instance, `input.checked` property (f
```
-Javascript enforces the right type for a DOM property.
+There are more advanced examples. As we've already seen, `style` property is an object:
+
+```html run
+Hello
+
+
+```
**But even if a DOM property type is a string, it may differ from the attribute.**
@@ -226,50 +237,6 @@ Here we can see that:
Let's note again: if we need the value exactly as written in the HTML, we need to use `getAttribute`.
-## className and classList
-
-The `"class"` attribute is truly special, as there are two properties that correspond to it:
-1. `className` -- the string, same value as in the attribute. In the old times, there was a problem to use a reserved word such as `"class"` as an object property (now it's ok). So `className` was chosen instead.
-2. `classList` -- a special object with methods to `add/remove/toggle` classes. That's for better convenience.
-
-For instance:
-
-```html run
-
-
-
-```
-
-So we can operate both on the full class string using `className` or on individual classes using `classList`. What we choose depends on our needs.
-
-Methods of `classList`:
-
-- `elem.classList.contains("class")` -- returns `true/false`, checks for the given class.
-- `elem.classList.add/remove("class")` -- adds/removes the class.
-- `elem.classList.toggle("class")` -- if the class exists, then removes it, otherwise adds it.
-
-Besides that, `classList` is iterable, so we can list all classes like this:
-
-```html run
-
-
-
-```
-
## Non-standard attributes, dataset
When writing HTML, we use a lot of standard attributes. But what about non-standard, custom ones? May they be useful? What for?
@@ -333,15 +300,7 @@ That's because an attribute is more convenient to manage. If we want to change t
div.setAttribute('order-state', 'canceled');
```
-For classes we would have to clean the current state and add the new one. More cumbersome:
-
-```js
-// two lines, and we need to know the old class to clean it
-div.classList.remove('order-state-new');
-div.classList.add('order-state-canceled');
-```
-
-...But there's a problem here. What if we use a non-standard attribute for our purposes and later the standard introduces it and makes it do something? The HTML language is alive, it grows, more attributes appear to suit the needs of developers. There may be unexpected side-effects.
+...But there may be a possible problem here. What if we use a non-standard attribute for our purposes and later the standard introduces it and makes it do something? The HTML language is alive, it grows, more attributes appear to suit the needs of developers. There may be unexpected side-effects.
To evade conflicts, there exist [data-*](https://html.spec.whatwg.org/#embedding-custom-non-visible-data-with-the-data-*-attributes) attributes.
@@ -432,7 +391,3 @@ Some use cases:
- We want to access a non-standard attribute. But if it starts with `data-`, then we should use `dataset`.
- We want to read the value "as written" in HTML. The value of the DOM property may be different, for instance `href` property is always a full URL, and we may want to get the "original" value.
-
-Also please note that for `class` attribute there are two DOM properties:
-- `className` -- the string value.
-- `classList` -- the object for easier management of individual classes.