diff --git a/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/solution.md b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/solution.md new file mode 100644 index 00000000..4b8fe50b --- /dev/null +++ b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/solution.md @@ -0,0 +1,6 @@ + +The algorithm: +1. Make `img` for every source. +2. Add `onload/onerror` for every image. +3. Increase the counter when either `onload` or `onerror` triggers. +4. When the counter value equals to the sources count -- we're done: `callback()`. diff --git a/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/solution.view/index.html b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/solution.view/index.html new file mode 100644 index 00000000..bc7ff3c4 --- /dev/null +++ b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/solution.view/index.html @@ -0,0 +1,54 @@ + + + + + + + + + + + diff --git a/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/source.view/index.html b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/source.view/index.html new file mode 100644 index 00000000..6280adb4 --- /dev/null +++ b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/source.view/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + diff --git a/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/task.md b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/task.md new file mode 100644 index 00000000..bc742ab1 --- /dev/null +++ b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/task.md @@ -0,0 +1,36 @@ +importance: 4 + +--- + +# Load images with a callback + +Normally, images are loaded when they are created. So i when we add `` to the page, the user does not see the picture immediately. The browser needs to load it first. + +To show an image immediately, we can create it "in advance", like this: + +```js +let img = document.createElement('img'); +img.src = 'my.jpg'; +``` + +The browser starts loading the image and remembers it in the cache. Later, when the same image appears in the document (no matter how), it shows up immediately. + +**Create a function `preloadImages(sources, callback)` that loads all images from the array `sources` and, when ready, runs `callback`.** + +For instance, this will show an `alert` after the images are loaded: + +```js +function loaded() { + alert("Images loaded") +} + +preloadImages(["1.jpg", "2.jpg", "3.jpg"], loaded); +``` + +In case of an error, the function should still assume the picture "loaded". + +In other words, the `callback` is executed when all images are either loaded or errored out. + +The function is useful, for instance, when we plan to show a gallery with many scrollable images, and want to be sure that all images are loaded. + +In the source document you can find links to test images, and also the code to check whether they are loaded or not. It should output `300`. diff --git a/2-ui/3-event-details/11-onload-onerror/1-nice-alt/solution.md b/2-ui/3-event-details/11-onload-onerror/1-nice-alt/solution.md deleted file mode 100644 index 7e90a02a..00000000 --- a/2-ui/3-event-details/11-onload-onerror/1-nice-alt/solution.md +++ /dev/null @@ -1,8 +0,0 @@ -# Подсказка - -Текст на странице пусть будет изначально `DIV`, с классом `img-replace` и атрибутом `data-src` для картинки. - -Функция `replaceImg()` должна искать такие `DIV` и загружать изображение с указанным `src`. По `onload` осуществляется замена `DIV` на картинку. - -# Решение - diff --git a/2-ui/3-event-details/11-onload-onerror/1-nice-alt/solution.view/index.html b/2-ui/3-event-details/11-onload-onerror/1-nice-alt/solution.view/index.html deleted file mode 100755 index 4935f238..00000000 --- a/2-ui/3-event-details/11-onload-onerror/1-nice-alt/solution.view/index.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - -
-
- Google -
- -
- Яндекс -
- -
bing
- - - - - - - \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/1-nice-alt/source.view/index.html b/2-ui/3-event-details/11-onload-onerror/1-nice-alt/source.view/index.html deleted file mode 100755 index eba12fd0..00000000 --- a/2-ui/3-event-details/11-onload-onerror/1-nice-alt/source.view/index.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - -
- Google -
- - -
- Яндекс -
- - -
bing
- -
- - - Яндекс - Google - Файла нет (bing) - - - - - \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/1-nice-alt/task.md b/2-ui/3-event-details/11-onload-onerror/1-nice-alt/task.md deleted file mode 100644 index 25fc4f02..00000000 --- a/2-ui/3-event-details/11-onload-onerror/1-nice-alt/task.md +++ /dev/null @@ -1,20 +0,0 @@ -importance: 5 - ---- - -# Красивый "ALT" - -Обычно, до того как изображение загрузится (или при отключенных картинках), посетитель видит пустое место с текстом из "ALT". Но этот атрибут не допускает HTML-форматирования. - -При мобильном доступе скорость небольшая, и хочется, чтобы посетитель сразу видел красивый текст. - -**Реализуйте "красивый" (HTML) аналог `alt` при помощи CSS/JavaScript, который затем будет заменён картинкой сразу же как только она загрузится.** А если загрузка не состоится -- то не заменён. - -Демо: (нажмите "перезагрузить", чтобы увидеть процесс загрузки и замены) - -[iframe src="solution" height="100"] - -Картинки для `bing` специально нет, так что текст остается "как есть". - -Исходный документ содержит разметку текста и ссылки на изображения. - diff --git a/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/solution.md b/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/solution.md deleted file mode 100644 index e7fb799a..00000000 --- a/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/solution.md +++ /dev/null @@ -1,5 +0,0 @@ - -Создайте переменную-счетчик для подсчёта количества загруженных картинок, и увеличивайте при каждом `onload/onerror`. - -Когда счетчик станет равен количеству картинок -- вызывайте `callback`. - diff --git a/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/solution.view/index.html b/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/solution.view/index.html deleted file mode 100755 index 23825080..00000000 --- a/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/solution.view/index.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/source.view/index.html b/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/source.view/index.html deleted file mode 100755 index 1e3afe5a..00000000 --- a/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/source.view/index.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/task.md b/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/task.md deleted file mode 100644 index edf99d23..00000000 --- a/2-ui/3-event-details/11-onload-onerror/2-load-img-callback/task.md +++ /dev/null @@ -1,20 +0,0 @@ -importance: 4 - ---- - -# Загрузить изображения с коллбэком - -Создайте функцию `preloadImages(sources, callback)`, которая предзагружает изображения из массива `sources`, и после загрузки вызывает функцию `callback`. - -Пример использования: - -```js -preloadImages(["1.jpg", "2.jpg", "3.jpg"], callback); -``` - -Если вдруг возникает ошибка при загрузке -- считаем такое изображение загруженным, чтобы не ломать поток выполнения. - -Такая функция может полезна, например, для фоновой загрузки картинок в онлайн-галерею. - -В исходном документе содержатся ссылки на картинки, а также код для проверки, действительно ли изображения загрузились. Он должен выводить "0", затем "300". - diff --git a/2-ui/3-event-details/11-onload-onerror/3-script-callback/solution.md b/2-ui/3-event-details/11-onload-onerror/3-script-callback/solution.md deleted file mode 100644 index 753fe747..00000000 --- a/2-ui/3-event-details/11-onload-onerror/3-script-callback/solution.md +++ /dev/null @@ -1,18 +0,0 @@ -# Подсказка - -Добавляйте `SCRIPT` при помощи методов `DOM`: - -```js -var script = document.createElement('script'); -script.src = src; - -// в документе может не быть HEAD или BODY, -// но хотя бы один (текущий) SCRIPT в документе есть -var s = document.getElementsByTagName('script')[0]; -s.parentNode.insertBefore(script, s); // перед ним и вставим -``` - -На скрипт повесьте обработчики `onload/onreadystatechange`. - -# Решение - diff --git a/2-ui/3-event-details/11-onload-onerror/3-script-callback/solution.view/go.js b/2-ui/3-event-details/11-onload-onerror/3-script-callback/solution.view/go.js deleted file mode 100755 index 1729e58f..00000000 --- a/2-ui/3-event-details/11-onload-onerror/3-script-callback/solution.view/go.js +++ /dev/null @@ -1,3 +0,0 @@ -function go() { - alert("ok"); -} \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/3-script-callback/solution.view/index.html b/2-ui/3-event-details/11-onload-onerror/3-script-callback/solution.view/index.html deleted file mode 100755 index e840c12d..00000000 --- a/2-ui/3-event-details/11-onload-onerror/3-script-callback/solution.view/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/3-script-callback/source.view/go.js b/2-ui/3-event-details/11-onload-onerror/3-script-callback/source.view/go.js deleted file mode 100755 index 1729e58f..00000000 --- a/2-ui/3-event-details/11-onload-onerror/3-script-callback/source.view/go.js +++ /dev/null @@ -1,3 +0,0 @@ -function go() { - alert("ok"); -} \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/3-script-callback/source.view/index.html b/2-ui/3-event-details/11-onload-onerror/3-script-callback/source.view/index.html deleted file mode 100755 index fb498558..00000000 --- a/2-ui/3-event-details/11-onload-onerror/3-script-callback/source.view/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/3-script-callback/task.md b/2-ui/3-event-details/11-onload-onerror/3-script-callback/task.md deleted file mode 100644 index 2c5d5751..00000000 --- a/2-ui/3-event-details/11-onload-onerror/3-script-callback/task.md +++ /dev/null @@ -1,21 +0,0 @@ -importance: 4 - ---- - -# Скрипт с коллбэком - -Создайте функцию `addScript(src, callback)`, которая загружает скрипт с данным `src`, и после его загрузки и выполнения вызывает функцию `callback`. - -Скрипт может быть любым, работа функции не должна зависеть от его содержимого. - -Пример использования: - -```js -// go.js содержит функцию go() -addScript("go.js", function() { - go(); -}); -``` - -Ошибки загрузки обрабатывать не нужно. - diff --git a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.md b/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.md deleted file mode 100644 index cfe4d03f..00000000 --- a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.md +++ /dev/null @@ -1,8 +0,0 @@ -# Подсказки - -Создайте переменную-счетчик для подсчёта количества загруженных скриптов. - -Чтобы один скрипт не учитывался два раза (например, `onreadystatechange` запустился при `loaded` и `complete`), учитывайте его состояние в объекте `loaded`. Свойство `loaded[i] = true` означает что `i`-й скрипт уже учтён. - -# Решение - diff --git a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/a.js b/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/a.js deleted file mode 100755 index 9d6742cd..00000000 --- a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/a.js +++ /dev/null @@ -1,3 +0,0 @@ -function a() { - b(); -} \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/b.js b/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/b.js deleted file mode 100755 index ce1689f2..00000000 --- a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/b.js +++ /dev/null @@ -1,3 +0,0 @@ -function b() { - c(); -} \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/c.js b/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/c.js deleted file mode 100755 index e343ee11..00000000 --- a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/c.js +++ /dev/null @@ -1,3 +0,0 @@ -function c() { - alert('ok'); -} \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/index.html b/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/index.html deleted file mode 100755 index a98093ad..00000000 --- a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/solution.view/index.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/a.js b/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/a.js deleted file mode 100755 index 9d6742cd..00000000 --- a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/a.js +++ /dev/null @@ -1,3 +0,0 @@ -function a() { - b(); -} \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/b.js b/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/b.js deleted file mode 100755 index ce1689f2..00000000 --- a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/b.js +++ /dev/null @@ -1,3 +0,0 @@ -function b() { - c(); -} \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/c.js b/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/c.js deleted file mode 100755 index e343ee11..00000000 --- a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/c.js +++ /dev/null @@ -1,3 +0,0 @@ -function c() { - alert('ok'); -} \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/index.html b/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/index.html deleted file mode 100755 index cff5595f..00000000 --- a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/source.view/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/task.md b/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/task.md deleted file mode 100644 index da8ac3f6..00000000 --- a/2-ui/3-event-details/11-onload-onerror/4-scripts-callback/task.md +++ /dev/null @@ -1,22 +0,0 @@ -importance: 5 - ---- - -# Скрипты с коллбэком - -Создайте функцию `addScripts(scripts, callback)`, которая загружает скрипты из массива `scripts`, и *после загрузки и выполнения их всех* вызывает функцию `callback`. - -Скрипт может быть любым, работа функции не должна зависеть от его содержимого. - -Пример использования: - -```js no-beautify -addScripts(["a.js", "b.js", "c.js"], function() { a() }); -/* функция a() описана в a.js и использует b.js,c.js */ -``` - -- Ошибки загрузки обрабатывать не нужно. -- Один скрипт не ждёт другого. Они все загружаются, а по окончании вызывается обработчик `callback`. - -Исходный код содержит скрипты `a.js`, `b.js`, `c.js`: - diff --git a/2-ui/3-event-details/11-onload-onerror/article.md b/2-ui/3-event-details/11-onload-onerror/article.md index 40edbd5b..acb91d13 100644 --- a/2-ui/3-event-details/11-onload-onerror/article.md +++ b/2-ui/3-event-details/11-onload-onerror/article.md @@ -1,227 +1,89 @@ # Resource loading: onload and onerror -Браузер позволяет отслеживать загрузку внешних ресурсов -- скриптов, ифреймов, картинок и других. +The browser allows to track the loading of external resources -- scripts, iframes, pictures and so on. -Для этого есть два события: +There are two events for it: -- `onload` -- если загрузка успешна. -- `onerror` -- если при загрузке произошла ошибка. +- `onload` -- successful load, +- `onerror` -- an error occured. -## Загрузка SCRIPT +## Loading a script -Рассмотрим следующую задачу. +Let's say we need to call a function that resides in an external script. -В браузере работает сложный интерфейс и, чтобы создать очередной компонент, нужно загрузить скрипт с сервера. - -Подгрузить внешний скрипт -- достаточно просто: +We can load it dynamically, like this: ```js -var script = document.createElement('script'); +let script = document.createElement('script'); script.src = "my.js"; -document.body.appendChild(script); +document.head.append(script); ``` -...Но как после подгрузки выполнить функцию, которая объявлена в этом скрипте? Для этого нужно отловить момент окончания загрузки и выполнения тега ` +``` + diff --git a/2-ui/4-forms-controls/1-form-elements/1-add-select-option/task.md b/2-ui/4-forms-controls/1-form-elements/1-add-select-option/task.md new file mode 100644 index 00000000..fa8f38da --- /dev/null +++ b/2-ui/4-forms-controls/1-form-elements/1-add-select-option/task.md @@ -0,0 +1,21 @@ +importance: 5 + +--- + +# Добавьте опцию к селекту + +Есть селект: + +```html + +``` + +При помощи JavaScript: + +1. Выведите значение и текст текущей выбранной опции. +2. Добавьте опцию: ``. +3. Сделайте её выбранной. + diff --git a/2-ui/4-forms-controls/1-form-elements/article.md b/2-ui/4-forms-controls/1-form-elements/article.md new file mode 100644 index 00000000..199d0e13 --- /dev/null +++ b/2-ui/4-forms-controls/1-form-elements/article.md @@ -0,0 +1,276 @@ +# Form properties and methods [todo] + +Forms and control elements, such as `` have a lot of special properties and events. + +Working with forms can be much more convenient if we know them. + + +[cut] + +## Navigation: form and elements + +Document forms are members of the special collection `document.forms`. + +That's a *named* collection: we can use both the name and the number to get the form. + +```js no-beautify +document.forms.my - the form with name="my" +document.forms[0] - the first form in the document +``` + +When we have a form, then any element is available in the named collection `form.elements`. + +For instance: + +```html run height=40 +
+ + +
+ + +``` + +There may be multiple elements with the same name, that's often the case with radio buttons. + +In that case `form.elements[name]` is a collection, for instance: + +```html run height=40 +
+ + +
+ + +``` + +These navigation properties do not depend on the tag structure. All elements, no matter how deep they are in the form, are available in `form.elements`. + + +````smart header="Fieldsets as \"subforms\"" +A form may have one or many `
` elements inside it. They also support the `elements` property. + +For instance: + +```html run height=80 + +
+
+ info + +
+
+ + + +``` +```` + +````warn header="Shorter notation: `form.name`" +There's a shorter notation: we can access the element as `form[index/name]`. + +Instead of `form.elements.login` we can write `form.login`. + +That also works, but there's a minor issue: if we access an element, and then change its `name`, then it is still available under the old name (as well as under the new one). + +That's easy to see in an example: + +```html run height=40 +
+ +
+ + +``` + +That's usually not a problem, because we rarely change names of form elements. + +```` + +## Backreference: element.form + +For any element, the form is available as `element.form`. So a form references all elements, and elements +reference the form. + +Here's the picture: + +![](form-navigation.png) + +For instance: + +```html run height=40 +
+ +
+ + +``` + +## Values: input and textarea + +Normally, we can read the value as `input.value` or `input.checked` (for radio) + +Для большинства типов `input` значение ставится/читается через свойство `value`. + +```js +input.value = "Новое значение"; +textarea.value = "Новый текст"; +``` + +```warn header="Не используйте `textarea.innerHTML`" +Для элементов `textarea` также доступно свойство `innerHTML`, но лучше им не пользоваться: оно хранит только HTML, изначально присутствовавший в элементе, и не меняется при изменении значения. +``` + +Исключения -- `input type="checkbox"` и `input type="radio"` + +**Текущее "отмеченное" состояние для `checkbox` и `radio` находится в свойстве `checked` (`true/false`).** + +```js +if (input.checked) { + alert( "Чекбокс выбран" ); +} +``` + +## Элементы select и option + +Селект в JavaScript можно установить двумя путями: поставив значение `select.value`, либо установив свойство `select.selectedIndex` в номер нужной опции.: + +```js +select.selectedIndex = 0; // первая опция +``` + +Установка `selectedIndex = -1` очистит выбор. + +**Список элементов-опций доступен через `select.options`.** + +Если `select` допускает множественный выбор (атрибут `multiple`), то значения можно получить/установить, сделав цикл по `select.options`. При этом выбранные опции будут иметь свойство `option.selected = true`. + +Пример: + +```html run +
+ +
+ + +``` + +Спецификация: [the select element](https://html.spec.whatwg.org/multipage/forms.html#the-select-element). + +````smart header="`new Option`" +В стандарте [the option element](https://html.spec.whatwg.org/multipage/forms.html#the-option-element) есть любопытный короткий синтаксис для создания элемента с тегом `option`: + +```js +option = new Option(text, value, defaultSelected, selected); +``` + +Параметры: + +- `text` -- содержимое, +- `value` -- значение, +- `defaultSelected` и `selected` поставьте в `true`, чтобы сделать элемент выбранным. + +Его можно использовать вместо `document.createElement('option')`, например: + +```js +var option = new Option("Текст", "value"); +// создаст +``` + +Такой же элемент, но выбранный: + +```js +var option = new Option("Текст", "value", true, true); +``` +```` + +```smart header="Дополнительные свойства `option`" +У элементов `option` также есть особые свойства, которые могут оказаться полезными (см. [the option element](https://html.spec.whatwg.org/multipage/forms.html#the-option-element)): + +`selected` +: выбрана ли опция + +`index` +: номер опции в списке селекта + +`text` +: Текстовое содержимое опции (то, что видит посетитель). +``` + +## Итого + +Свойства для навигации по формам: + +`document.forms` +: Форму можно получить как `document.forms[name/index]`. + +`form.elements` +: Элементы в форме: `form.elements[name/index]`. Каждый элемент имеет ссылку на форму в свойстве `form`. Свойство `elements` также есть у `
`. + +Значение элементов читается/ставится через `value` или `checked`. + +Для элемента `select` можно задать опцию по номеру через `select.selectedIndex` и перебрать опции через `select.options`. При этом выбранные опции (в том числе при мультиселекте) будут иметь свойство `option.selected = true`. + + +Спецификация: [HTML5 Forms](https://html.spec.whatwg.org/multipage/forms.html). diff --git a/2-ui/4-forms-controls/1-form-elements/form-navigation.png b/2-ui/4-forms-controls/1-form-elements/form-navigation.png new file mode 100644 index 00000000..5d00632b Binary files /dev/null and b/2-ui/4-forms-controls/1-form-elements/form-navigation.png differ diff --git a/2-ui/4-forms-controls/1-form-elements/form-navigation@2x.png b/2-ui/4-forms-controls/1-form-elements/form-navigation@2x.png new file mode 100644 index 00000000..1997b2b3 Binary files /dev/null and b/2-ui/4-forms-controls/1-form-elements/form-navigation@2x.png differ diff --git a/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/solution.md b/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/solution.md new file mode 100644 index 00000000..cfb7ad1e --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/solution.md @@ -0,0 +1,3 @@ +В данном случае достаточно событий `input.focus/input.blur`. + +Если бы мы хотели реализовать это на уровне документа, то применили бы делегирование и события `focusin/focusout` (эмуляцию для firefox), так как обычные `focus/blur` не всплывают. \ No newline at end of file diff --git a/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/solution.view/index.html b/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/solution.view/index.html new file mode 100644 index 00000000..208bc604 --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/solution.view/index.html @@ -0,0 +1,74 @@ + + + + + + + + + + +

Красивый placeholder:

+ + + + + + + + + + \ No newline at end of file diff --git a/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/source.view/index.html b/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/source.view/index.html new file mode 100644 index 00000000..d03c3101 --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/source.view/index.html @@ -0,0 +1,48 @@ + + + + + + + + + + +

Красивый placeholder:

+ + + + + + + + + + \ No newline at end of file diff --git a/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/task.md b/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/task.md new file mode 100644 index 00000000..68467638 --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/1-emulate-placeholder/task.md @@ -0,0 +1,20 @@ +importance: 5 + +--- + +# Улучшенный плейсхолдер + +Реализуйте более удобный плейсхолдер-подсказку на JavaScript через атрибут `data-placeholder`. + +Правила работы плейсхолдера: + +- Элемент изначально содержит плейсхолдер. Специальный класс `placeholder` придает ему синий цвет. +- При фокусировке плейсхолдер показывается уже над полем, становясь "подсказкой". +- При снятии фокуса, подсказка убирается, если поле пустое -- плейсхолдер возвращается в него. + +Демо: + +[iframe src="solution" height=100] + +В этой задаче плейсхолдер должен работать на одном конкретном input. Подумайте, если input много, как здесь применить делегирование? + diff --git a/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/solution.md b/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/solution.md new file mode 100644 index 00000000..57380a29 --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/solution.md @@ -0,0 +1,9 @@ + +Нам нужно ловить `onclick` на мышонке и в `onkeydown` на нём смотреть коды символов. При скан-кодах стрелок двигать мышонка через `position:absolute` или `position:fixed`. + +Скан-коды для клавиш стрелок можно узнать, нажимая на них на [тестовом стенде](info:keyboard-events#keyboard-test-stand). Вот они: 37-38-39-40 (влево-вверх-вправо-вниз). + +Проблема может возникнуть одна -- `keydown` не возникает на элементе, если на нём нет фокуса. + +Чтобы фокус был -- нужно добавить мышонку атрибут `tabindex` через JS или в HTML. + diff --git a/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/solution.view/index.html b/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/solution.view/index.html new file mode 100644 index 00000000..ac1a3259 --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/solution.view/index.html @@ -0,0 +1,65 @@ + + + + + + + + + + +

Кликните на мышонка и передвигайте его, нажимая клавиши со стрелками.

+ +
+ _   _
+(q\_/p)
+ /. .\
+=\_t_/=   __
+ /   \   (
+((   ))   )
+/\) (/\  /
+\  Y  /-'
+ nn^nn
+
+ + + + + + + \ No newline at end of file diff --git a/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/source.view/index.html b/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/source.view/index.html new file mode 100644 index 00000000..348d0a1d --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/source.view/index.html @@ -0,0 +1,42 @@ + + + + + + + + + + +

Кликните на мышонка и передвигайте его, нажимая клавиши со стрелками.

+ +
+ _   _
+(q\_/p)
+ /. .\
+=\_t_/=   __
+ /   \   (
+((   ))   )
+/\) (/\  /
+\  Y  /-'
+ nn^nn
+
+ + + + + + + \ No newline at end of file diff --git a/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/task.md b/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/task.md new file mode 100644 index 00000000..cc24c948 --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/2-keyboard-mouse/task.md @@ -0,0 +1,13 @@ +importance: 4 + +--- + +# Мышонок на "клавиатурном" приводе + +Кликните по мышонку. Затем нажимайте клавиши со стрелками, и он будет двигаться. + +[demo src="solution"] + +В этой задаче запрещается ставить обработчики куда-либо, кроме элемента `#mouse`. + +Можно изменять атрибуты и классы в HTML. diff --git a/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/solution.md b/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/solution.md new file mode 100644 index 00000000..c701514f --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/solution.md @@ -0,0 +1,99 @@ +# CSS для решения + +Как видно из исходного кода, `#view` -- это `
`, который будет содержать результат, а `#area` - это редактируемое текстовое поле. + +Так как мы преобразуем `
` в ` +
Текст
+ + + + + + + \ No newline at end of file diff --git a/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/solution.view/my.css b/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/solution.view/my.css new file mode 100644 index 00000000..06993029 --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/solution.view/my.css @@ -0,0 +1,27 @@ +#view, +#area { + height: 150px; + width: 400px; + font-family: arial; + font-size: 14px; +} + +#view { + /* padding + border = 3px */ + + padding: 2px; + border: 1px solid black; +} + +#area { + display: none; + /* replace padding with border (still 3px not to shift the contents) */ + + border: 3px groove blue; + padding: 0px; +} + +#area:focus { + outline: none; + /* remove focus border in Safari */ +} \ No newline at end of file diff --git a/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/source.view/index.html b/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/source.view/index.html new file mode 100644 index 00000000..1731e944 --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/source.view/index.html @@ -0,0 +1,22 @@ + + + + + + + + + +
    +
  • Ctrl-E to start editing.
  • +
  • While editing: Ctrl-S to save, Esc to cancel.
  • +
+ + + +
Text
+ + + + + \ No newline at end of file diff --git a/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/source.view/my.css b/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/source.view/my.css new file mode 100644 index 00000000..06993029 --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/source.view/my.css @@ -0,0 +1,27 @@ +#view, +#area { + height: 150px; + width: 400px; + font-family: arial; + font-size: 14px; +} + +#view { + /* padding + border = 3px */ + + padding: 2px; + border: 1px solid black; +} + +#area { + display: none; + /* replace padding with border (still 3px not to shift the contents) */ + + border: 3px groove blue; + padding: 0px; +} + +#area:focus { + outline: none; + /* remove focus border in Safari */ +} \ No newline at end of file diff --git a/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/task.md b/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/task.md new file mode 100644 index 00000000..4d0c1585 --- /dev/null +++ b/2-ui/4-forms-controls/2-focus-blur/3-hotkeys/task.md @@ -0,0 +1,14 @@ +importance: 5 + +--- + +# Горячие клавиши + +Создайте `
`, который при нажатии `key:Ctrl+E` превращается в ` + + + + + + + + + + + \ No newline at end of file diff --git a/2-ui/4-forms-controls/4-forms-submit/2-form-validation/source.view/index.html b/2-ui/4-forms-controls/4-forms-submit/2-form-validation/source.view/index.html new file mode 100644 index 00000000..b316af7c --- /dev/null +++ b/2-ui/4-forms-controls/4-forms-submit/2-form-validation/source.view/index.html @@ -0,0 +1,74 @@ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
От кого + +
Ваш пароль + +
Повторите пароль + +
Куда + +
+ + Сообщение: + + + +
+ + + + + + + \ No newline at end of file diff --git a/2-ui/4-forms-controls/4-forms-submit/2-form-validation/task.md b/2-ui/4-forms-controls/4-forms-submit/2-form-validation/task.md new file mode 100644 index 00000000..42ec25fd --- /dev/null +++ b/2-ui/4-forms-controls/4-forms-submit/2-form-validation/task.md @@ -0,0 +1,17 @@ +importance: 3 + +--- + +# Валидация формы + +Напишите функцию `validate(form)`, которая проверяет содержимое формы по клику на кнопку "Проверить". + +Ошибки: + +1. Одно из полей не заполнено. +2. Пароли не совпадают. + +Ошибка должна сопровождаться сообщением у поля. Например: + +[iframe height=280 src="solution"] + diff --git a/2-ui/4-forms-controls/4-forms-submit/article.md b/2-ui/4-forms-controls/4-forms-submit/article.md new file mode 100644 index 00000000..f3eb1409 --- /dev/null +++ b/2-ui/4-forms-controls/4-forms-submit/article.md @@ -0,0 +1,56 @@ +# Формы: отправка, событие и метод submit + +Событие `submit` возникает при отправке формы. Наиболее частое его применение -- это *валидация* (проверка) формы перед отправкой. + +Метод `submit` позволяет инициировать отправку формы из JavaScript, без участия пользователя. Далее мы рассмотрим детали их использования. + +[cut] + +## Событие submit + +Чтобы отправить форму на сервер, у посетителя есть два способа: + +1. **Первый -- это нажать кнопку `` или ``.** +2. **Второй -- нажать Enter, находясь на каком-нибудь поле.** + +Какой бы способ ни выбрал посетитель -- будет сгенерировано событие `submit`. Обработчик в нём может проверить данные и, если они неверны, то вывести ошибку и сделать `event.preventDefault()` -- тогда форма не отправится на сервер. + +Например, в таком HTML оба способа выведут `alert`, форма не будет отправлена: + +```html autorun height=80 no-beautify +
+ Первый: Enter в текстовом поле
+ Второй: Нажать на "Отправить": +
+``` + +Ожидаемое поведение: + +1. Перейдите в текстовое поле и нажмите Enter, будет событие, но форма не отправится на сервер благодаря `return false` в обработчике. +2. То же самое произойдет при клике на ``. + +````smart header="Взаимосвязь событий `submit` и `click`" +При отправке формы путём нажатия Enter на текстовом поле, на элементе `` везде, кроме IE8-, генерируется событие `click`. + +Это довольно забавно, учитывая что клика-то и не было. + +```html autorun height=80 +
+ + +
+``` +```` + +```warn header="В IE8- событие `submit` не всплывает" +В IE8- событие `submit` не всплывает. Нужно вешать обработчик `submit` на сам элемент формы, без использования делегирования. +``` + +## Метод submit + +Чтобы отправить форму на сервер из JavaScript -- нужно вызвать на элементе формы метод `form.submit()`. + +При этом само событие `submit` не генерируется. Предполагается, что если программист вызывает метод `form.submit()`, то он выполнил все проверки. + +Это используют, в частности, для искусственной генерации и отправки формы. + diff --git a/2-ui/4-forms-controls/index.md b/2-ui/4-forms-controls/index.md new file mode 100644 index 00000000..726474b1 --- /dev/null +++ b/2-ui/4-forms-controls/index.md @@ -0,0 +1,3 @@ +# Forms, controls + +Special properties and events for forms `
` and controls: ``, ` + +
+ + + + \ No newline at end of file diff --git a/7-frames-and-windows/3-same-origin-policy/article.md b/7-frames-and-windows/3-same-origin-policy/article.md new file mode 100644 index 00000000..a6b925b2 --- /dev/null +++ b/7-frames-and-windows/3-same-origin-policy/article.md @@ -0,0 +1,127 @@ +# Кросс-доменные ограничения и их обход + +Ограничение "Same Origin" ("тот же источник") ограничивает доступ окон и фреймов друг к другу, а также влияет на AJAX-запросы к серверу. + +Причина, по которой оно существует -- безопасность. Если есть два окна, в одном из которых `vasya-pupkin.com`, а в другом `gmail.com`, то мы бы не хотели, чтобы скрипт из первого мог читать нашу почту. + +Сама концепция проста, но есть много важных исключений и особенностей, которые нужно знать для полного понимания этого правила. + +[cut] + +## Концепция Same Origin [#same-origin] + +Два URL считаются имеющим один источник ("same origin"), если у них одинаковый протокол, домен и порт. + +Эти URL имеют один источник: + +- `http://site.com` +- `http://site.com`/ +- `http://site.com/my/page.html` + +А вот эти -- все из других источников: + +- http://www.site.com (другой домен) +- http://site.org (другой домен) +- https://site.com (другой протокол) +- http://site.com:8080 (другой порт) + +Существует ряд исключений, позволяющих-таки окнам с разных доменов обмениваться информацией, но прямой вызов методов друг друга и чтение свойств запрещены. + +## В действии + +Если одно окно попытается обратиться к другому, то браузер проверит, из одного ли они источника. Если нет -- доступ будет запрещён. + +Например: + +```html run + + + +``` + +Пример выше выведет ошибку. + +## Исключение: запись в location + +Окна могут менять `location` друг друга, даже если они из разных источников. + +Причём *читать* свойства `location` нельзя, одно окно не имеет право знать, на каком URL пользователь в другом. А вот *запись* браузеры считают безопасной. + +Например, открыв на `javascript.ru` iframe с `http://example.com`, из этого ифрейма нельзя будет прочитать URL, а вот поменять его -- запросто: + +```html run + + + +``` + +Если запустить код выше, то окно сначала загрузит `example.com`, а потом будет перенаправлено на `wikipedia.org`. + +## Исключение: поддомен 3-го уровня + +Ещё одно важное исключение касается доменов третьего уровня. + +Если несколько окон имеют общий домен второго уровня, к примеру `john.site.com`, `peter.site.com`, `site.com`, и присваивают в `document.domain` свой общий поддомен 2-го уровня `site.com`, то все ограничения снимаются. + +То есть, на всех этих сайтах должен быть код: +```js +document.domain = 'site.com'; +``` + +Тогда между ними не будет кросс-доменных ограничений. + +Обратим внимание: свойство `document.domain` должно быть присвоено на всех окнах, участвующих в коммуникации. Выглядит абсурдно, но даже на документе с `site.com` нужно вызвать: `document.domain="site.com"`. Иначе не будет работать. + +Таким образом разные подсайты в рамках одного общего проекта могут взаимодействовать без ограничений. + +## Исключения в IE + +В браузере Internet Explorer есть два своих, дополнительных исключения из Same Origin Policy. + +1. Порт не входит в понятие "источник" (origin). + + Это означает, что окно с `http://site.com` может свободно общаться с `http://site.com:8080`. + + Это иногда используют для общения серверов, использующих один IP-адрес. Но допустимо такое только в IE. +2. Если сайт находится в зоне "Надёжные узлы", то в Internet Explorer ограничения к нему не применяются. + + При этом подразумевается, что для этой зоны в параметрах "Безопасность" включена опция "Доступ к источникам данных за пределами домена". + +## Итого + +Ограничение "одного источника" запрещает окнам и фреймам с разных источников вызывать методы друг друга и читать данные друг из друга. + +При этом "из одного источника" означает "совпадают протокол, домен и порт". + +У этого подхода ряд существенных исключений: + +- Свойства `window.location.*` нельзя читать, но можно менять. +- Домены третьего уровня с общим наддоменом могут поменять `document.domain` на их общий домен второго уровня, и тогда они смогут взаимодействовать без ограничений. +- IE не включает порт в понятие источника. Кроме того, он позволяет снять ограничения для конкретного сайта включением в доверенную зону. + diff --git a/7-frames-and-windows/4-cross-window-messaging-with-postmessage/article.md b/7-frames-and-windows/4-cross-window-messaging-with-postmessage/article.md new file mode 100644 index 00000000..098690f9 --- /dev/null +++ b/7-frames-and-windows/4-cross-window-messaging-with-postmessage/article.md @@ -0,0 +1,97 @@ +# Общение окон с разных доменов: postMessage + +Интерфейс `postMessage` позволяет общаться друг с другом окнам и ифреймам с разных доменов. + +Он очень удобен, например, для взаимодействия внешних виджетов и сервисов, подключённых через ифрейм с основной страницей. + +[cut] + +## Отправитель: метод postMessage + +Первая часть интерфейса состоит из метода [postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage). Его вызывает окно, которое хочет отправить сообщение, в контексте окна-получателя. + +Проще говоря, если мы хотим отправить сообщение в окно `win`, то нужно вызвать `win.postMessage(data, targetOrigin)`. + +Аргументы: + +data +: Данные. По спецификации, это может быть любой объект, который будет *клонирован с сохранением структуры* при передаче. + + Но IE поддерживает только строки, поэтому обычно данные JSON-сериализуют. + +targetOrigin +: Разрешить получение сообщения только окнам с данного источника. + + Мы ведь не можем из JavaScript узнать, на каком именно URL находится другое окно. Но иногда хочется быть уверенным, что данные передаются в доверенный документ. Для этого и нужен этот параметр. Проверку осуществляет браузер. При указании `'*'` ограничений нет. + +Например: +```html no-beautify + + + + */!* + +
..И всё получится (хе-хе, у меня, злого хакера, получится)!
+``` + +В действии: + +[codetabs src="clickjacking-visible" height=200] + +Так как ` +``` + +Есть и другие приёмы для обхода этой простейшей защиты. + +Firefox и старый IE могут активировать designMode на исходной странице, это также предотвращает framebusting, у IE есть нестандартный атрибут [security](https://msdn.microsoft.com/en-us/library/ie/ms534622.aspx) для ифреймов, который можно использовать с той же целью. + +Как мы видим, эта защита не только не выдерживает реальной атаки, но и может скомпрометировать сайт (программист-то думает, что защитил его). + +## Заголовок X-Frame-Options + +Все современные браузеры поддерживают заголовок `X-Frame-Options`. + +Он разрешает или запрещает отображение страницы, если она открыта во фрейме. + +Браузеры игнорируют заголовок, если он определен в МЕТА теге. Таким образом, `` будет проигнорирован. + +У заголовка может быть три значения: + +SAMEORIGIN +: Рендеринг документа, при открытии во фрейме, производится только в том случае, когда верхний (top) документ -- с того же домена. + +DENY +: Рендеринг документа внутри фрейма запрещён. + +ALLOW-FROM domain +: Разрешает рендеринг, если внешний документ с данного домена (не поддерживается в Safari, Firefox). + +К примеру, Twitter использует `X-Frame-Options: SAMEORIGIN`. Результат: + +```html + +``` + + + +В зависимости от браузера, `iframe` выше либо пустой, либо в нём находится сообщение о невозможности отобразить его (IE). + +## Показ с отключённым функционалом + +Заголовок `X-Frame-Options` имеет неприятный побочный эффект. Иногда поисковики, анонимайзеры или другие сайты хотели бы отобразить страницу в `iframe`, по вполне "легальным" причинам, но не могут. + +Хорошо бы показывать их посетителям не пустой `iframe`, а нечто, что может быть более интересно. + +Например, можно изначально "накрывать" документ `div` с `height:100%;width:100%`, который будет перехватывать все клики. И поставить на нём ссылку, ведующую на страницу в новом окне. + +```html + + + + + +``` + +Если страница -- не во фрейме или домен совпадает, то посетитель не увидит его. + +## Заключение + +Атаку "Clickjacking" легко осуществить, если на сайте есть действие, активируемое с помощью одного клика. + +Злоумышленник может осуществить атаку целенаправленно на посетителей ресурса -- опубликовав ссылку на форуме, или "счастливой рассылкой". Существует масса вариантов. + +С первого взгляда, она "неглубокая": всё, что можно сделать -- это один клик. С другой стороны, если хакер знает, что после клика появляется какой-то другой управляющий элемент, то он, хитрыми сообщениями, может заставить посетителя кликнуть и по нему. А это уже не один, а два клика. + +Атака особенно опасна, поскольку, проектируя интерфейс сайта, обычно никто и не задумывается о том, что клик от имени юзера может сделать хакер. Точки уязвимости могут быть в совершенно непредсказуемых местах. + +- Рекомендуется использовать `X-Frame-Options` на страницах, заведомо не предназначеных для запуска во фрейме и на важнейших страницах (финансовые транзакции). +- Используйте перекрывающий `
`, если это допустимо вашим проектом и вы хотите разрешить безопасный показ документа во фреймах с любых доменов. + diff --git a/7-frames-and-windows/6-clickjacking/clickjacking-visible.view/facebook.html b/7-frames-and-windows/6-clickjacking/clickjacking-visible.view/facebook.html new file mode 100644 index 00000000..9d88ae28 --- /dev/null +++ b/7-frames-and-windows/6-clickjacking/clickjacking-visible.view/facebook.html @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/7-frames-and-windows/6-clickjacking/clickjacking-visible.view/index.html b/7-frames-and-windows/6-clickjacking/clickjacking-visible.view/index.html new file mode 100644 index 00000000..5301b0f8 --- /dev/null +++ b/7-frames-and-windows/6-clickjacking/clickjacking-visible.view/index.html @@ -0,0 +1,35 @@ + + + + + + + + + + + +
Нажмите, чтобы разбогатеть сейчас:
+ + + + + + +
..И всё получится (хе-хе, у меня, злого хакера, получится)!
+ + + + \ No newline at end of file diff --git a/7-frames-and-windows/6-clickjacking/clickjacking.view/facebook.html b/7-frames-and-windows/6-clickjacking/clickjacking.view/facebook.html new file mode 100644 index 00000000..9d88ae28 --- /dev/null +++ b/7-frames-and-windows/6-clickjacking/clickjacking.view/facebook.html @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/7-frames-and-windows/6-clickjacking/clickjacking.view/index.html b/7-frames-and-windows/6-clickjacking/clickjacking.view/index.html new file mode 100644 index 00000000..0e0599c4 --- /dev/null +++ b/7-frames-and-windows/6-clickjacking/clickjacking.view/index.html @@ -0,0 +1,35 @@ + + + + + + + + + + + +
Нажмите, чтобы разбогатеть сейчас:
+ + + + + + +
..И всё получится (хе-хе, у меня, злого хакера, получится)!
+ + + + \ No newline at end of file diff --git a/7-frames-and-windows/6-clickjacking/top-location.view/iframe.html b/7-frames-and-windows/6-clickjacking/top-location.view/iframe.html new file mode 100644 index 00000000..849ee4b1 --- /dev/null +++ b/7-frames-and-windows/6-clickjacking/top-location.view/iframe.html @@ -0,0 +1,18 @@ + + + + + + + + + +
Меняет top.location на javascript.ru
+ + + + + + \ No newline at end of file diff --git a/7-frames-and-windows/6-clickjacking/top-location.view/index.html b/7-frames-and-windows/6-clickjacking/top-location.view/index.html new file mode 100644 index 00000000..ef10e519 --- /dev/null +++ b/7-frames-and-windows/6-clickjacking/top-location.view/index.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + +

При нажатии на кнопку посетитель получит "странный" вопрос о том, не хочет ли уйти со страницы.

+ +

Наверно, он ответит "хочу остаться" и защита ифрейма будет провалена.

+ + + + + + \ No newline at end of file diff --git a/7-frames-and-windows/index.md b/7-frames-and-windows/index.md new file mode 100644 index 00000000..680aa953 --- /dev/null +++ b/7-frames-and-windows/index.md @@ -0,0 +1,2 @@ +# Окна и Фреймы + diff --git a/figures.sketch b/figures.sketch index 3bd350f9..222695ab 100644 Binary files a/figures.sketch and b/figures.sketch differ