diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/task.md b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/task.md
index db49fb3d..3bb9a2d8 100644
--- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/task.md
+++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/task.md
@@ -4,13 +4,11 @@
Нужно написать функцию, которая показывает подсказку при *наведении* на элемент, но не при *быстром проходе* над ним.
-То есть, если посетитель именно навёл курсор мыши на элемент и почти остановился -- подсказку показать, а если быстро провёл над ним, то не надо (зачем излишнее мигание?).
+То есть, если посетитель именно навёл курсор мыши на элемент и почти остановился -- подсказку показать, а если быстро провёл над ним, то не надо, зачем излишнее мигание?
Технически -- можно измерять скорость движения мыши над элементом, если она маленькая, то считаем, что это "наведение на элемент" (показать подсказку), если большая -- "быстрый проход мимо элемента" (не показывать).
-Задача -- сделать универсальный код, который отслеживает "наведение на элемент".
-
-Пусть это будет объект `new HoverIntent(options)`, который при создании принимает `options`:
+Реализуйте это через универсальный объект `new HoverIntent(options)`, с параметрами `options`:
`elem` -- элемент, наведение на который нужно отслеживать.
`over` -- функция-обработчик наведения на элемент.
@@ -19,10 +17,6 @@
Пример использования такого объекта для подсказки:
```js
-function HoverIntent(options) {
- //... ваш код ...
-}
-
// образец подсказки
var tooltip = document.createElement('div');
tooltip.className = "tooltip";
@@ -48,6 +42,6 @@ new HoverIntent({
Если провести мышкой над "часиками" быстро, то ничего не будет, а если медленно или остановиться на них, то появится подсказка.
-Обратите внимание -- подсказка не "мигает"" при проходе мыши внутри "часиков", по подэлементам.
+Обратите внимание -- подсказка не "мигает" при проходе мыши внутри "часиков", по подэлементам.
diff --git a/3-more/7-frames-and-windows/1-window-open/article.md b/3-more/5-frames-and-windows/1-window-open/article.md
similarity index 51%
rename from 3-more/7-frames-and-windows/1-window-open/article.md
rename to 3-more/5-frames-and-windows/1-window-open/article.md
index 12c80b0f..4916fcd3 100644
--- a/3-more/7-frames-and-windows/1-window-open/article.md
+++ b/3-more/5-frames-and-windows/1-window-open/article.md
@@ -13,7 +13,7 @@
window.open("http://ya.ru");
```
-...При запуске откроется новое окно с данным URL.
+...При запуске откроется новое окно с указанным URL.
Большинство браузеров по умолчанию создают новую вкладку вместо отдельного окна, но чуть далее мы увидим, что можно и "заказать" именно окно.
@@ -25,37 +25,12 @@ window.open("http://ya.ru");
Как же браузер понимает -- посетитель вызвал открытие окна или нет?
-**Для этого при работе скрипта он хранит внутренний "флаг", который говорит -- инициировал посетитель выполнение или нет.**
+Для этого при работе скрипта он хранит внутренний "флаг", который говорит -- инициировал посетитель выполнение или нет. Например, при клике на кнопку весь код, который выполнится в результате, включая вложенные вызовы, будет иметь флаг "инициировано посетителем" и попапы при этом разрешены.
-Например, при клике на кнопку весь код, который выполнится в результате, включая вложенные вызовы, будет иметь флаг "инициировано посетителем" и попапы при этом разрешены.
+А если код был на странице и выполнился автоматически при её загрузке -- у него этого флага не будет. Попапы будут заблокированы.
-А если код был на странице и выполнился автоматически при её загрузке -- у него этого флага не будет. Попапы будут заблокированы..
-Здесь есть ещё ряд тонких моментов. Например: обработчик `onclick` вызвал `setTimeout(func, timeout)`. В результате код `func` выполнится уже после того, как событие `onclick` обработано. Следует ли передать ему флаг "инициировано посетителем" или нет?
-
-Возможны разные точки зрения, например, IE блокирует такие окна (видимо, проще было реализовать), а Firefox и Chrome/Safari передают флаг, если таймаут меньше секунды. А если больше -- то не передают ;)
-
-Вот это окно откроется в Firefox и Chrome (но не в IE):
-
-```js
-//+ run
-setTimeout(function() {
- window.open("http://ya.ru");
-}, *!*500*/!*);
-```
-
-...А это -- будет заблокировано:
-
-```js
-//+ run
-setTimeout(function() {
- window.open("http://ya.ru");
-}, *!*2500*/!*);
-```
-
-**Таким образом, современные браузеры расширяют область "действий посетителя" и блокируют попапы не всегда.**
-
-## Синтаксис window.open
+## Полный синтаксис window.open
Полный синтаксис:
@@ -63,17 +38,19 @@ setTimeout(function() {
win = window.open(url, name, params)
```
+Функция возвращает ссылку но объект `window` нового окна, либо `null`, если окно было заблокировано браузером.
+
+Параметры:
+
`url`
URL для загрузки в новое окно.
`name`
-
Имя нового окна. Может быть использовано в параметре `target` в формах. Если позднее вызвать `window.open()` с тем же именем, то некоторые браузеры (Firefox) заменяют существующее окно на новосозданное. А вот IE при этом откроет новое окно.
+
Имя нового окна. Может быть использовано в параметре `target` в формах. Если позднее вызвать `window.open()` с тем же именем, то браузеры (кроме IE) заменяют существующее окно на новое.
`params`
Строка с конфигурацией для нового окна. Состоит из параметров, перечисленных через запятую. Пробелов в ней быть не должно.
-**Можно легко узнать, было ли окно заблокировано. При этом результат `window.open` равен `null`.**
-
Значения параметров `params`.
@@ -108,32 +85,14 @@ win = window.open(url, name, params)
Еще есть небольшое количество не кросс-браузерных свойств, которые обычно не используются. Вы можете узнать о них в документации, например MDN: [window.open](https://developer.mozilla.org/en/DOM/window.open).
-Откроем окно с минимальным набором функций, чтобы посмотреть, какие из них браузер позволяет отключить:
-
-```js
-//+ run
-var params = 'scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no' +
- 'width=0,height=0,left=-1000,top=-1000';
-window.open('/', 'test', params);
-```
-
-Здесь большинство параметров отключено и окно позиционированно за пределами экрана. Запустите, чтобы увидеть, что произойдет на самом деле.
-
-Теперь давайте добавим корректные параметры позиционирования: нормальную ширину, высоту и координаты левого верхнего угла.
-
-Этот пример браузер отобразит "как заказано":
-
-```js
-//+ run
-var params = 'scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no' +
- 'width=100,height=100,left=100,top=100';
-window.open('/', 'test', params);
-```
+[warn]
+Браузер подходит к этим параметрам интеллектуально. Он может проигнорировать их часть или даже все, они скорее являются "пожеланиями", нежели "требованиями".
+[/warn]
Важные моменты:
-
Если при вызове `open` третий параметр отсутствует, то используются параметры по умолчанию. Обычно при этом будет открыто не окно, а вкладка.
+
Если при вызове `open` указан только первый параметр, параметр отсутствует, то используются параметры по умолчанию. Обычно при этом будет открыто не окно, а вкладка, что зачастую более удобно.
Если указана строка с параметрами, но некоторые `yes/no` параметры отсутствуют, то браузер выставляет их в `no`. Поэтому убедитесь, что все нужные вам параметры выставлены в `yes`.
Когда не указан `top/left`, то браузер откроет окно с небольшим смещением относительно левого верхнего угла последнего открытого окна.
Если не указаны `width/height`, новое окно будет такого же размера, как последнее открытое.
@@ -143,12 +102,23 @@ window.open('/', 'test', params);
Вызов `window.open` возвращает ссылку на новое окно. Она может быть использована для манипуляции свойствами окна, изменения URL, доступа к его переменным и т.п.
-В примере ниже содержимое нового окна модифицируется после загрузки.
+В примере ниже мы заполняем новое окно содержимым целиком из JavaScript:
+
+```js
+//+ run
+var newWin = window.open("about:blank", "hello", "width=200,height=200");
+
+newWin.document.write("Привет, мир!");
+```
+
+А здесь модифицируем содержимое после загрузки:
```js
//+ run
var newWin = window.open('/', 'example', 'width=600,height=400');
-newWin.focus();
+
+alert(newWin.location.href); // (*) about:blank, загрузка ещё не началась
+
newWin.onload = function() {
// создать div в документе нового окна
@@ -156,33 +126,101 @@ newWin.onload = function() {
div.innerHTML = 'Добро пожаловать!'
div.style.fontSize = '30px'
-*!*
- var body = newWin.document.body;
-*/!*
- // вставить первым элементом в новое body
- body.insertBefore(div, body.firstChild);
+ // вставить первым элементом в body нового окна
+ body.insertBefore(div, newWin.document.body.firstChild);
}
```
-**Сразу после `window.open` новое окно ещё не загружено.**
+Обратим внимание: сразу после `window.open` новое окно ещё не загружено. Это демонстрирует `alert` в строке `(*)`. Поэтому в примере выше окно модифицируется при `onload`. Можно было и поставить обработчик на `DOMContentLoaded` для `newWin.document`.
+
+**Связь между окнами -- двухсторонняя.**
+
+Родительское окно получает ссылку на новое через `window.open`, а дочернее -- ссылку на родителя `window.opener`.
+
+Оно тоже может его модифицировать.
+
+Если запустить пример ниже, то новое окно заменит содержимое текущего на `'Test'`:
+
+```js
+//+ run
+var newWin = window.open("about:blank", "hello", "width=200,height=200");
+
+newWin.document.write(
+ ""
+);
+```
-Поэтому в примере выше изменения начинаются при `onload`. Можно использовать и событие `DOMContentLoaded`.
[warn header="Same Origin Policy -- защита проверкой протокол-сайт-порт"]
-**Большинство действий, особенно получение содержимого окна и его переменных, возможны лишь в том случае, если URL нового окна происходит из того же источника (англ. - *"Same Origin"*), т.е. совпадают домен, протокол и порт.**
+Большинство действий, особенно получение содержимого окна и его переменных, возможны лишь в том случае, если URL нового окна происходит из того же источника (англ. - *"Same Origin"*), т.е. совпадают домен, протокол и порт.
Иначе говоря, если новое окно содержит документ с того же сайта.
-Исключение: замена адреса. Поменять (но не прочитать) `win.location = ...` можно всегда, даже если окно с другого домена.
-
-Больше информации об этом -- в главе [](/same-origin-policy).
+Больше информации об этом будет позже, в главе [](/same-origin-policy).
[/warn]
-## Связь между новым и родительским окном
-Связь между окнами -- двухсторонняя. Родительское окно получает ссылку из `window.open`, а дочернее -- специальное свойство `window.opener`.
+## События
+
+Наиболее важные события при работе с окном браузера:
+
+
+
`onresize` -- событие изменения размера окна.
+
`onscroll` -- событие при прокрутке окна.
+
`onload` -- полностью загрузилась страница со всеми ресурсами.
+
`onfocus/onblur` -- получение/потеря фокуса.
+
+
+## Методы и свойства
+
+
+
`window.closed`
+
Свойство `window.closed` равно `true`, если окно закрыто. Может быть использовано, чтобы проверить, закрыл ли посетитель попап.
+
`window.close()`
+
Закрывает попап без предупреждений и уведомлений. Вообще, метод `close()` можно вызвать для любого окна, в том числе, текущего. Но если окно открыто не с помощью `window.open()`, то браузер может проигнорировать вызов `close` или запросить подтверждение.
+
+
+
+## Перемещение и изменение размеров окна
+
+Существует несколько методов для перемещения/изменения размеров окна.
+
+
+
`win.moveBy(x,y)`
+
Перемещает окно относительно текущего положения на `x` пикселей вправо и `y` пикселей вниз. Допускаются отрицательные значения.
+
`win.moveTo(x,y)`
+
Передвигает окно в заданную координатами `x` и `y` точку экрана монитора.
+
`win.resizeBy(width,height)`
+
Изменяет размер окна на заданную величину `width/height` (ширина/высота). Допускаются отрицательные значения.
+
`win.resizeTo(width,height)`
+
Изменяет размер окна на заданное значение.
+
+
+[warn]
+Чтобы предотвратить использование этих методов с плохими целями, браузеры часто блокируют их выполнение. Как правило, они работают, если окно `win` открыто вызовом [window.open](https://developer.mozilla.org/en-US/docs/Web/API/window.open) из JavaScript текущей страницы и в нём нет дополнительных вкладок.
+[/warn]
+
+[warn header="Ни свернуть ни развернуть"]
+Заметим, что JavaScript не может ни свернуть ни развернуть ни "максимизировать" (Windows) окно.
+
+Эти функции операционной системы от Frontend-разработчиков скрыты. Вызовы, описанные выше, в случае свёрнутого или максимизированного окна не работают.
+[/warn]
+
+## Прокрутка окна
+
+Прокрутка окна требуется, пожалуй, чаще всего. Мы уже говорили о ней в главе [](/metrics-window):
+
+
+
`win.scrollBy(x,y)`
+
+Прокрутка окна на заданное число пикселей вперед или назад. Допускаются отрицательные значения.
+
`win.scrollTo(x,y)`
+
Прокручивает окно к заданным координатам.
+
`elem.scrollIntoView(top)`
+
Этот метод прокрутки вызывается на элементе. При этом окно прокручивается так, чтобы элемент был полностью видим. Если параметр `top` равен `true` или не задан, то верх элемента совпадает с верхом окна. Если он равен `false`, то окно прокручивается так, чтобы нижний край элемента совпал с нижним краем окна.
+
+
-Оно равно `null`, если открывшего окна нет.
## Итого
@@ -195,11 +233,9 @@ newWin.onload = function() {
Окна могут общаться между собой как угодно, если они из одного источника. Иначе действуют жёсткие ограничения безопасности.
-Всплывающие окна используются нечасто. Ведь загрузить новую информацию можно динамически, с помощью технологии AJAX, а показать -- в элементе `DIV`, расположенным над страницей (`z-index`). Ещё одна альтернатива -- тег `IFRAME`.
+Всплывающие окна используются нечасто. Ведь загрузить новую информацию можно динамически, с помощью технологии AJAX, а показать -- в элементе `
`, расположенным над страницей (`z-index`). Ещё одна альтернатива -- тег `