diff --git a/3-more/2-animation/2-bezier/demo.svg b/3-more/2-animation/2-bezier/demo.svg
deleted file mode 100755
index 5ff89a6e..00000000
--- a/3-more/2-animation/2-bezier/demo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/3-more/2-animation/index.md b/3-more/2-animation/index.md
deleted file mode 100644
index d940e7df..00000000
--- a/3-more/2-animation/index.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Анимация
-
diff --git a/3-more/2-animation/2-bezier/article.md b/3-more/3-animation/1-bezier/article.md
similarity index 62%
rename from 3-more/2-animation/2-bezier/article.md
rename to 3-more/3-animation/1-bezier/article.md
index 9696fd1b..5d7cf395 100644
--- a/3-more/2-animation/2-bezier/article.md
+++ b/3-more/3-animation/1-bezier/article.md
@@ -1,14 +1,13 @@
# Кривые Безье
-Кривые Безье используются в компьютерной графике для рисования плавных изгибов, в [CSS-анимации](#css-animation) для описания процесса анимации и много где ещё.
+Кривые Безье используются в компьютерной графике для рисования плавных изгибов, в CSS-анимации и много где ещё.
-Тему эту стоит изучить, чтобы в дальнейшем с комфортом пользоваться этим замечательным инструментом.
+Несмотря на "умное" название -- это очень простая штука.
+
+В принципе, можно создавать анимацию и без знания кривых Безье, но стоит один раз прочитать, что это такое, так как в векторной графике и продвинутых анимаций без них никак. Это образовательный минимум.
+
+Тему эту стоит изучить один раз, чтобы в дальнейшем с комфортом пользоваться этим замечательным инструментом.
[cut]
-
## Виды кривых Безье
@@ -16,29 +15,24 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
Их может быть две, три, четыре или больше. Например:
-
-
-
По двум точкам
-
По трём точкам
-
По четырём точкам
-
-
-
+По двум точкам:
+
-
-
+
+По трём точкам:
+
-
-
+
+По четырём точкам:
+
-
-
-
+
Если вы посмотрите внимательно на эти кривые, то "на глазок" заметите:
+
**Точки не всегда на кривой.** Это совершенно нормально, как именно строится кривая мы рассмотрим чуть позже.
**Степень кривой равна числу точек минус один**.
-На рисунках выше, соответственно, получаются для двух точек -- линейная кривая (прямая), для трёх точек -- квадратическая кривая (парабола), для четырёх -- кубическая.
+Для двух точек -- это линейная кривая (т.е. прямая), для трёх точек -- квадратическая кривая (парабола), для четырёх -- кубическая.
**Кривая всегда находится внутри [выпуклой оболочки](http://ru.wikipedia.org/wiki/%D0%92%D1%8B%D0%BF%D1%83%D0%BA%D0%BB%D0%B0%D1%8F_%D0%BE%D0%B1%D0%BE%D0%BB%D0%BE%D1%87%D0%BA%D0%B0), образованной опорными точками:**
@@ -47,13 +41,13 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
-Основная ценность кривых Безье -- в том, что **кривую можно менять, двигая точки**. При этом **кривая меняется интуитивно понятным образом**.
+Основная ценность кривых Безье -- в том, что, двигая точки, кривую можно менять, причём кривая при этом меняется интуитивно понятным образом.
Попробуйте двигать точки мышью в примере ниже:
[iframe src="demo.svg?nocpath=1&p=0,0,0.5,0,0.5,1,1,1" height=370]
-Как можно заметить, **кривая натянута по касательным 1 -> 2 и 3 -> 4.**
+**Как можно заметить, кривая натянута по касательным 1 -> 2 и 3 -> 4.**
После небольшой практики становится понятно, как расположить точки, чтобы получить нужную форму. А, соединяя несколько кривых, можно получить практически что угодно.
@@ -63,7 +57,9 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
## Математика
-У кривых Безье есть математическая формула. Как мы увидим далее, в ней нет особенной необходимости, но для полноты картины -- вот она.
+У кривых Безье есть математическая формула.
+
+Как мы увидим далее, для пользования кривыми Безье знать её нет особенной необходимости, но для полноты картины -- вот она.
**Координаты кривой описываются в зависимости от параметра `t⋲[0,1]`**
@@ -88,28 +84,39 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
-Эти уравнения -- векторные, т.е. вместо Pi нужно подставить координаты i-й опорной точки (xi, yi).
+Вместо Pi нужно подставить координаты i-й опорной точки (xi, yi).
-Формула даёт возможность строить кривые, но не очень понятно, почему они именно такие, и как зависят от опорных точек. С этим нам поможет разобраться другой алгоритм.
+Эти уравнения векторные, то есть на для каждой из координат:
+
+
x = (1−t)2x1 + 2(1−t)tx2 + t2x3
+
y = (1−t)2y1 + 2(1−t)ty2 + t2y3
+
+
+Вместо x1, y1, x2, y2, x3, y3 подставляются координаты трёх опорных точек, и в то время как `t` пробегает множество от `0` до `1`, соответствующие значения `(x, y)` как раз и образуют кривую.
+
+Впрочем, это чересчур наукообразно, не очень понятно, почему кривые именно такие, и как зависят от опорных точек. С этим нам поможет разобраться другой, более наглядный алгоритм.
## Рисование "де Кастельжо"
[Метод де Кастельжо](http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%B5_%D0%9A%D0%B0%D1%81%D1%82%D0%B5%D0%BB%D1%8C%D0%B6%D0%BE) идентичен математическому определению кривой и наглядно показывает, как она строится.
-Посмотрим его на примере трех точек (точки можно двигать). Нажатие на кнопку "edit" запустит демонстрацию.
+Посмотрим его на примере трёх точек (точки можно двигать). Нажатие на кнопку "play" запустит демонстрацию.
[iframe src="demo.svg?p=0,0,0.5,1,1,0&animate=1" height=370]
-**Алгоритм построения "де Кастельжо":**
+**Алгоритм построения кривой по "методу де Кастельжо":**
-
-
Строятся отрезки между опорными точками 1-2-3. На рисунке выше они **чёрные**.
+
Рисуем опорные точки. В примере выше это `1`, `2`, `3`.
+
Строятся отрезки между опорными точками 1 -> 2 -> 3. На рисунке выше они **чёрные**.
Параметр `t` пробегает значения от `0` до `1`. В примере выше использован шаг `0.05`, т.е. в цикле `0, 0.05, 0.1, 0.15, ... 0.95, 1`.
-Для каждого значения `t`:
+Значение `t` пробегает интервал от 0 до 1, для каждого `t`:
-
На каждом из этих отрезков берётся точка, находящаяся от начала на расстоянии от 0 до `t` пропорционально длине. То есть, при `t=0` -- точка будет в начале, при `t=0.25` -- на расстоянии в 25% от начала отрезка, при `t=0.5` -- 50%(на середине), при `t=1` -- в конце. Так как **чёрных** отрезков -- два, то и точек выходит две штуки.
+
На каждом из этих отрезков берётся точка, находящаяся от начала на расстоянии от 0 до `t` пропорционально длине. Так как чёрных отрезков -- два, то и точек выходит две штуки.
+
+То есть, при `t=0` -- точки будут в начале, при `t=0.25` -- на расстоянии в 25% от начала отрезка, при `t=0.5` -- 50%(на середине), при `t=1` -- в конце отрезка.
+
Эти точки соединяются. На рисунке ниже соединяющий их отрезок изображён синим.
@@ -121,7 +128,7 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
-
На получившемся отрезке берётся точка на расстоянии, соответствующем `t`. То есть, для `t=0.25` получаем точку в конце первой четверти отрезка, для `t=0.5` -- в середине отрезка. На рисунке выше эта точка отмечена красным.
+
На получившемся отрезке берётся точка на расстоянии, соответствующем `t`. То есть, для `t=0.25` (первый рисунок) получаем точку в конце первой четверти отрезка, для `t=0.5` (второй рисунок) -- в середине отрезка. На рисунках выше эта точка отмечена красным.
@@ -138,14 +145,14 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
Алгоритм:
-
Точки по порядку соединяются отрезками: `1-2`, `2-3`, `3-4`. Получается три чёрных отрезка.
+
Точки по порядку соединяются отрезками: 1 -> 2, 2 -> 3, 3 -> 4. Получается три чёрных отрезка.
На отрезках берутся точки, соответствующие текущему `t`, соединяются. Получается два зелёных отрезка.
На этих отрезках берутся точки, соответствующие текущему `t`, соединяются. Получается один синий отрезок.
На синем отрезке берётся точка, соответствующая текущему `t`. При запуске примера выше она красная.
Эти точки описывают кривую.
-Нажмите на кнопку "edit" в примере выше, чтобы увидеть это в действии.
+Нажмите на кнопку "play" в примере выше, чтобы увидеть это в действии.
Ещё примеры кривых:
@@ -165,12 +172,12 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
Аналогичным образом могут быть построены кривые Безье и более высокого порядка: по пяти точкам, шести и так далее. Но обычно используются 2-3 точки, а для сложных линий несколько кривых соединяются. Это гораздо проще с точки зрения поддержки и расчётов.
-[smart header="Как провести кривую через нужные точки?"]
-Этот вопрос не связан с кривыми Безье, но он иногда возникает в смежных задачах.
+[smart header="Как провести кривую Безье через нужные точки?"]
+Кривые Безье обычно проводятся через "опорные" точки, которые, как можно видеть из примеров выше, редко лежат на кривой.
-Такая задача называется [интерполяцией](http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D0%BE%D0%BB%D1%8F%D1%86%D0%B8%D1%8F). Существуют математические формулы, которые подбирают коэффициенты кривой по точкам, исходя из требований, например [многочлен Лагранжа](http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D0%BE%D0%BB%D1%8F%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE%D1%87%D0%BB%D0%B5%D0%BD_%D0%9B%D0%B0%D0%B3%D1%80%D0%B0%D0%BD%D0%B6%D0%B0).
+Если нужно провести кривую именно через нужные точки, то это уже другая задача. Она называется [интерполяцией](http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D0%BE%D0%BB%D1%8F%D1%86%D0%B8%D1%8F). Существуют математические формулы, которые подбирают коэффициенты кривой по точкам, исходя из требований, например [многочлен Лагранжа](http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D0%BE%D0%BB%D1%8F%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE%D1%87%D0%BB%D0%B5%D0%BD_%D0%9B%D0%B0%D0%B3%D1%80%D0%B0%D0%BD%D0%B6%D0%B0).
-Как правило, в компьютерной графике для интерполяции используют кубические кривые, соединённых гладким образом. Вместе они выглядят как одна кривая. Это называется [интерполяция сплайнами](http://ru.wikipedia.org/wiki/%D0%9A%D1%83%D0%B1%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D1%81%D0%BF%D0%BB%D0%B0%D0%B9%D0%BD).
+Как правило, в компьютерной графике для интерполяции используют кубические кривые, соединённых гладким образом. Вместе они выглядят как одна кривая. Это называется [интерполяция сплайнами](http://ru.wikipedia.org/wiki/%D0%9A%D1%83%D0%B1%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D1%81%D0%BF%D0%BB%D0%B0%D0%B9%D0%BD).
[/smart]
## Итого
@@ -180,12 +187,16 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
Через процесс построения де Кастельжо.
-С их помощью можно описать почти любую линию, особенно если соединить несколько.
+Их удобство в том, что:
+
+
Можно легко нарисовать плавные линии вручную, передвигая точки мышкой.
+
Более сложные изгибы и линии можно составить, если соединить несколько кривых Безье.
+
Применение:
В компьютерной графике, моделировании, в графических редакторах. Шрифты описываются с помощью кривых Безье.
В веб-разработке -- для графики на Canvas или в формате SVG. Кстати, все живые примеры выше написаны на SVG. Фактически, это один SVG-документ, к которому точки передаются параметрами. Вы можете открыть его в отдельном окне и посмотреть исходник: demo.svg.
-
В CSS-анимации, для задания временной функции.
+
В CSS-анимации, для задания траектории и скорости передвижения.
\ No newline at end of file
diff --git a/3-more/2-animation/2-bezier/bezier2.png b/3-more/3-animation/1-bezier/bezier2.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/2-bezier/bezier2.png
rename to 3-more/3-animation/1-bezier/bezier2.png
diff --git a/3-more/2-animation/2-bezier/bezier3-draw1.png b/3-more/3-animation/1-bezier/bezier3-draw1.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/2-bezier/bezier3-draw1.png
rename to 3-more/3-animation/1-bezier/bezier3-draw1.png
diff --git a/3-more/2-animation/2-bezier/bezier3-draw2.png b/3-more/3-animation/1-bezier/bezier3-draw2.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/2-bezier/bezier3-draw2.png
rename to 3-more/3-animation/1-bezier/bezier3-draw2.png
diff --git a/3-more/2-animation/2-bezier/bezier3-e.png b/3-more/3-animation/1-bezier/bezier3-e.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/2-bezier/bezier3-e.png
rename to 3-more/3-animation/1-bezier/bezier3-e.png
diff --git a/3-more/2-animation/2-bezier/bezier3.png b/3-more/3-animation/1-bezier/bezier3.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/2-bezier/bezier3.png
rename to 3-more/3-animation/1-bezier/bezier3.png
diff --git a/3-more/2-animation/2-bezier/bezier4-e.png b/3-more/3-animation/1-bezier/bezier4-e.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/2-bezier/bezier4-e.png
rename to 3-more/3-animation/1-bezier/bezier4-e.png
diff --git a/3-more/2-animation/2-bezier/bezier4.png b/3-more/3-animation/1-bezier/bezier4.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/2-bezier/bezier4.png
rename to 3-more/3-animation/1-bezier/bezier4.png
diff --git a/3-more/2-animation/2-bezier/car.jpg b/3-more/3-animation/1-bezier/car.jpg
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/2-bezier/car.jpg
rename to 3-more/3-animation/1-bezier/car.jpg
diff --git a/3-more/3-animation/1-bezier/demo.svg b/3-more/3-animation/1-bezier/demo.svg
new file mode 100644
index 00000000..7dd51ad6
--- /dev/null
+++ b/3-more/3-animation/1-bezier/demo.svg
@@ -0,0 +1 @@
+
1t:1
\ No newline at end of file
diff --git a/3-more/2-animation/2-bezier/letter_m.png b/3-more/3-animation/1-bezier/letter_m.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/2-bezier/letter_m.png
rename to 3-more/3-animation/1-bezier/letter_m.png
diff --git a/3-more/3-animation/1-bezier/play.png b/3-more/3-animation/1-bezier/play.png
new file mode 100644
index 00000000..03131b1d
Binary files /dev/null and b/3-more/3-animation/1-bezier/play.png differ
diff --git a/3-more/2-animation/2-bezier/vase.png b/3-more/3-animation/1-bezier/vase.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/2-bezier/vase.png
rename to 3-more/3-animation/1-bezier/vase.png
diff --git a/3-more/2-animation/3-css-animation/1-animate-logo-css/solution.md b/3-more/3-animation/2-css-transitions/1-animate-logo-css/solution.md
similarity index 100%
rename from 3-more/2-animation/3-css-animation/1-animate-logo-css/solution.md
rename to 3-more/3-animation/2-css-transitions/1-animate-logo-css/solution.md
diff --git a/3-more/2-animation/3-css-animation/1-animate-logo-css/solution.view/index.html b/3-more/3-animation/2-css-transitions/1-animate-logo-css/solution.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/3-css-animation/1-animate-logo-css/solution.view/index.html
rename to 3-more/3-animation/2-css-transitions/1-animate-logo-css/solution.view/index.html
diff --git a/3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/animate.js b/3-more/3-animation/2-css-transitions/1-animate-logo-css/source.view/animate.js
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/animate.js
rename to 3-more/3-animation/2-css-transitions/1-animate-logo-css/source.view/animate.js
diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/source.view/index.html b/3-more/3-animation/2-css-transitions/1-animate-logo-css/source.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/2-animate-logo/source.view/index.html
rename to 3-more/3-animation/2-css-transitions/1-animate-logo-css/source.view/index.html
diff --git a/3-more/2-animation/3-css-animation/1-animate-logo-css/task.md b/3-more/3-animation/2-css-transitions/1-animate-logo-css/task.md
similarity index 100%
rename from 3-more/2-animation/3-css-animation/1-animate-logo-css/task.md
rename to 3-more/3-animation/2-css-transitions/1-animate-logo-css/task.md
diff --git a/3-more/2-animation/3-css-animation/article.md b/3-more/3-animation/2-css-transitions/article.md
similarity index 78%
rename from 3-more/2-animation/3-css-animation/article.md
rename to 3-more/3-animation/2-css-transitions/article.md
index 13dde71f..330b14ec 100644
--- a/3-more/2-animation/3-css-animation/article.md
+++ b/3-more/3-animation/2-css-transitions/article.md
@@ -1,11 +1,10 @@
-# CSS-анимация
+# CSS-transitions
Все современные браузеры, кроме IE9- поддерживают CSS transitions, которые позволяют реализовать анимацию средствами CSS, без привлечения JavaScript.
-Большинство примеров из этой статьи не будут работать в IE9-.
[cut]
-## Анимация свойства [#css-animation]
+## Анимация свойства [#css-transition]
Идея проста. Вы указываете, что некоторое свойство будет анимироваться при помощи специальных CSS-правил. Далее, при изменении этого свойства, браузер сам обработает анимацию.
@@ -18,7 +17,7 @@
}
```
-Любое изменение фонового цвета будет анимироваться в течение 2-х секунд.
+Теперь любое изменение фонового цвета будет анимироваться в течение 2-х секунд.
У свойства `"transition"` есть и короткая запись:
@@ -28,46 +27,7 @@
}
```
-Так как [стандарт CSS Transitions](http://www.w3.org/TR/css3-transitions/) находится в стадии разработки, то `transition` нужно снабжать браузерными префиксами.
-
-### Пример
-Этот пример работает во всех современных браузерах, не работает в IE9-.
-
-```html
-
-
- Кликни меня
-
-```
-
-
-
- Кликни меня
-
-
-CSS-анимации особенно рекомендуются на мобильных устройствах. Они отрисовываются плавнее, чем JavaScript, и меньше нагружают процессор, так как используют графическую акселерацию.
-
-
-## Полный синтаксис CSS
+## Полный синтаксис
Свойства для CSS-анимаций:
@@ -76,41 +36,27 @@ CSS-анимации особенно рекомендуются на мобил
`transition-duration`
Продолжительность анимации. Если указано одно значение -- оно применится ко всем свойствам, можно указать несколько значений для разных `transition-property`.
`transition-timing-function`
-
[Кривая Безье](/bezier) по 4-м точкам, используемая в качестве временной функциии.
+
Кривая Безье по 4-м точкам, используемая в качестве временной функциии. Их мы изучим [чуть позже](/bezier)
`transition-delay`
Указывает задержку от изменения свойства до начала CSS-анимации.
Свойство **`transition`** может содержать их все, в порядке: `property duration timing-function delay, ...`.
-### Пример
+## Пример
Анимируем одновременно цвет и размер шрифта:
```html
+
```
-
-
-
## Временнáя функция
В качестве временной функции можно выбрать любую [кривую Безье](/bezier), удовлетворяющую условиям:
diff --git a/3-more/2-animation/3-css-animation/boat.view/index.html b/3-more/3-animation/2-css-transitions/boat.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/3-css-animation/boat.view/index.html
rename to 3-more/3-animation/2-css-transitions/boat.view/index.html
diff --git a/3-more/2-animation/3-css-animation/ease-in-out.png b/3-more/3-animation/2-css-transitions/ease-in-out.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/3-css-animation/ease-in-out.png
rename to 3-more/3-animation/2-css-transitions/ease-in-out.png
diff --git a/3-more/2-animation/3-css-animation/ease-in.png b/3-more/3-animation/2-css-transitions/ease-in.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/3-css-animation/ease-in.png
rename to 3-more/3-animation/2-css-transitions/ease-in.png
diff --git a/3-more/2-animation/3-css-animation/ease-out.png b/3-more/3-animation/2-css-transitions/ease-out.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/3-css-animation/ease-out.png
rename to 3-more/3-animation/2-css-transitions/ease-out.png
diff --git a/3-more/2-animation/3-css-animation/ease.png b/3-more/3-animation/2-css-transitions/ease.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/3-css-animation/ease.png
rename to 3-more/3-animation/2-css-transitions/ease.png
diff --git a/3-more/2-animation/3-css-animation/train-curve.png b/3-more/3-animation/2-css-transitions/train-curve.png
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/3-css-animation/train-curve.png
rename to 3-more/3-animation/2-css-transitions/train-curve.png
diff --git a/3-more/2-animation/1-js-animation/1-carousel-animated/solution.md b/3-more/3-animation/3-js-animation/1-carousel-animated/solution.md
similarity index 100%
rename from 3-more/2-animation/1-js-animation/1-carousel-animated/solution.md
rename to 3-more/3-animation/3-js-animation/1-carousel-animated/solution.md
diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/solution.view/animate.js b/3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/animate.js
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/2-animate-logo/solution.view/animate.js
rename to 3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/animate.js
diff --git a/3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/index.html b/3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/index.html
rename to 3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/index.html
diff --git a/3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/style.css b/3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/style.css
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/style.css
rename to 3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/style.css
diff --git a/3-more/2-animation/1-js-animation/1-carousel-animated/task.md b/3-more/3-animation/3-js-animation/1-carousel-animated/task.md
similarity index 100%
rename from 3-more/2-animation/1-js-animation/1-carousel-animated/task.md
rename to 3-more/3-animation/3-js-animation/1-carousel-animated/task.md
diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/solution.md b/3-more/3-animation/3-js-animation/2-animate-logo/solution.md
similarity index 100%
rename from 3-more/2-animation/1-js-animation/2-animate-logo/solution.md
rename to 3-more/3-animation/3-js-animation/2-animate-logo/solution.md
diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/source.view/animate.js b/3-more/3-animation/3-js-animation/2-animate-logo/solution.view/animate.js
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/2-animate-logo/source.view/animate.js
rename to 3-more/3-animation/3-js-animation/2-animate-logo/solution.view/animate.js
diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/solution.view/index.html b/3-more/3-animation/3-js-animation/2-animate-logo/solution.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/2-animate-logo/solution.view/index.html
rename to 3-more/3-animation/3-js-animation/2-animate-logo/solution.view/index.html
diff --git a/3-more/2-animation/3-css-animation/1-animate-logo-css/source.view/animate.js b/3-more/3-animation/3-js-animation/2-animate-logo/source.view/animate.js
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/3-css-animation/1-animate-logo-css/source.view/animate.js
rename to 3-more/3-animation/3-js-animation/2-animate-logo/source.view/animate.js
diff --git a/3-more/2-animation/3-css-animation/1-animate-logo-css/source.view/index.html b/3-more/3-animation/3-js-animation/2-animate-logo/source.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/3-css-animation/1-animate-logo-css/source.view/index.html
rename to 3-more/3-animation/3-js-animation/2-animate-logo/source.view/index.html
diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/task.md b/3-more/3-animation/3-js-animation/2-animate-logo/task.md
similarity index 100%
rename from 3-more/2-animation/1-js-animation/2-animate-logo/task.md
rename to 3-more/3-animation/3-js-animation/2-animate-logo/task.md
diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/solution.md b/3-more/3-animation/3-js-animation/3-animate-ball/solution.md
similarity index 100%
rename from 3-more/2-animation/1-js-animation/3-animate-ball/solution.md
rename to 3-more/3-animation/3-js-animation/3-animate-ball/solution.md
diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/solution.view/animate.js b/3-more/3-animation/3-js-animation/3-animate-ball/solution.view/animate.js
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/3-animate-ball/solution.view/animate.js
rename to 3-more/3-animation/3-js-animation/3-animate-ball/solution.view/animate.js
diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/solution.view/index.html b/3-more/3-animation/3-js-animation/3-animate-ball/solution.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/3-animate-ball/solution.view/index.html
rename to 3-more/3-animation/3-js-animation/3-animate-ball/solution.view/index.html
diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/source.view/animate.js b/3-more/3-animation/3-js-animation/3-animate-ball/source.view/animate.js
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/3-animate-ball/source.view/animate.js
rename to 3-more/3-animation/3-js-animation/3-animate-ball/source.view/animate.js
diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/source.view/index.html b/3-more/3-animation/3-js-animation/3-animate-ball/source.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/3-animate-ball/source.view/index.html
rename to 3-more/3-animation/3-js-animation/3-animate-ball/source.view/index.html
diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/task.md b/3-more/3-animation/3-js-animation/3-animate-ball/task.md
similarity index 100%
rename from 3-more/2-animation/1-js-animation/3-animate-ball/task.md
rename to 3-more/3-animation/3-js-animation/3-animate-ball/task.md
diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.md b/3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.md
similarity index 100%
rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.md
rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.md
diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.view/animate.js b/3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.view/animate.js
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.view/animate.js
rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.view/animate.js
diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.view/index.html b/3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.view/index.html
rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.view/index.html
diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/source.view/animate.js b/3-more/3-animation/3-js-animation/4-animate-ball-hops/source.view/animate.js
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/source.view/animate.js
rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/source.view/animate.js
diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/source.view/index.html b/3-more/3-animation/3-js-animation/4-animate-ball-hops/source.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/source.view/index.html
rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/source.view/index.html
diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/task.md b/3-more/3-animation/3-js-animation/4-animate-ball-hops/task.md
similarity index 100%
rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/task.md
rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/task.md
diff --git a/3-more/2-animation/1-js-animation/article.md b/3-more/3-animation/3-js-animation/article.md
similarity index 100%
rename from 3-more/2-animation/1-js-animation/article.md
rename to 3-more/3-animation/3-js-animation/article.md
diff --git a/3-more/2-animation/1-js-animation/back.svg b/3-more/3-animation/3-js-animation/back.svg
similarity index 100%
rename from 3-more/2-animation/1-js-animation/back.svg
rename to 3-more/3-animation/3-js-animation/back.svg
diff --git a/3-more/2-animation/1-js-animation/bounce-inout.svg b/3-more/3-animation/3-js-animation/bounce-inout.svg
similarity index 100%
rename from 3-more/2-animation/1-js-animation/bounce-inout.svg
rename to 3-more/3-animation/3-js-animation/bounce-inout.svg
diff --git a/3-more/2-animation/1-js-animation/circ-ease.svg b/3-more/3-animation/3-js-animation/circ-ease.svg
similarity index 100%
rename from 3-more/2-animation/1-js-animation/circ-ease.svg
rename to 3-more/3-animation/3-js-animation/circ-ease.svg
diff --git a/3-more/2-animation/1-js-animation/circ.svg b/3-more/3-animation/3-js-animation/circ.svg
similarity index 100%
rename from 3-more/2-animation/1-js-animation/circ.svg
rename to 3-more/3-animation/3-js-animation/circ.svg
diff --git a/3-more/2-animation/1-js-animation/elastic.svg b/3-more/3-animation/3-js-animation/elastic.svg
similarity index 100%
rename from 3-more/2-animation/1-js-animation/elastic.svg
rename to 3-more/3-animation/3-js-animation/elastic.svg
diff --git a/3-more/2-animation/1-js-animation/linear.svg b/3-more/3-animation/3-js-animation/linear.svg
similarity index 100%
rename from 3-more/2-animation/1-js-animation/linear.svg
rename to 3-more/3-animation/3-js-animation/linear.svg
diff --git a/3-more/2-animation/1-js-animation/move.view/index.html b/3-more/3-animation/3-js-animation/move.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/move.view/index.html
rename to 3-more/3-animation/3-js-animation/move.view/index.html
diff --git a/3-more/2-animation/1-js-animation/move100.view/index.html b/3-more/3-animation/3-js-animation/move100.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/move100.view/index.html
rename to 3-more/3-animation/3-js-animation/move100.view/index.html
diff --git a/3-more/2-animation/1-js-animation/quad.svg b/3-more/3-animation/3-js-animation/quad.svg
similarity index 100%
rename from 3-more/2-animation/1-js-animation/quad.svg
rename to 3-more/3-animation/3-js-animation/quad.svg
diff --git a/3-more/2-animation/1-js-animation/quint.svg b/3-more/3-animation/3-js-animation/quint.svg
similarity index 100%
rename from 3-more/2-animation/1-js-animation/quint.svg
rename to 3-more/3-animation/3-js-animation/quint.svg
diff --git a/3-more/2-animation/1-js-animation/width.view/index.html b/3-more/3-animation/3-js-animation/width.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/2-animation/1-js-animation/width.view/index.html
rename to 3-more/3-animation/3-js-animation/width.view/index.html
diff --git a/3-more/3-animation/index.md b/3-more/3-animation/index.md
new file mode 100644
index 00000000..51699284
--- /dev/null
+++ b/3-more/3-animation/index.md
@@ -0,0 +1,3 @@
+# Анимация [todo]
+
+CSS анимации. Контроль над ними из JavaScript. Анимации на чистом JavaScript.
\ No newline at end of file
diff --git a/3-more/4-optimize/1-memory-leaks/article.md b/3-more/4-optimize/1-memory-leaks/article.md
index 7e511a09..0cc9d101 100644
--- a/3-more/4-optimize/1-memory-leaks/article.md
+++ b/3-more/4-optimize/1-memory-leaks/article.md
@@ -13,53 +13,15 @@
## Коллекция утечек в IE
-### Утечка DOM ↔ JS в IE7-
+### Утечка DOM ↔ JS в IE8-
IE до версии 8 не умел очищать циклические ссылки, появляющиеся между DOM-объектами и объектами JavaScript. В результате и DOM и JS оставались в памяти навсегда.
-[warn header="Пропустите эту секцию, если IE8- не нужен"]
-Проблема была особенно серьезна в IE6 до SP3 (или до обновления июня 2007 года), там память не освобождалась даже при переходе на другую страницу.
+В браузере IE8 была проведена серьёзная работа над ошибками, но утечка в IE8- появляется, если круговая ссылка возникает "через объект".
-Сейчас она существует в IE6, 7, а также, в облегчённом варианте, в IE8 (см. далее). Если вы не поддерживаете IE8-, то можете пропустить эту секцию.
-[/warn]
+Чтобы было понятнее, о чём речь, посмотрите на следующий код. Он вызывает утечку памяти в IE8-:
-Функция `setHandler` в примере ниже ведёт к утечке памяти в IE6,7:
-
-```js
-function setHandler() {
- var elem = document.getElementById('id');
- elem.onclick = function() {
- /* может быть пустая функция, не важно */
- };
-}
```
-
-Элемент `elem` здесь ссылается на JavaScript-функцию через ссылку `onclick` напрямую, через свойство, а функция ссылается на `elem` через замыкание.
-
-
-
-Здесь вместо DOM-элемента в IE может быть `XMLHttpRequest`, `ActiveX`, любой другой COM-объект. Круговая ссылка гарантирует утечку.
-
-
-**Обойти утечки памяти в IE можно, разорвав циклические ссылки.**
-
-Например, можно удалить ссылку на `elem` из замыкания, присвоив `elem = null`. Таким образом обработчик больше не ссылается на DOM-элемент. Циклическая ссылка разорвана:
-
-
-
-
-Больше информации об этой утечке вы можете почерпнуть из статей: Understanding and Solving Internet Explorer Leak Patterns и Circular Memory Leak Mitigation.
-
-
-### Утечка DOM ↔ JS, вариант для IE8-
-
-В браузере IE8 была проведена серьёзная работа над ошибками, и пример, описанный выше, больше не приводит к утечке.
-
-**Но ситуация исправлена не до конца. Утечка в IE8- появляется, если круговая ссылка возникает "через объект".**
-
-Чтобы было понятнее, о чём речь, посмотрите на следующий код. Он вызывает утечку памяти:
-
-```js
function leak() {
// Создаём новый DIV, добавляем к BODY
var elem = document.createElement('div');
@@ -80,11 +42,12 @@ function leak() {
}
```
-Открыть в новом окне (в IE)
+Полный пример (только для IE8-, а также IE9 в режиме совместимости с IE8):
-Этот пример, течёт в IE6,7,8, а также в IE9 в режиме совместимости с IE8. Проблема -- в круговой ссылке `elem.__expando__elem = elem`.
+[codetabs src="leak-ie8"]
-**Утечка может возникать и неявным образом, через замыкание:**
+
+Круговая ссылка и, как следствие, утечка может возникать и неявным образом, через замыкание:
```js
function leak() {
@@ -103,32 +66,17 @@ function leak() {
}
```
-Открыть в новом окне (в IE)
+Полный пример (IE8-, IE9 в режиме совместимости с IE8):
-**Без метода `method` здесь утечки не возникнет.**
+[codetabs src="leak-ie8-2"]
+
+Без привязки метода `method` к элементу здесь утечки не возникнет.
Бывает ли такая ситуация в реальной жизни? Или это -- целиком синтетический пример, для заумных программистов?
-Да, конечно бывает. Например, при разработке графических компонент.
-
-Во-первых, сам объект компонента хранит ссылку на его DOM-элемент, чтобы работать с ним. Например:
-
-```js
-function Menu(elem) {
- elem.onclick = function() {
- // ссылка на elem осталась в замыкании
- };
-}
-
-var menu = new Menu(elem);
-```
-
-То есть, компонент всегда знает свой элемент.
-
-Но бывают ситуации, когда нужно пойти в обратном направлении, а именно -- по элементу определить, какой на нём компонент. Например, при делегировании, чтобы передать обработку события на элементе соответствующему компоненту. Или при Drag'n'Drop, чтобы получить компонент, соответствующий элементу, на который произведён перенос.
-
-Сама задача не является чем-то из ряда вон выходящим. Вполне естественно, что JS-компонент привязан к элементу, а элемент знает о компоненте на нём. Но в IE8- прямая привязка ведёт к утечке памяти!
+Да, конечно бывает. Например, при разработке графических компонент -- бывает удобно присвоить DOM-элементу ссылку на JavaScript-объект, который представляет собой компонент. Это упрощает делегирование и, в общем-то, логично, что DOM-элемент знает о компоненте на себе. Но в IE8- прямая привязка ведёт к утечке памяти!
+Примерно так:
```js
function Menu(elem) {
elem.onclick = function() {};
@@ -136,12 +84,13 @@ function Menu(elem) {
var menu = new Menu(elem); // Menu содержит ссылку на elem
*!*
-elem.menu = menu; // вот такая привязка или что-то подобное ведёт к утечке
+elem.menu = menu; // такая привязка или что-то подобное ведёт к утечке в IE8
+*/!*
```
-Открыть в новом окне (в IE)
+Полный пример (IE8-, IE9 в режиме совместимости с IE8):
-Такая привязка удобна, т.к. мы по DOM-элементу можем получить JS-компонент, который к нему привязан. Но, как видим, ведёт к утечке в IE8-.
+[codetabs src="leak-ie8-widget"]
### Утечка IE8 при обращении к коллекциям таблицы
@@ -168,7 +117,9 @@ function leak() {
}
```
-Открыть в новом окне (в IE)
+Полный пример (IE8):
+
+[codetabs src="leak-ie8-table"]
Особенности:
@@ -217,10 +168,12 @@ function leak() {
Когда запускается асинхронный запрос `xhr`, браузер создаёт специальную внутреннюю ссылку (internal reference) на этот объект. находится в процессе коммуникации. Именно поэтому объект `xhr` будет жив после окончания работы функции.
-**Когда запрос завершен, браузер удаляет внутреннюю ссылку, `xhr` становится недостижимым и память очищается... Везде, кроме IE8-.**
+Когда запрос завершен, браузер удаляет внутреннюю ссылку, `xhr` становится недостижимым и память очищается... Везде, кроме IE8-.
-Открыть в новом окне (в IE8-) (откройте страницу и пусть поработает минут 20 - съест всю память, включая виртуальную).
+Полный пример (IE8):
+
+[codetabs src="leak-ie8-xhr"]
Чтобы это исправить, нам нужно разорвать круговую ссылку `XMLHttpRequest ↔ JS`. Например, можно удалить `xhr` из замыкания:
@@ -248,9 +201,7 @@ function leak() {
-Теперь циклической ссылки нет -- мы устранили утечку.
-
-Посмотреть исправленный пример для IE в отдельном окне.
+Теперь циклической ссылки нет -- и не будет утечки.
## Объемы утечек памяти
@@ -273,13 +224,11 @@ function f() {
}
```
-**Пока функция `inner` остается в памяти, `LexicalEnvironment` с переменной большого объема внутри висит в памяти.**
+Пока функция `inner` остается в памяти, `LexicalEnvironment` с переменной большого объема внутри висит в памяти.
Висит до тех пор, пока функция `inner` жива.
-**Как правило, JavaScript не знает, какие из переменных функции `inner` будут использованы, поэтому оставляет их все.**
-
-Исключение -- виртуальная машина V8 (Chrome, Opera, Node.JS), она обычно видит, что переменная не используется во внутренних функциях, и очистит память.
+Как правило, JavaScript не знает, какие из переменных функции `inner` будут использованы, поэтому оставляет их все. Исключение -- виртуальная машина V8 (Chrome, Opera, Node.JS), она часто (не всегда) видит, что переменная не используется во внутренних функциях, и очистит память.
В других же интерпретаторах, даже если код спроектирован так, что никакой утечки нет, по вполне разумной причине может создаваться множество функций, а память будет расти потому, что функция тянет за собой своё замыкание.
@@ -303,113 +252,6 @@ function f() {
}
```
-## jQuery: утечки и борьба с утечками
-
-[warn header="Изменения в jQuery 2"]
-В jQuery 2 объект с данными элемента, о котором идёт речь далее, более недоступен извне. Он стал локальной переменной внутри jQuery с именем `data_priv`, явный доступ к внутренним данным более невозможен (или deprecated).
-
-Но в остальном всё работает точно так, как описано, и с теми же последствиями.
-[/warn]
-
-**В jQuery для борьбы с утечками памяти в IE6-7 используется $.data API. Однако, это может стать причиной новых(!) утечек, характерных для jQuery.**
-
-Основной принцип `$.data` — это для любого JavaScript объекта сохранить/получить значение для элемента с помощью jQuery вызова:
-
-```js
-//+ run
-$(document.body).data('prop', { anything: "любой объект" }) // set
-alert( $(document.body).data('prop') ) // get
-```
-
-jQuery `elem.data(prop, val)` делает следующее:
-
-
Элемент получает уникальный идентификатор, если у него такого еще нет:
-
-```js
-elem[ jQuery.expando ] = id = ++jQuery.uuid; // средствами jQuery
-```
-
-`jQuery.expando` -- это случайная строка, сгенерированная jQuery один раз при входе на страницу. Уникальное свойство, чтобы ничего важного не перезаписать.
-
...А сами данные сохраняются в специальном объекте `jQuery.cache`:
-
-```js
-jQuery.cache[id]['prop'] = { anything: "любой объект" };
-```
-
-
-
-
-Когда данные считываются из элемента:
-
-
-
Уникальный идентификатор элемента извлекается из `id = elem[ jQuery.expando]`.
-
Данные считываются из `jQuery.cache[id]`.
-
-
-Смысл этого API в том, что DOM-элемент никогда не ссылается на JavaScript объект напрямую. Задействуется идентификатор, а сами данные хранятся в `jQuery.cache`. Утечек в IE не будет.
-
-К тому же все данные известны библиотеке, так что можно клонировать с ними и т.п.
-
-**Как побочный эффект -- возникает утечка памяти, если элемент удален из DOM без дополнительной очистки.**
-
-### Примеры утечек в jQuery
-
-Следующий код создает jQuery-утечку во всех браузерах:
-
-```js
-$('')
- .html(new Array(1000).join('text')) // div с текстом, возможна AJAX-загрузка
- .click(function() { })
- .appendTo('#data')
-
-document.getElementById('data').innerHTML = ''; // (*)
-```
-
-Показать в отдельном окне
-
-Утечка происходит потому, что обработчик события в jQuery хранится в данных элемента. В строке `(*)` элемент удален очисткой родительского `innerHTML`, но в `jQuery.cache` данные остались.
-
-Более того, система обработки событий в jQuery устроена так, что вместе с обработчиком в данных хранится и ссылка на элемент, так что в итоге оба -- и обработчик и элемент -- остаются в памяти вместе со всем замыканием!
-
-**Ещё более простой пример утечки:**
-
-Этот код создает утечку:
-
-```js
-function go() {
- $('')
- .html(new Array(1000).join('text'))
- .click(function() { })
-}
-```
-
-Показать в отдельном окне
-
-Причина здесь в том, что элемент `
` создан, но нигде не размещен :). После выполнения функции ссылка на него теряется. Но обработчик события `click` уже сохранил данные в `jQuery.cache`, которые застревают там навсегда.
-
-### Используем jQuery без утечек
-
-Чтобы избежать утечек, описанных выше, для удаления элементов используйте функции jQuery API, а не чистый JavaScript.
-
-Методы remove(), empty() и html() проверяют дочерние элементы на наличие данных и очищают их. Это несколько замедляет процедуру удаления, но зато освобождается память.
-
-
-**К счастью обнаружить такие утечки легко. Проверьте размер `$.cache.`** Если он большой и растет, то изучите кэш, посмотрите, какие записи остаются и почему.
-
-### Улучшение производительности jQuery
-
-У способа борьбы с утечками IE, применённого в jQuery, есть побочный эффект.
-
-**Функции, удаляющие элементы, бегают по всему дереву DOM и очищают подэлементы.**
-
-Представьте себе, что вы получили с сервера большую таблицу (в виде текста), вставили её в документ и хотите обновить. Вызов `$('table').remove()` будет бегать по всем ячейкам и искать в них данные. Но мы-то знаем, что обработчики назначены через делегирование, и тратить на это время ни к чему!
-
-Чтобы "грязно" удалить элемент, без чистки, можно воспользоваться методом detach(). Его официальное назначение -- в том, чтобы убрать элемент из DOM, но сохранить возможность для вставки (и, соответственно, оставить на нём все данные). А неофициальное -- быстро убрать элемент из DOM. Если на нём нет данных и обработчиков, то всё хорошо.
-
-В принципе, если хочется всё сделать чисто, но быстро -- никто не мешает сделать `elem.detach()` и поместить вызов `elem.remove()` в `setTimeout`. В результате очистка будет происходить ассинхронно и незаметно.
-
-Итак, будем надеяться, что эта тема для вас теперь прозрачна и ясна и в следующих разделах мы не будем больше говорить об утечках в jQuery.
-
## Поиск и устранение утечек памяти
### Проверка на утечки
@@ -472,9 +314,4 @@ firefox --profilemanager
Утечки памяти штука довольно сложная. В борьбе с ними вам определенно понадобится одна вещь: *Удача!*
-
-
-
-
Перевести с английского варианта учебника помог Марат Шагиев
Нажимайте на кнопку и наблюдайте, как увеличивается количество занимаемой браузером памяти.
+
+
+
+
\ No newline at end of file
diff --git a/3-more/4-optimize/1-memory-leaks/leak-ie8-table.view/index.html b/3-more/4-optimize/1-memory-leaks/leak-ie8-table.view/index.html
new file mode 100644
index 00000000..b31ed103
--- /dev/null
+++ b/3-more/4-optimize/1-memory-leaks/leak-ie8-table.view/index.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
Нажимайте на кнопку и наблюдайте, как увеличивается количество занимаемой браузером памяти.
+
+
+
+
+
\ No newline at end of file
diff --git a/3-more/4-optimize/1-memory-leaks/leak-ie8-widget.view/index.html b/3-more/4-optimize/1-memory-leaks/leak-ie8-widget.view/index.html
new file mode 100644
index 00000000..6a071791
--- /dev/null
+++ b/3-more/4-optimize/1-memory-leaks/leak-ie8-widget.view/index.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
Нажимайте на кнопку и наблюдайте, как увеличивается количество занимаемой браузером памяти.
+
+
+
+
+
\ No newline at end of file
diff --git a/3-more/4-optimize/1-memory-leaks/leak-ie8-xhr.view/index.html b/3-more/4-optimize/1-memory-leaks/leak-ie8-xhr.view/index.html
new file mode 100644
index 00000000..71dae9f6
--- /dev/null
+++ b/3-more/4-optimize/1-memory-leaks/leak-ie8-xhr.view/index.html
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
Страница создаёт объект XMLHttpRequest каждые 50мс.
+
+
Смотрите на память, она течёт в IE<9.
+
+
+
+
Количество запросов: 0
+
+
+
\ No newline at end of file
diff --git a/3-more/4-optimize/1-memory-leaks/leak-ie8.view/index.html b/3-more/4-optimize/1-memory-leaks/leak-ie8.view/index.html
new file mode 100644
index 00000000..f0b88ce4
--- /dev/null
+++ b/3-more/4-optimize/1-memory-leaks/leak-ie8.view/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
Нажимайте на кнопку и наблюдайте, как увеличивается количество занимаемой браузером памяти.
+
+
+
+
+
\ No newline at end of file
diff --git a/3-more/4-optimize/2-memory-leaks-jquery/article.md b/3-more/4-optimize/2-memory-leaks-jquery/article.md
new file mode 100644
index 00000000..feb0bcb6
--- /dev/null
+++ b/3-more/4-optimize/2-memory-leaks-jquery/article.md
@@ -0,0 +1,125 @@
+
+# Утечки памяти при использовании jQuery
+
+В jQuery для хранения обработчиков событий и других вспомогательных данных, связанных с DOM-элементами, используется внутренний объект, который в jQuery 1 доступен через $.data.
+
+В jQuery 2 доступ к нему закрыт через замыкание, он стал локальной переменной внутри jQuery с именем `data_priv`, но в остальном всё работает точно так, как описано, и с теми же последствиями.
+
+## $.data
+
+Встроенная функция `$.data` позволяет хранить привязывать произвольные значения к DOM-узлам.
+
+Например:
+
+```js
+// присвоить
+$(document).data('prop', { anything: "любой объект" })
+
+// прочитать
+alert( $(document).data('prop').anything ) // любой объект
+```
+
+Реализована она хитрым образом. Данные не хранятся в самом элементе, а во внутреннем объекте jQuery.
+
+jQuery-вызов `elem.data(prop, val)` делает следующее:
+
+
+
Элемент получает уникальный идентификатор, если у него такого еще нет:
+
+```js
+elem[ jQuery.expando ] = id = ++jQuery.uuid; // средствами jQuery
+```
+
+`jQuery.expando` -- это случайная строка, сгенерированная jQuery один раз при входе на страницу. Уникальное свойство, чтобы ничего важного не перезаписать.
+
...А сами данные сохраняются в специальном объекте `jQuery.cache`:
+
+```js
+jQuery.cache[id]['prop'] = { anything: "любой объект" };
+```
+
+
+
+
+Когда данные считываются из элемента:
+
+
+
Уникальный идентификатор элемента извлекается из `id = elem[ jQuery.expando]`.
+
Данные считываются из `jQuery.cache[id]`.
+
+
+Смысл этого API в том, что DOM-элемент никогда не ссылается на JavaScript объект напрямую. Задействуется идентификатор, а сами данные хранятся в `jQuery.cache`. Утечек в IE не будет.
+
+К тому же все данные известны библиотеке, так что можно клонировать с ними и т.п.
+
+Как побочный эффект -- возникает утечка памяти, если элемент удален из DOM без дополнительной очистки.
+
+## Примеры утечек в jQuery
+
+Следующий код создает jQuery-утечку во всех браузерах:
+
+```js
+$('')
+ .html(new Array(1000).join('text')) // div с текстом, возможна AJAX-загрузка
+ .click(function() { })
+ .appendTo('#data')
+
+document.getElementById('data').innerHTML = ''; // (*)
+```
+
+Полный пример:
+
+[codetabs src="jquery-leak"]
+
+Утечка происходит потому, что обработчик события в jQuery хранится в данных элемента. В строке `(*)` элемент удален очисткой родительского `innerHTML`, но в `jQuery.cache` данные остались.
+
+Более того, система обработки событий в jQuery устроена так, что вместе с обработчиком в данных хранится и ссылка на элемент, так что в итоге оба -- и обработчик и элемент -- остаются в памяти вместе со всем замыканием!
+
+Ещё более простой пример утечки:
+
+Этот код также создает утечку:
+
+```js
+function go() {
+ $('')
+ .click(function() { })
+}
+```
+
+...То есть, мы создаём элемент, вешаем на него обработчик... И всё.
+
+Такой код ведёт к утечке памяти как раз потому, что элемент `
` создан, но нигде не размещен :). После выполнения функции ссылка на него теряется. Но обработчик события `click` уже сохранил данные в `jQuery.cache`, которые застревают там навсегда.
+
+## Используем jQuery без утечек
+
+Чтобы избежать утечек, описанных выше, для удаления элементов используйте функции jQuery API, а не чистый JavaScript.
+
+Методы remove(), empty() и html() проверяют дочерние элементы на наличие данных и очищают их. Это несколько замедляет процедуру удаления, но зато освобождается память.
+
+К счастью обнаружить такие утечки легко. Проверьте размер `$.cache`. Если он большой и растет, то изучите кэш, посмотрите, какие записи остаются и почему.
+
+## Улучшение производительности jQuery
+
+У способа организации внутренних данных, применённого в jQuery, есть важный побочный эффект.
+
+Функции, удаляющие элементы, также должны удалить и связанные с ними внутренние данные. Для этого нужно для каждого удаляемого элемента проверить -- а нет ли чего во внутреннем хранилище? И, если есть -- удалить.
+
+Представим, что у нас есть большая таблица `
`, и мы хотим обновить её содержимое на новое. Вызов `$('table').html(новые данные)` перед вставкой новых данных аккуратно удалит старые: пробежит по всем ячейкам и проверит внутреннее хранилище.
+
+Если это большая таблица, то обработчики, скорее всего, стоят не на ячейках, а на самом элементе `
`, то есть используется делегирование. А, значит, тратить время на проверку всех подэлементов ни к чему.
+
+Но jQuery-то об этом не знает!
+
+Чтобы "грязно" удалить элемент, без чистки, мы можем сделать это через "обычные" DOM-вызовы или воспользоваться методом detach(). Его официальное назначение -- в том, чтобы убрать элемент из DOM, но сохранить возможность для вставки (и, соответственно, оставить на нём все данные). А неофициальное -- быстро убрать элемент из DOM, без чистки.
+
+Возможен и промежуточный вариант: никто не мешает сделать `elem.detach()` и поместить вызов `elem.remove()` в `setTimeout`. В результате очистка будет происходить асинхронно и незаметно.
+
+## Итого
+
+
+
Утечки памяти при использовании jQuery возможны, если через DOM-методы удалять элементы, к которым привязаны данные или обработчики.
+
Чтобы утечки не было, достаточно убедиться, что элемент удаляется при помощи методов jQuery.
+
Побочный эффект -- при удалении элементов jQuery должна проверить наличие данных для них. Это сильно замедляет процесс удаления большого поддерева DOM.
+
Если мы значем, что обработчиков и данных нет -- гораздо быстрее удалять элементы при помощи вызова `detach` или обычного DOM.
+
+
+
diff --git a/3-more/4-optimize/2-memory-leaks-jquery/jquery-leak.view/index.html b/3-more/4-optimize/2-memory-leaks-jquery/jquery-leak.view/index.html
new file mode 100644
index 00000000..13a18544
--- /dev/null
+++ b/3-more/4-optimize/2-memory-leaks-jquery/jquery-leak.view/index.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+Утечка идёт...
+
+
+
+
+
diff --git a/3-more/5-compress/1-minification/article.md b/3-more/4-optimize/3-minification/article.md
similarity index 100%
rename from 3-more/5-compress/1-minification/article.md
rename to 3-more/4-optimize/3-minification/article.md
diff --git a/3-more/5-compress/1-minification/my.svg b/3-more/4-optimize/3-minification/my.svg
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/5-compress/1-minification/my.svg
rename to 3-more/4-optimize/3-minification/my.svg
diff --git a/3-more/5-compress/2-better-minification/article.md b/3-more/4-optimize/4-better-minification/article.md
similarity index 76%
rename from 3-more/5-compress/2-better-minification/article.md
rename to 3-more/4-optimize/4-better-minification/article.md
index 68b4debb..e5560ba9 100644
--- a/3-more/5-compress/2-better-minification/article.md
+++ b/3-more/4-optimize/4-better-minification/article.md
@@ -132,20 +132,27 @@ window.isIE = window.isIE || getBrowserVersion();
## Убираем вызовы console.*
-Минификатор имеет в своём распоряжении дерево кода и может удалить ненужные вызовы. Хотя по умолчанию в UglifyJS и GCC такого флага нет, код минификатора можно легко расширить, добавив эту возможность.
+Минификатор имеет в своём распоряжении дерево кода и может удалить ненужные вызовы.
+Для UglifyJS это делают опции компилятора:
-
Для UglifyJS функция обхода дерева:
+
`drop_debugger` -- убирает вызовы `debugger`.
+
`drop_console` -- убирает вызовы `console.*`.
+
+
+Можно написать и дополнительную функцию преобразования, которая убирает другие вызовы, например для `log.*`:
```js
-//+ hide="Раскрыть функцию"
+var uglify = require('uglify-js');
+var pro = uglify.uglify;
+
function ast_squeeze_console(ast) {
var w = pro.ast_walker(),
walk = w.walk,
scope;
return w.with_walkers({
"stat": function(stmt) {
- if(stmt[0] === "call" && stmt[1][0] == "dot" && stmt[1][1] instanceof Array && stmt[1][1][0] == 'name' && stmt[1][1][1] == "console") {
+ if(stmt[0] === "call" && stmt[1][0] == "dot" && stmt[1][1] instanceof Array && stmt[1][1][0] == 'name' && stmt[1][1][1] == "log") {
return ["block"];
}
return ["stat", walk(stmt)];
@@ -161,22 +168,5 @@ function ast_squeeze_console(ast) {
};
```
-Полный код, использующий эту функцию и модуль uglify-js для сжатия с убиранием вызова: [myuglify.js](/files/tutorial/compress/myuglify.js).
-
-Вы можете добавить свои любимые опции и использовать его вместо поставляемого "из коробки".
-
-
В GCC соответствующие опции называются `stripNameSuffixes` и `stripTypePrefixes`, но они скрыты при запуске минификатора из командной строки или через веб-сервис.
-
-Чтобы их использовать, нужно либо поставить утилиту [plovr](http://plovr.com/), что эквивалентно стрельбе из пушки по воробьям, либо написать свой Java-код для вызова компилятора, который будет ставить опции.
-
-Выглядеть этот код может [примерно так](https://groups.google.com/d/msg/closure-compiler-discuss/qqdnzikzpWA/8cPHKIR1svgJ).
-
-
-
-Аналогичным образом можно убрать и любой другой код, например вызовы вашего собственного логгера.
-
-
-
-
-
+Эту функцию следует вызвать на результате `parse`, и она пройдётся по дереву и удалит все вызовы `log.*`.
diff --git a/3-more/5-compress/3-gcc-advanced-optimization/article.md b/3-more/4-optimize/5-gcc-advanced-optimization/article.md
similarity index 100%
rename from 3-more/5-compress/3-gcc-advanced-optimization/article.md
rename to 3-more/4-optimize/5-gcc-advanced-optimization/article.md
diff --git a/3-more/5-compress/4-gcc-check-types/article.md b/3-more/4-optimize/6-gcc-check-types/article.md
similarity index 100%
rename from 3-more/5-compress/4-gcc-check-types/article.md
rename to 3-more/4-optimize/6-gcc-check-types/article.md
diff --git a/3-more/5-compress/5-gcc-closure-library/article.md b/3-more/4-optimize/7-gcc-closure-library/article.md
similarity index 100%
rename from 3-more/5-compress/5-gcc-closure-library/article.md
rename to 3-more/4-optimize/7-gcc-closure-library/article.md
diff --git a/3-more/4-optimize/index.md b/3-more/4-optimize/index.md
index 77df4229..66af82f4 100644
--- a/3-more/4-optimize/index.md
+++ b/3-more/4-optimize/index.md
@@ -1,2 +1,4 @@
# Оптимизация
+Утечки памяти, увеличение скорости выполнения и загрузки скриптов.
+
diff --git a/3-more/5-compress/index.md b/3-more/5-compress/index.md
deleted file mode 100644
index 9bee2987..00000000
--- a/3-more/5-compress/index.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Сжатие JavaScript
-
diff --git a/3-more/4-optimize/3-reflow/article.md b/archive/3-reflow/article.md
similarity index 100%
rename from 3-more/4-optimize/3-reflow/article.md
rename to archive/3-reflow/article.md
diff --git a/3-more/4-optimize/3-reflow/reflow.view/index.html b/archive/3-reflow/reflow.view/index.html
old mode 100755
new mode 100644
similarity index 100%
rename from 3-more/4-optimize/3-reflow/reflow.view/index.html
rename to archive/3-reflow/reflow.view/index.html
diff --git a/3-more/4-optimize/2-script-place-optimize/article.md b/archive/4-script-place-optimize/article.md
similarity index 100%
rename from 3-more/4-optimize/2-script-place-optimize/article.md
rename to archive/4-script-place-optimize/article.md