renovations
This commit is contained in:
parent
5fb0e36f13
commit
dac75c79b5
18 changed files with 95 additions and 936 deletions
|
@ -20,28 +20,27 @@
|
||||||
var script = document.createElement('script');
|
var script = document.createElement('script');
|
||||||
script.src = "my.js";
|
script.src = "my.js";
|
||||||
|
|
||||||
document.documentElement.appendChild(script);
|
document.body.appendChild(script);
|
||||||
```
|
```
|
||||||
|
|
||||||
...Но, как подгрузки выполнить функцию из этого скрипта? Конечно, можно вызвать её в самом скрипте, но если скрипт -- это универсальная библиотека, то это было бы неправильно.
|
...Но как после подгрузки выполнить функцию, которая объявлена в этом скрипте? Для этого нужно отловить момент окончания загрузки и выполнения тега `<script>`.
|
||||||
|
|
||||||
### script.onload [#onload]
|
### script.onload
|
||||||
|
|
||||||
Первым нашим помощником станет событие `onload`.
|
Главным помощником станет событие `onload`. Оно сработает, когда скрипт загрузился и выполнился.
|
||||||
|
|
||||||
**Событие `onload` сработает, когда скрипт загрузился *и* выполнился.**
|
|
||||||
|
|
||||||
Например:
|
Например:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
var script = document.createElement('script');
|
var script = document.createElement('script');
|
||||||
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"
|
script.src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js"
|
||||||
document.documentElement.appendChild(script);
|
document.body.appendChild(script);
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
script.onload = function() {
|
script.onload = function() {
|
||||||
alert(jQuery);
|
// после выполнения скрипта становится доступна функция _
|
||||||
|
alert(_); // её код
|
||||||
}
|
}
|
||||||
*/!*
|
*/!*
|
||||||
```
|
```
|
||||||
|
@ -50,19 +49,19 @@ script.onload = function() {
|
||||||
|
|
||||||
...А что, если загрузка скрипта не удалась? Например, такого скрипта на сервере нет (ошибка 404) или сервер "упал" (ошибка 500).
|
...А что, если загрузка скрипта не удалась? Например, такого скрипта на сервере нет (ошибка 404) или сервер "упал" (ошибка 500).
|
||||||
|
|
||||||
По-хорошему, такое тоже нужно как-то обрабатывать, хотя бы сообщить посетителю о возникшей проблеме.
|
Такую ситуацию тоже нужно как-то обрабатывать, хотя бы сообщить посетителю о возникшей проблеме.
|
||||||
|
|
||||||
### script.onerror [#onerror]
|
### script.onerror
|
||||||
|
|
||||||
Любые ошибки загрузки (но не выполнения) скрипта отслеживаются обработчиком `onerror`.
|
Любые ошибки загрузки (но не выполнения) скрипта отслеживаются обработчиком `onerror`.
|
||||||
|
|
||||||
Например, для заведомо отсутствующего скрипта:
|
Например, сделаем запрос заведомо отсутствующего скрипта:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
var script = document.createElement('script');
|
var script = document.createElement('script');
|
||||||
script.src = "http://example.com/404.js"
|
script.src = "https://example.com/404.js"
|
||||||
document.documentElement.appendChild(script);
|
document.body.appendChild(script);
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
script.onerror = function() {
|
script.onerror = function() {
|
||||||
|
|
|
@ -9,10 +9,9 @@
|
||||||
|
|
||||||
Попробуйте различные варианты нажатия клавиш в текстовом поле.
|
Попробуйте различные варианты нажатия клавиш в текстовом поле.
|
||||||
|
|
||||||
|
[codetabs src="keyboard-dump" height=480]
|
||||||
|
|
||||||
[codetabs src="keyboard-dump"]
|
По мере чтения, если возникнут вопросы -- возвращайтесь к этому стенду.
|
||||||
|
|
||||||
По мере чтения статьи, если возникнут вопросы -- возвращайтесь к этому стенду.
|
|
||||||
|
|
||||||
## События keydown и keyup
|
## События keydown и keyup
|
||||||
|
|
||||||
|
@ -20,26 +19,27 @@
|
||||||
|
|
||||||
Скан-код клавиши одинаков в любой раскладке и в любом регистре. Например, клавиша [key z] может означать символ `"z"`, `"Z"` или `"я"`, `"Я"` в русской раскладке, но её *скан-код* будет всегда одинаков: `90`.
|
Скан-код клавиши одинаков в любой раскладке и в любом регистре. Например, клавиша [key z] может означать символ `"z"`, `"Z"` или `"я"`, `"Я"` в русской раскладке, но её *скан-код* будет всегда одинаков: `90`.
|
||||||
|
|
||||||
|
[online]
|
||||||
В действии:
|
В действии:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<input onkeydown="this.nextSibling.innerHTML = event.keyCode"><b></b>
|
<input onkeydown="this.nextSibling.innerHTML = event.keyCode"> <b></b>
|
||||||
```
|
```
|
||||||
|
|
||||||
<input size="40" placeholder="Нажмите клавишу, скан-код будет справа" onkeydown="this.nextSibling.innerHTML = event.keyCode"><b></b>
|
<input size="40" placeholder="Нажмите клавишу, скан-код будет справа" onkeydown="this.nextElementSibling.innerHTML = event.keyCode"> <b></b>
|
||||||
|
[/online]
|
||||||
|
|
||||||
### Какими бывают скан-коды?
|
### Скан-коды
|
||||||
|
|
||||||
Для буквенно-цифровых клавиш, скан-код будет равен коду соответствующей заглавной английской буквы/цифры.
|
Для буквенно-цифровых клавиш есть очень простое правило: скан-код будет равен коду соответствующей заглавной английской буквы/цифры.
|
||||||
|
|
||||||
Например, при нажатии клавиши [key S] (не важно, каков регистр и раскладка) её скан-код будет равен `"S".charCodeAt(0)`.
|
Например, при нажатии клавиши [key S] (не важно, каков регистр и раскладка) её скан-код будет равен `"S".charCodeAt(0)`.
|
||||||
|
|
||||||
С другими символами, например, знаками пунктуации, ситуация тоже понятна. Есть таблица кодов, которую можно взять, например, из статьи Джона Уолтера: <a href="http://unixpapa.com/js/key.html">JavaScript Madness: Keyboard Events</a>, или же можно нажать на нужную клавишу на [тестовом стенде](#keyboard-test-stand) и получить код.
|
Для других другими символов, например, знаками пунктуации, есть таблица кодов, которую можно взять, например, из статьи Джона Уолтера: <a href="http://unixpapa.com/js/key.html">JavaScript Madness: Keyboard Events</a>, или же можно нажать на нужную клавишу на [тестовом стенде](#keyboard-test-stand) и получить код.
|
||||||
|
|
||||||
Когда-то в этих кодах была масса кросс-браузерных несовместимостей. Сейчас всё проще -- таблицы кодов в различных браузерах почти полностью совпадают.
|
Когда-то в этих кодах была масса кросс-браузерных несовместимостей. Сейчас всё проще -- таблицы кодов в различных браузерах почти полностью совпадают. Но некоторые несовместимости, всё же, остались. Вы можете увидеть их в таблице ниже. Слева -- клавиша с символом, а справа -- скан-коды в различных браузерах.
|
||||||
|
|
||||||
Но некоторые несовместимости, всё же, остались. Вы можете увидеть их в таблице ниже. Слева -- клавиша с символом, а справа -- скан-коды в различных браузерах.
|
|
||||||
|
|
||||||
|
Таблица несовместимостей:
|
||||||
<table>
|
<table>
|
||||||
<tr><th>Клавиша</th><th>Firefox</th><th>Остальные браузеры</th></tr>
|
<tr><th>Клавиша</th><th>Firefox</th><th>Остальные браузеры</th></tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -59,6 +59,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
Остальные коды одинаковы, код для нужного символа будет в тестовом стенде.
|
||||||
|
|
||||||
## Событие keypress
|
## Событие keypress
|
||||||
|
|
||||||
|
@ -97,18 +98,18 @@ function getChar(event) {
|
||||||
<ol>
|
<ol>
|
||||||
<li>Во всех браузерах, кроме IE, у события `keypress` есть свойство `charCode`, которое содержит код символа.</li>
|
<li>Во всех браузерах, кроме IE, у события `keypress` есть свойство `charCode`, которое содержит код символа.</li>
|
||||||
<li>Браузер IE для `keypress` не устанавливает `charCode`, а вместо этого он записывает код символа в `keyCode` (в `keydown/keyup` там хранится скан-код).</li>
|
<li>Браузер IE для `keypress` не устанавливает `charCode`, а вместо этого он записывает код символа в `keyCode` (в `keydown/keyup` там хранится скан-код).</li>
|
||||||
|
<li>Также в функции выше используется проверка `if(event.which!=0)`, а не более короткая `if(event.which)`. Это не случайно! При `event.which=null` первое сравнение даст `true`, а второе -- `false`.</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
Также, посмотрите -- в функции выше используется проверка `if(event.which!=0)`, а не более короткая `if(event.which)`. Это не случайно! При `event.which=null` первое сравнение даст `true`, а второе -- `false`.
|
[online]
|
||||||
|
|
||||||
В действии:
|
В действии:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<input onkeypress="this.nextSibling.innerHTML = getChar(event)+''"><b></b>
|
<input onkeypress="this.nextSibling.innerHTML = getChar(event)+''"><b></b>
|
||||||
```
|
```
|
||||||
|
|
||||||
<input size="40" placeholder="Наберите символ, он будет справа" onkeypress="this.nextSibling.innerHTML = getChar(event)+''"><b></b>
|
<input size="40" placeholder="Наберите символ, он будет справа" onkeypress="this.nextElementSibling.innerHTML = getChar(event)+''"> <b></b>
|
||||||
|
[/online]
|
||||||
|
|
||||||
[warn header="Неправильный `getChar`"]
|
[warn header="Неправильный `getChar`"]
|
||||||
В сети вы можете найти другую функцию того же назначения:
|
В сети вы можете найти другую функцию того же назначения:
|
||||||
|
@ -119,15 +120,12 @@ function getChar(event) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Она работает неверно для многих специальных клавиш, потому что не фильтрует их. Например, она возвращает символ амперсанда `"&"`, когда нажата клавиша 'Стрелка Вверх'.
|
Она работает неверно для многих специальных клавиш, потому что не фильтрует их. Например, она возвращает символ амперсанда `"&"`, когда нажата клавиша 'Стрелка Вверх'. Лучше использовать ту, что приведена выше.
|
||||||
[/warn]
|
[/warn]
|
||||||
|
|
||||||
[smart header="Свойства-модификаторы"]
|
|
||||||
|
|
||||||
Как и у других событий, связанных с пользовательским вводом, поддерживаются свойства `shiftKey`, `ctrlKey`, `altKey` и `metaKey`.
|
Как и у других событий, связанных с пользовательским вводом, поддерживаются свойства `shiftKey`, `ctrlKey`, `altKey` и `metaKey`.
|
||||||
|
|
||||||
Они установлены в `true`, если нажаты клавиши-модификаторы -- соответственно, [key Shift], [key Ctrl], [key Alt] и [key Cmd] для Mac.
|
Они установлены в `true`, если нажаты клавиши-модификаторы -- соответственно, [key Shift], [key Ctrl], [key Alt] и [key Cmd] для Mac.
|
||||||
[/smart]
|
|
||||||
|
|
||||||
## Отмена пользовательского ввода
|
## Отмена пользовательского ввода
|
||||||
|
|
||||||
|
@ -139,11 +137,13 @@ function getChar(event) {
|
||||||
<input *!*onkeypress="return false"*/!* type="text" size="30">
|
<input *!*onkeypress="return false"*/!* type="text" size="30">
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[online]
|
||||||
Попробуйте что-нибудь ввести в этих полях (не получится):
|
Попробуйте что-нибудь ввести в этих полях (не получится):
|
||||||
|
|
||||||
<input onkeydown="return false" type="text" size="30">
|
<input onkeydown="return false" type="text" size="30">
|
||||||
|
|
||||||
<input onkeypress="return false" type="text" size="30">
|
<input onkeypress="return false" type="text" size="30">
|
||||||
|
[/online]
|
||||||
|
|
||||||
При тестировании на стенде вы можете заметить, что отмена действия браузера при `keydown` также предотвращает само событие `keypress`.
|
При тестировании на стенде вы можете заметить, что отмена действия браузера при `keydown` также предотвращает само событие `keypress`.
|
||||||
|
|
||||||
|
@ -158,17 +158,6 @@ function getChar(event) {
|
||||||
[/warn]
|
[/warn]
|
||||||
|
|
||||||
|
|
||||||
[warn header="Не для работы с формами"]
|
|
||||||
Распространённая ошибка -- использовать события клавиатуры для работы с полями ввода в формах.
|
|
||||||
|
|
||||||
Это неправильно. События клавиатуры предназначены именно для работы с клавиатурой. Да, их можно использовать и для `<input>`, но будут побочные эффекты.
|
|
||||||
|
|
||||||
Например, текст может быть вставлен мышкой, при помощи правого клика и меню, без единого нажатия клавиши. И как нам помогут события клавиатуры?
|
|
||||||
|
|
||||||
Некоторые мобильные устройства не генерируют `keypress/keydown`, а сразу вставляют текст в поле. Отменить ввод для них таким образом нельзя, как и вообще отловить его.
|
|
||||||
|
|
||||||
Далее мы разберём [события для элементов форм](/events-change), которые позволяют работать с вводом в формы правильно.
|
|
||||||
[/warn]
|
|
||||||
|
|
||||||
### Отмена любых действий
|
### Отмена любых действий
|
||||||
|
|
||||||
|
@ -188,9 +177,9 @@ function getChar(event) {
|
||||||
В примере ниже действие браузера отменяется с помощью `return false`, а вместо него в `input` добавляется значение в верхнем регистре:
|
В примере ниже действие браузера отменяется с помощью `return false`, а вместо него в `input` добавляется значение в верхнем регистре:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<input id="my" type="text" size="2">
|
<input id="only-upper" type="text" size="2">
|
||||||
<script>
|
<script>
|
||||||
document.getElementById('my').onkeypress = function(e) {
|
document.getElementById('only-upper').onkeypress = function(e) {
|
||||||
// спец. сочетание - не обрабатываем
|
// спец. сочетание - не обрабатываем
|
||||||
if (e.ctrlKey || e.altKey || e.metaKey) return;
|
if (e.ctrlKey || e.altKey || e.metaKey) return;
|
||||||
|
|
||||||
|
@ -205,9 +194,10 @@ document.getElementById('my').onkeypress = function(e) {
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
В действии: <input id="my" type="text" size="2">
|
[online]
|
||||||
|
В действии: <input id="only-upper" type="text" size="2">
|
||||||
<script>
|
<script>
|
||||||
document.getElementById('my').onkeypress = function(e) {
|
document.getElementById('only-upper').onkeypress = function(e) {
|
||||||
var char = getChar(e);
|
var char = getChar(e);
|
||||||
|
|
||||||
// спец. сочетание - не обрабатываем
|
// спец. сочетание - не обрабатываем
|
||||||
|
@ -219,63 +209,53 @@ document.getElementById('my').onkeypress = function(e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
[/online]
|
||||||
|
|
||||||
|
## Невосместимости [#keyboard-events-order]
|
||||||
|
|
||||||
## Особенности клавиш и ОС [#keyboard-events-order]
|
Некоторые несовместимости в порядке срабатывания клавиатурных событий (когда что) ещё существуют.
|
||||||
|
|
||||||
События `keydown/keyup` возникают всегда. А `keypress` -- по-разному.
|
Стоит иметь в виду три основных категории клавиш, работа с которыми отличается.
|
||||||
|
|
||||||
Есть три основных категории клавиш, работа с которыми отличается.
|
|
||||||
|
|
||||||
Перечислим их в таблице, обращая основное внимание на особенности работы с ними.
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Категория</th>
|
<th>Категория</th>
|
||||||
<th>Примеры</th>
|
|
||||||
<th>События</th>
|
<th>События</th>
|
||||||
<th>Описание</th>
|
<th>Описание</th>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Печатные клавиши</td>
|
<td>Печатные клавиши [key S] [key 1] [key ,]</td>
|
||||||
<td style="white-space:nowrap">[key S] [key 1] [key ,]</td>
|
|
||||||
<td>`keydown`
|
<td>`keydown`
|
||||||
`keypress`
|
`keypress`
|
||||||
`keyup`</td>
|
`keyup`</td>
|
||||||
<td>Нажатие вызывает `keydown` и `keypress`.
|
<td>Нажатие вызывает `keydown` и `keypress`.
|
||||||
Когда клавишу отпускают, срабатывает `keyup`.
|
Когда клавишу отпускают, срабатывает `keyup`.
|
||||||
|
|
||||||
Исключение -- CapsLock под MacOS, он глючит неимоверно:
|
Исключение -- CapsLock под MacOS, с ним есть проблемы:
|
||||||
<ul>
|
<ul>
|
||||||
<li>В Safari/Chrome/Opera: при включении только `keydown`, при отключении только `keyup`.</li>
|
<li>В Safari/Chrome/Opera: при включении только `keydown`, при отключении только `keyup`.</li>
|
||||||
<li>В Firefox: при включении и отключении только `keydown`.</li>
|
<li>В Firefox: при включении и отключении только `keydown`.</li>
|
||||||
</ul>
|
</ul>
|
||||||
Попробуйте на тестовом стенде.
|
</td>
|
||||||
</td>
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Специальные клавиши</td>
|
<td>Специальные клавиши [key Alt] [key Esc] [key ⇧]</td>
|
||||||
<td style="white-space:nowrap">[key Alt] [key Esc] [key ⇧]</td>
|
|
||||||
<td>`keydown`
|
<td>`keydown`
|
||||||
`keyup`</td>
|
`keyup`</td>
|
||||||
<td>Нажатие вызывает `keydown`.
|
<td>Нажатие вызывает `keydown`.
|
||||||
Когда клавишу отпускают, срабатывает `keyup`.
|
Когда клавишу отпускают, срабатывает `keyup`.
|
||||||
|
|
||||||
Некоторые браузеры могут дополнительно генерировать и `keypress`, например IE для [key Esc]. Попробуйте нажать [key Esc] на тестовом стенде в разных браузерах -- и увидите: в IE `keypress` есть, а в остальных -- нет.
|
Некоторые браузеры могут дополнительно генерировать и `keypress`, например IE для [key Esc].
|
||||||
|
|
||||||
На практике это не доставляет проблем, так как для специальных клавиш мы всегда используем `keydown/keyup`.
|
На практике это не доставляет проблем, так как для специальных клавиш мы всегда используем `keydown/keyup`.
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Сочетания с печатной клавишей</td>
|
<td>Сочетания с печатной клавишей
|
||||||
<td style="white-space:nowrap">
|
|
||||||
|
|
||||||
[key Alt+E]
|
[key Alt+E]
|
||||||
[key Ctrl+У]
|
[key Ctrl+У]
|
||||||
[key Cmd+1]
|
[key Cmd+1]
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td>`keydown`
|
<td>`keydown`
|
||||||
`keypress?`
|
`keypress?`
|
||||||
|
@ -283,11 +263,18 @@ document.getElementById('my').onkeypress = function(e) {
|
||||||
<td>
|
<td>
|
||||||
Браузеры под Windows -- не генерируют `keypress`, браузеры под MacOS -- генерируют.
|
Браузеры под Windows -- не генерируют `keypress`, браузеры под MacOS -- генерируют.
|
||||||
|
|
||||||
Кроме того, если сочетание вызвало браузерное действие или диалог ("Сохранить файл", "Открыть" и т.п., ряд диалогов можно отменить при `keydown`), то `keypress/keyup` может не быть.
|
Кроме того, если сочетание вызвало браузерное действие или диалог ("Сохранить файл", "Открыть" и т.п., ряд диалогов можно отменить при `keydown`), то может быть только `keydown`.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
Общий вывод можно сделать такой:
|
||||||
|
<ul>
|
||||||
|
<li>Обычные символы работают везде корректно.</li>
|
||||||
|
<li>CapsLock под MacOS ведёт себя плохо, не стоит ставить на него обработчики вообще.</li>
|
||||||
|
<li>Для других специальных клавиш и сочетаний с ними следует использовать только `keydown`.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## Автоповтор
|
## Автоповтор
|
||||||
|
|
||||||
При долгом нажатии клавиши возникает *автоповтор*. По стандарту, должны генерироваться многократные события `keydown (+keypress)`, и вдобавок стоять свойство [repeat=true](http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent-repeat) у объекта события.
|
При долгом нажатии клавиши возникает *автоповтор*. По стандарту, должны генерироваться многократные события `keydown (+keypress)`, и вдобавок стоять свойство [repeat=true](http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent-repeat) у объекта события.
|
||||||
|
@ -316,23 +303,27 @@ keyup
|
||||||
keyup
|
keyup
|
||||||
```
|
```
|
||||||
|
|
||||||
...А Chrome под MacOS не генерирует `keypress`. В общем, "зоопарк". Полагаться можно только на `keydown` при каждом автонажатии и `keyup` по отпусканию клавиши.
|
...А Chrome под MacOS не генерирует `keypress`. В общем, "зоопарк".
|
||||||
|
|
||||||
## Итого, рецепты
|
Полагаться можно только на `keydown` при каждом автонажатии и `keyup` по отпусканию клавиши.
|
||||||
|
|
||||||
Если обобщить данные из этой таблицы и статьи, то можно сделать ряд выводов:
|
## Итого
|
||||||
|
|
||||||
|
Ряд рецептов по итогу этой главы:
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>Для реализации горячих клавиш, включая сочетания -- используем `keydown`.</li>
|
<li>Для реализации горячих клавиш, включая сочетания -- используем `keydown`. Скан-код будет в `keyCode`, почти все скан-коды кросс-браузерны, кроме нескольких пунктуационных, перечисленных в таблице выше.</li>
|
||||||
<li>Если нужен именно символ -- используем `keypress`. При этом функция `getChar` позволит получить символ и отфильтровать лишние срабатывания.</li>
|
<li>Если нужен именно символ -- используем `keypress`. При этом функция `getChar` позволит получить символ и отфильтровать лишние срабатывания. Гарантированно получать символ можно только при нажатии обычных клавиш, если речь о сочетаниях с модификаторами, то `keypress` не всегда генерируется.</li>
|
||||||
<li>Ловля CapsLock глючит под MacOS. Её можно организовать при помощи проверки `navigator.userAgent` и `navigator.platform`, а лучше вообще не трогать эту клавишу.</li>
|
<li>Ловля CapsLock глючит под MacOS. Её можно организовать при помощи проверки `navigator.userAgent` и `navigator.platform`, а лучше вообще не трогать эту клавишу.</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
Для работы с вводом в формы, существуют [события для форм](/events-change), которые мы разберём позже. Их можно использовать как отдельно от событий клавиатуры, так и вместе с ними.
|
Распространённая ошибка -- использовать события клавиатуры для работы с полями ввода в формах.
|
||||||
|
|
||||||
|
Это нежелательно. События клавиатуры предназначены именно для работы с клавиатурой. Да, их можно использовать для проверки ввода в `<input>`, но будут недочёты. Например, текст может быть вставлен мышкой, при помощи правого клика и меню, без единого нажатия клавиши. И как нам помогут события клавиатуры?
|
||||||
|
|
||||||
|
Некоторые мобильные устройства также не генерируют `keypress/keydown`, а сразу вставляют текст в поле. Обработать ввод на них при помощи клавиатурных событий нельзя.
|
||||||
|
|
||||||
|
Далее мы разберём [события для элементов форм](/events-change), которые позволяют работать с вводом в формы правильно.
|
||||||
|
|
||||||
|
Их можно использовать как отдельно от событий клавиатуры, так и вместе с ними.
|
||||||
|
|
||||||
[head]
|
|
||||||
<style> #scan-codes th, #scan-codes td {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
[/head]
|
|
|
@ -6,7 +6,6 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
|
||||||
<form id="form" onsubmit="return false">
|
<form id="form" onsubmit="return false">
|
||||||
|
|
||||||
Предотвратить действие по умолчанию для:<label><input type="checkbox" name="keydownStop" value="1"> keydown</label> <label><input type="checkbox" name="keypressStop" value="1"> keypress</label> <label><input type="checkbox" name="keyupStop" value="1"> keyup</label>
|
Предотвратить действие по умолчанию для:<label><input type="checkbox" name="keydownStop" value="1"> keydown</label> <label><input type="checkbox" name="keypressStop" value="1"> keypress</label> <label><input type="checkbox" name="keyupStop" value="1"> keyup</label>
|
||||||
|
@ -16,10 +15,11 @@
|
||||||
|
|
||||||
<p>Сфокусируйтесь на поле и нажмите какую-нибудь клавишу.</p>
|
<p>Сфокусируйтесь на поле и нажмите какую-нибудь клавишу.</p>
|
||||||
|
|
||||||
<input type="text" placeholder="Поле для тестов" id="kinput">
|
<input type="text" placeholder="Клавиши нажимать тут" id="kinput">
|
||||||
|
|
||||||
|
<textarea id="area"></textarea>
|
||||||
|
<input type="button" value="Очистить" onclick="area.value = ''"/></form>
|
||||||
|
|
||||||
<textarea rows="18" id="text"></textarea>
|
|
||||||
<input type="button" value="Очистить" onclick="text.value = ''"/></form>
|
|
||||||
</form>
|
</form>
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
|
|
||||||
kinput.onkeydown = kinput.onkeyup = kinput.onkeypress = handle;
|
kinput.onkeydown = kinput.onkeyup = kinput.onkeypress = handle;
|
||||||
|
|
||||||
|
var lastTime = Date.now();
|
||||||
|
|
||||||
function handle(e) {
|
function handle(e) {
|
||||||
if (form.elements[e.type + 'Ignore'].checked) return;
|
if (form.elements[e.type + 'Ignore'].checked) return;
|
||||||
|
|
||||||
var evt = e.type
|
var text = event.type +
|
||||||
while (evt.length < 10) evt += ' '
|
|
||||||
text.value += evt +
|
|
||||||
' keyCode=' + e.keyCode +
|
' keyCode=' + e.keyCode +
|
||||||
' which=' + e.which +
|
' which=' + e.which +
|
||||||
' charCode=' + e.charCode +
|
' charCode=' + e.charCode +
|
||||||
|
@ -16,6 +16,12 @@ function handle(e) {
|
||||||
(e.altKey ? ' +alt' : '') +
|
(e.altKey ? ' +alt' : '') +
|
||||||
(e.metaKey ? ' +meta' : '') + "\n";
|
(e.metaKey ? ' +meta' : '') + "\n";
|
||||||
|
|
||||||
|
if (area.value && Date.now() - lastTime > 250) {
|
||||||
|
area.value += new Array(81).join('-') + '\n';
|
||||||
|
}
|
||||||
|
lastTime = Date.now();
|
||||||
|
|
||||||
|
area.value += text;
|
||||||
|
|
||||||
if (form.elements[e.type + 'Stop'].checked) {
|
if (form.elements[e.type + 'Stop'].checked) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
form {
|
|
||||||
border:solid gray 1px;
|
|
||||||
margin:10px;
|
|
||||||
padding:10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#kinput {
|
#kinput {
|
||||||
font-size:150%;
|
font-size: 150%;
|
||||||
width:600px;
|
width: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#text {
|
|
||||||
width:600px;
|
#area {
|
||||||
border:1px solid black;
|
width: 600px;
|
||||||
|
height: 250px;
|
||||||
|
border: 1px solid black;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
form label {
|
form label {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<style>
|
|
||||||
body, html {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-left {
|
|
||||||
float: left;
|
|
||||||
width: 30%;
|
|
||||||
background: #aef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-right {
|
|
||||||
margin-left: 30%;
|
|
||||||
width: 70%;
|
|
||||||
background: tan;
|
|
||||||
overflow: auto; /* расшириться вниз захватить float'ы */
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
line-height: 60px;
|
|
||||||
background: yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner {
|
|
||||||
margin: 1em;
|
|
||||||
font-size: 130%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#avatar {
|
|
||||||
float:left;
|
|
||||||
margin: 0 1em .5em 0;
|
|
||||||
border: 1px solid black;
|
|
||||||
text-align:center;
|
|
||||||
background:white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fixed {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="header">Шапка</div>
|
|
||||||
|
|
||||||
<div class="column-left">
|
|
||||||
<div class="inner">
|
|
||||||
<h3>Персонажи:</h3>
|
|
||||||
<ul>
|
|
||||||
<li>Винни-Пух</li>
|
|
||||||
<li>Ослик Иа</li>
|
|
||||||
<li>Сова</li>
|
|
||||||
<li>Кролик</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="column-right">
|
|
||||||
<div class="inner">
|
|
||||||
|
|
||||||
<h3>Винни-Пух</h3>
|
|
||||||
|
|
||||||
<div id="avatar">
|
|
||||||
<img src="//js.cx/clipart/winnie-mult.jpg" width="200" height="150">
|
|
||||||
<div>Кадр из мультфильма</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>Ви́нни-Пу́х (англ. Winnie-the-Pooh) — плюшевый мишка, персонаж повестей и стихов Алана Александра Милна (цикл не имеет общего названия и обычно тоже называется «Винни-Пух», по первой книге). Один из самых известных героев детской литературы XX века.</p>
|
|
||||||
|
|
||||||
<p>В 1960-е—1970-е годы, благодаря пересказу Бориса Заходера «Винни-Пух и все-все-все», а затем и фильмам студии «Союзмультфильм», где мишку озвучивал Евгений Леонов, Винни-Пух стал очень популярен и в Советском Союзе.</p>
|
|
||||||
|
|
||||||
<p>Как и многие другие персонажи книги Милна, медвежонок Винни получил имя от одной из реальных игрушек Кристофера Робина (1920—1996), сына писателя. В свою очередь, плюшевый мишка Винни-Пух был назван по имени медведицы по кличке Виннипег (Винни), содержавшейся в 1920-х в Лондонском зоопарке.</p>
|
|
||||||
|
|
||||||
<p>Медведица Виннипег (американский чёрный медведь) попала в Великобританию как живой талисман (маскот) Канадского армейского ветеринарного корпуса из Канады, а именно из окрестностей города Виннипега. Она оказалась в кавалерийском полку «Форт Гарри Хорс» 24 августа 1914 года ещё будучи медвежонком (её купил у канадского охотника-траппера за двадцать долларов 27-летний полковой ветеринар лейтенант Гарри Колборн, заботившийся о ней и в дальнейшем). Уже в октябре того же года медвежонок был привезён вместе с войсками в Британию, а так как полк должен был быть в ходе Первой мировой войны переправлен во Францию, то в декабре было принято решение оставить зверя до конца войны в Лондонском зоопарке. Медведица полюбилась лондонцам, и военные не стали возражать против того, чтобы не забирать её из зоопарка и после войны[1]. До конца дней (она умерла 12 мая 1934 года) медведица находилась на довольствии ветеринарного корпуса, о чём в 1919 году на её клетке сделали соответствующую надпись.</p>
|
|
||||||
|
|
||||||
<p>«Винни-Пух» представляет собой дилогию, но каждая из двух книг Милна распадается на 10 рассказов (stories) с собственным сюжетом, которые могут читаться, экранизироваться и т. д. независимо друг от друга. В некоторых переводах деление на две части не сохранено, в других не переведена вторая («Дом на Пуховой опушке»). Иногда первая и вторая книги выполнены разными переводчиками. Такова необычная судьба немецкого Винни-Пуха: первая книга вышла в немецком переводе в 1928 году, а вторая лишь в 1954; между этими датами — ряд трагических событий германской истории.</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>Действие книг о Пухе происходит в 500-акровом лесу Эшдаун близ купленной Милнами в 1925 году фермы Кочфорд в графстве Восточный Сассекс, Англия, представленном в книге как Стоакровый лес (англ. The Hundred Acre Wood, в пересказе Заходера — Чудесный лес). Реальными являются также Шесть сосен и ручеёк, у которого был найден Северный Полюс, а также упоминаемая в тексте растительность, в том числе колючий утёсник (gorse-bush, чертополох у Заходера), в который падает Пух[2]. Маленький Кристофер Робин любил забираться в дупла деревьев и играть там с Пухом, поэтому многие персонажи книг живут в дуплах, и значительная часть действия происходит в таких жилищах или на ветвях деревьев[2].
|
|
||||||
Алан Милн, Кристофер Робин и Винни-Пух. Фотография из Британской национальной портретной галереи</p>
|
|
||||||
|
|
||||||
<p>Действие «Винни-Пуха» разворачивается одновременно в трёх планах — это мир игрушек в детской, мир зверей «на своей территории» в Стоакровом лесу и мир персонажей в рассказах отца сыну (это наиболее чётко показано в самом начале)[4]. В дальнейшем рассказчик исчезает из повествования, и сказочный мир начинает собственное существование, разрастаясь от главы к главе[6]. Отмечалось сходство пространства и мира персонажей «Винни-Пуха» с классическим античным и средневековым эпосом[6]. Многообещающие эпические начинания персонажей (путешествия, подвиги, охоты, игры) оказываются комически малозначительными, в то время как настоящие события происходят во внутреннем мире героев (помощь в беде, гостеприимство, дружба)[6].</p>
|
|
||||||
|
|
||||||
<p>Книги Милна выросли из устных рассказов и игр с Кристофером Робином; устное происхождение характерно и для многих других знаменитых литературных сказок[6]. «Я, собственно, ничего не придумывал, мне оставалось только описывать», как говорил впоследствии Милн[5]. Реальными игрушками Кристофера Робина были также Пятачок (подарок соседей), Иа-Иа без хвоста (ранний подарок родителей), Кенга с Крошкой Ру в сумке и Тигра (куплены родителями впоследствии специально для развития сюжета вечерних рассказов сыну). В рассказах они появляются именно в таком порядке[2]. Сову и Кролика Милн придумал сам; на иллюстрациях Шепарда они выглядят не как игрушки, а как настоящие животные, Кролик говорит Сове: «Только у меня и тебя есть мозги. У остальных — опилки». В процессе игры все эти персонажи получили индивидуальные повадки, привычки и манеру разговора[6]. На созданный Милном мир животных повлияла повесть Кеннета Грэма «Ветер в ивах», которой он восхищался и которую ранее иллюстрировал Шепард[5], возможна также скрытая полемика с «Книгой джунглей» Киплинга[5]. Текст взят из Википедии.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var avatarElem = document.getElementById('avatar');
|
|
||||||
|
|
||||||
var avatarSourceBottom = avatarElem.getBoundingClientRect().bottom + window.pageYOffset;
|
|
||||||
|
|
||||||
window.onscroll = function() {
|
|
||||||
if (avatarElem.classList.contains('fixed') && window.pageYOffset < avatarSourceBottom) {
|
|
||||||
avatarElem.classList.remove('fixed');
|
|
||||||
} else if (window.pageYOffset > avatarSourceBottom) {
|
|
||||||
avatarElem.classList.add('fixed');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,91 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<style>
|
|
||||||
body, html {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-left {
|
|
||||||
float: left;
|
|
||||||
width: 30%;
|
|
||||||
background: #aef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-right {
|
|
||||||
margin-left: 30%;
|
|
||||||
width: 70%;
|
|
||||||
background: tan;
|
|
||||||
overflow: auto; /* расшириться вниз захватить float'ы */
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
line-height: 60px;
|
|
||||||
background: yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner {
|
|
||||||
margin: 1em;
|
|
||||||
font-size: 130%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#avatar {
|
|
||||||
float:left;
|
|
||||||
margin: 0 1em .5em 0;
|
|
||||||
border: 1px solid black;
|
|
||||||
text-align:center;
|
|
||||||
background:white;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="header">Шапка</div>
|
|
||||||
|
|
||||||
<div class="column-left">
|
|
||||||
<div class="inner">
|
|
||||||
<h3>Персонажи:</h3>
|
|
||||||
<ul>
|
|
||||||
<li>Винни-Пух</li>
|
|
||||||
<li>Ослик Иа</li>
|
|
||||||
<li>Сова</li>
|
|
||||||
<li>Кролик</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="column-right">
|
|
||||||
<div class="inner">
|
|
||||||
|
|
||||||
<h3>Винни-Пух</h3>
|
|
||||||
|
|
||||||
<div id="avatar">
|
|
||||||
<img src="//js.cx/clipart/winnie-mult.jpg" width="200" height="150">
|
|
||||||
<div>Кадр из мультфильма</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>Ви́нни-Пу́х (англ. Winnie-the-Pooh) — плюшевый мишка, персонаж повестей и стихов Алана Александра Милна (цикл не имеет общего названия и обычно тоже называется «Винни-Пух», по первой книге). Один из самых известных героев детской литературы XX века.</p>
|
|
||||||
|
|
||||||
<p>В 1960-е—1970-е годы, благодаря пересказу Бориса Заходера «Винни-Пух и все-все-все», а затем и фильмам студии «Союзмультфильм», где мишку озвучивал Евгений Леонов, Винни-Пух стал очень популярен и в Советском Союзе.</p>
|
|
||||||
|
|
||||||
<p>Как и многие другие персонажи книги Милна, медвежонок Винни получил имя от одной из реальных игрушек Кристофера Робина (1920—1996), сына писателя. В свою очередь, плюшевый мишка Винни-Пух был назван по имени медведицы по кличке Виннипег (Винни), содержавшейся в 1920-х в Лондонском зоопарке.</p>
|
|
||||||
|
|
||||||
<p>Медведица Виннипег (американский чёрный медведь) попала в Великобританию как живой талисман (маскот) Канадского армейского ветеринарного корпуса из Канады, а именно из окрестностей города Виннипега. Она оказалась в кавалерийском полку «Форт Гарри Хорс» 24 августа 1914 года ещё будучи медвежонком (её купил у канадского охотника-траппера за двадцать долларов 27-летний полковой ветеринар лейтенант Гарри Колборн, заботившийся о ней и в дальнейшем). Уже в октябре того же года медвежонок был привезён вместе с войсками в Британию, а так как полк должен был быть в ходе Первой мировой войны переправлен во Францию, то в декабре было принято решение оставить зверя до конца войны в Лондонском зоопарке. Медведица полюбилась лондонцам, и военные не стали возражать против того, чтобы не забирать её из зоопарка и после войны[1]. До конца дней (она умерла 12 мая 1934 года) медведица находилась на довольствии ветеринарного корпуса, о чём в 1919 году на её клетке сделали соответствующую надпись.</p>
|
|
||||||
|
|
||||||
<p>«Винни-Пух» представляет собой дилогию, но каждая из двух книг Милна распадается на 10 рассказов (stories) с собственным сюжетом, которые могут читаться, экранизироваться и т. д. независимо друг от друга. В некоторых переводах деление на две части не сохранено, в других не переведена вторая («Дом на Пуховой опушке»). Иногда первая и вторая книги выполнены разными переводчиками. Такова необычная судьба немецкого Винни-Пуха: первая книга вышла в немецком переводе в 1928 году, а вторая лишь в 1954; между этими датами — ряд трагических событий германской истории.</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>Действие книг о Пухе происходит в 500-акровом лесу Эшдаун близ купленной Милнами в 1925 году фермы Кочфорд в графстве Восточный Сассекс, Англия, представленном в книге как Стоакровый лес (англ. The Hundred Acre Wood, в пересказе Заходера — Чудесный лес). Реальными являются также Шесть сосен и ручеёк, у которого был найден Северный Полюс, а также упоминаемая в тексте растительность, в том числе колючий утёсник (gorse-bush, чертополох у Заходера), в который падает Пух[2]. Маленький Кристофер Робин любил забираться в дупла деревьев и играть там с Пухом, поэтому многие персонажи книг живут в дуплах, и значительная часть действия происходит в таких жилищах или на ветвях деревьев[2].
|
|
||||||
Алан Милн, Кристофер Робин и Винни-Пух. Фотография из Британской национальной портретной галереи</p>
|
|
||||||
|
|
||||||
<p>Действие «Винни-Пуха» разворачивается одновременно в трёх планах — это мир игрушек в детской, мир зверей «на своей территории» в Стоакровом лесу и мир персонажей в рассказах отца сыну (это наиболее чётко показано в самом начале)[4]. В дальнейшем рассказчик исчезает из повествования, и сказочный мир начинает собственное существование, разрастаясь от главы к главе[6]. Отмечалось сходство пространства и мира персонажей «Винни-Пуха» с классическим античным и средневековым эпосом[6]. Многообещающие эпические начинания персонажей (путешествия, подвиги, охоты, игры) оказываются комически малозначительными, в то время как настоящие события происходят во внутреннем мире героев (помощь в беде, гостеприимство, дружба)[6].</p>
|
|
||||||
|
|
||||||
<p>Книги Милна выросли из устных рассказов и игр с Кристофером Робином; устное происхождение характерно и для многих других знаменитых литературных сказок[6]. «Я, собственно, ничего не придумывал, мне оставалось только описывать», как говорил впоследствии Милн[5]. Реальными игрушками Кристофера Робина были также Пятачок (подарок соседей), Иа-Иа без хвоста (ранний подарок родителей), Кенга с Крошкой Ру в сумке и Тигра (куплены родителями впоследствии специально для развития сюжета вечерних рассказов сыну). В рассказах они появляются именно в таком порядке[2]. Сову и Кролика Милн придумал сам; на иллюстрациях Шепарда они выглядят не как игрушки, а как настоящие животные, Кролик говорит Сове: «Только у меня и тебя есть мозги. У остальных — опилки». В процессе игры все эти персонажи получили индивидуальные повадки, привычки и манеру разговора[6]. На созданный Милном мир животных повлияла повесть Кеннета Грэма «Ветер в ивах», которой он восхищался и которую ранее иллюстрировал Шепард[5], возможна также скрытая полемика с «Книгой джунглей» Киплинга[5]. Текст взят из Википедии.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,12 +0,0 @@
|
||||||
# Аватар наверху при прокрутке
|
|
||||||
|
|
||||||
[importance 5]
|
|
||||||
|
|
||||||
Сделайте так, чтобы при прокрутке ниже элемента `#avatar` (картинка с Винни-Пухом) -- он продолжал показываться в левом-верхнем углу.
|
|
||||||
|
|
||||||
При прокрутке вверх -- должен возвращаться на обычное место.
|
|
||||||
|
|
||||||
Прокрутите вниз, чтобы увидеть:
|
|
||||||
[iframe src="solution" height=300 link border="1"]
|
|
||||||
|
|
||||||
[edit task src="source"/]
|
|
|
@ -1,94 +0,0 @@
|
||||||
Добавим в документ `DIV` с кнопкой:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<div id="updown"></div>
|
|
||||||
```
|
|
||||||
|
|
||||||
Сама кнопка должна иметь `position:fixed`.
|
|
||||||
|
|
||||||
```css
|
|
||||||
#updown {
|
|
||||||
position: fixed;
|
|
||||||
top: 30px;
|
|
||||||
left: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Кнопка является CSS-спрайтом, поэтому мы дополнительно добавляем ей размер и два состояния:
|
|
||||||
|
|
||||||
```css
|
|
||||||
#updown {
|
|
||||||
height: 9px;
|
|
||||||
width: 14px;
|
|
||||||
position: fixed;
|
|
||||||
top: 30px;
|
|
||||||
left: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#updown.up {
|
|
||||||
background: url(...updown.gif) left top;
|
|
||||||
}
|
|
||||||
|
|
||||||
#updown.down {
|
|
||||||
background: url(...updown.gif) left -9px;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Для решения необходимо аккуратно разобрать все возможные состояния кнопки и указать, что делать при каждом.
|
|
||||||
|
|
||||||
Состояние -- это просто класс элемента: `up/down` или пустая строка, если кнопка не видна.
|
|
||||||
|
|
||||||
При прокрутке состояния меняются следующим образом:
|
|
||||||
|
|
||||||
```js
|
|
||||||
window.onscroll = function() {
|
|
||||||
var pageY = window.pageYOffset || document.documentElement.scrollTop;
|
|
||||||
var innerHeight = document.documentElement.clientHeight;
|
|
||||||
|
|
||||||
switch(updownElem.className) {
|
|
||||||
case '':
|
|
||||||
if (pageY > innerHeight) {
|
|
||||||
updownElem.className = 'up';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'up':
|
|
||||||
if (pageY < innerHeight) {
|
|
||||||
updownElem.className = '';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'down':
|
|
||||||
if (pageY > innerHeight) {
|
|
||||||
updownElem.className = 'up';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
При клике:
|
|
||||||
|
|
||||||
```js
|
|
||||||
var pageYLabel = 0;
|
|
||||||
|
|
||||||
updownElem.onclick = function() {
|
|
||||||
var pageY = window.pageYOffset || document.documentElement.scrollTop;
|
|
||||||
|
|
||||||
switch(this.className) {
|
|
||||||
case 'up':
|
|
||||||
pageYLabel = pageY;
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
this.className = 'down';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'down':
|
|
||||||
window.scrollTo(0, pageYLabel);
|
|
||||||
this.className = 'up';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<style>
|
|
||||||
body, html {
|
|
||||||
height:100%;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
#matrix {
|
|
||||||
width: 400px;
|
|
||||||
margin: auto;
|
|
||||||
overflow: auto;
|
|
||||||
text-align: justify;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#updown {
|
|
||||||
height: 9px;
|
|
||||||
width: 14px;
|
|
||||||
position: fixed;
|
|
||||||
top: 30px;
|
|
||||||
left: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#updown.up {
|
|
||||||
background: url(//js.cx/clipart/updown.gif) left top;
|
|
||||||
}
|
|
||||||
|
|
||||||
#updown.down {
|
|
||||||
background: url(//js.cx/clipart/updown.gif) left -9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div id="matrix">
|
|
||||||
<script>for (var i = 0; i < 2000; i++) document.writeln(i)</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="updown"></div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var updownElem = document.getElementById('updown');
|
|
||||||
|
|
||||||
var pageYLabel = 0;
|
|
||||||
|
|
||||||
updownElem.onclick = function() {
|
|
||||||
var pageY = window.pageYOffset || document.documentElement.scrollTop;
|
|
||||||
|
|
||||||
switch(this.className) {
|
|
||||||
case 'up':
|
|
||||||
pageYLabel = pageY;
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
this.className = 'down';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'down':
|
|
||||||
window.scrollTo(0, pageYLabel);
|
|
||||||
this.className = 'up';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onscroll = function() {
|
|
||||||
var pageY = window.pageYOffset || document.documentElement.scrollTop;
|
|
||||||
var innerHeight = document.documentElement.clientHeight;
|
|
||||||
|
|
||||||
switch(updownElem.className) {
|
|
||||||
case '':
|
|
||||||
if (pageY > innerHeight) {
|
|
||||||
updownElem.className = 'up';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'up':
|
|
||||||
if (pageY < innerHeight) {
|
|
||||||
updownElem.className = '';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'down':
|
|
||||||
if (pageY > innerHeight) {
|
|
||||||
updownElem.className = 'up';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,35 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<style>
|
|
||||||
body, html {
|
|
||||||
height:100%;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
#matrix {
|
|
||||||
width: 400px;
|
|
||||||
margin: auto;
|
|
||||||
overflow: auto;
|
|
||||||
text-align: justify;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<img src="//js.cx/clipart/updown.gif">
|
|
||||||
|
|
||||||
<div id="matrix">
|
|
||||||
<script>for (var i = 0; i < 2000; i++) document.writeln(i)</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// ... ваш код
|
|
||||||
// при необходимости, в документ можно добавить элементы и стили
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Кнопка вверх-вниз
|
|
||||||
|
|
||||||
[importance 3]
|
|
||||||
|
|
||||||
Создайте кнопку навигации, которая помогает при прокрутке страницы.
|
|
||||||
|
|
||||||
Работать должна следующим образом:
|
|
||||||
<ul>
|
|
||||||
<li>Пока страница промотана меньше чем на высоту экрана вниз -- кнопка не видна.</li>
|
|
||||||
<li>При промотке страницы вниз больше, чем на высоту экрана, появляется кнопка "стрелка вверх". При нажатии на нее страница запоминает текущую прокрутку и прыгает вверх, а кнопка меняется на "стрелка вниз" и остается такой, пока посетитель не прокрутит вниз больше, чем один экран, после чего вновь изменится на "стрелка вверх".</li>
|
|
||||||
<li>Нажатие на "стрелка вниз" отправляет обратно на запомненную позицию.</li>
|
|
||||||
</ul>
|
|
||||||
Должен получиться удобный навигационный помощник.
|
|
||||||
|
|
||||||
Посмотрите, как оно должно работать, в ифрейме ниже. Прокрутите ифрейм, навигационная стрелка появится слева.
|
|
||||||
|
|
||||||
[iframe border="1" height="200" link src="solution"]
|
|
||||||
|
|
||||||
В исходный документ включена кнопка.
|
|
||||||
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
Функция должна по текущей прокрутке определять, какие изображения видимы, и загружать их.
|
|
||||||
|
|
||||||
Она должна срабатывать не только при прокрутке, но и при загрузке. Вполне достаточно для этого -- указать ее вызов в скрипте под страницей, вот так:
|
|
||||||
|
|
||||||
```js
|
|
||||||
... страница ...
|
|
||||||
|
|
||||||
function isVisible(elem) {
|
|
||||||
|
|
||||||
var coords = elem.getBoundingClientRect();
|
|
||||||
|
|
||||||
var windowHeight = document.documentElement.clientHeight;
|
|
||||||
|
|
||||||
// верхняя граница elem в пределах видимости ИЛИ нижняя граница видима
|
|
||||||
var topVisible = coords.top > 0 && coords.top < windowHeight;
|
|
||||||
var bottomVisible = coords.bottom < windowHeight && coords.bottom > 0;
|
|
||||||
|
|
||||||
return topVisible || bottomVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
*!*
|
|
||||||
showVisible();
|
|
||||||
window.onscroll = showVisible;
|
|
||||||
*/!*
|
|
||||||
```
|
|
||||||
|
|
||||||
При запуске функция ищет все видимые картинки с `realsrc` и перемещает значение `realsrc` в `src`. Обратите внимание, т.к. атрибут `realsrc` нестандартный, то для доступа к нему мы используем `get/setAttribute`. А `src` -- стандартный, поэтому можно обратиться по DOM-свойству.
|
|
||||||
|
|
||||||
**Функция проверки видимости `isVisible(elem)` получает координаты текущей видимой области и сравнивает их с элементом.**
|
|
||||||
|
|
||||||
Для видимости достаточно, чтобы координаты верхней(или нижней) границы элемента находились между границами видимой области.
|
|
||||||
|
|
||||||
В решении также указан вариант с `isVisible`, который расширяет область видимости на +-1 страницу (высота страницы -- `document.documentElement.clientHeight`).
|
|
||||||
|
|
||||||
[edit src="solution"]Открыть полное решение в песочнице[/edit]
|
|
|
@ -1,159 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<style>
|
|
||||||
.news-item {
|
|
||||||
width: 700px;
|
|
||||||
text-align: justify;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
.news-item .title {
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<p>Тексты и картинки взяты с сайта http://etoday.ru. </p>
|
|
||||||
|
|
||||||
<h3>Все изображения с realsrc загружаются, когда становятся видимыми.</h3>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Космопорт Америка \ Architecture</div>
|
|
||||||
|
|
||||||
Будущее уже сейчас! Скоро фраза из фантастического фильма "флипнуть до космопорта" станет реальностью. По крайней мере вторую ее часть человечество обеспечило. В октябре состоялась официальная церемония открытия космопорта «Америка», первой в мире коммерческой площадки для частных космических полетов. Космопорт открылся в пустыне штата Нью-Мексико. Проект был реализован английским бюро Foster and Partners. Космопорт включает в себя зал ожидания и подготовки к полетам, диспетчерский пункт и ангар. Также обеспечена взлетно-посадочная полоса длиной в три километра.
|
|
||||||
|
|
||||||
<div class="illustrations">
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="200" height="140" realsrc="//js.cx/lazyimg/1.jpg">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Рокер и супермодель в Vogue Russia \ Celebrities</div>
|
|
||||||
|
|
||||||
Супермодель Анна Вялицына (Anne Vyalitsyna) и музыкант Адам Ливайн (Adam Levine) снялись в ноябрьском номере Vogue Russia. Снимал их Аликс Малка (Alix Malka). Анна и Адам примерили на себя рок-н-ролльные наряды от Alexander Wang, Louis Vuitton, Alexander McQueen, Balmain, Yves Saint Laurent, подобранные для них Катериной Мухиной.
|
|
||||||
<div class="illustrations">
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="200" height="259" realsrc="//js.cx/lazyimg/2-1.jpg">
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="200" height="260" realsrc="//js.cx/lazyimg/2-2.jpg">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Старость - не радость в Vogue Italia \ Fashion Photo</div>
|
|
||||||
|
|
||||||
Стивен Мейзел (Steven Meisel) снял фотосессию для октябрьского Vogue Italia. В съемках приняли участие: Карен Элсон (Karen Elson), Джиневер ван Синус (Guinevere van Seenus), Эмма Балфур (Emma Balfour), Эн Уст (An Oost), Коринна Ингенлеф (Corinna Ingenleuf), Танга Моро (Tanga Moreau), Кордула Рейер (Cordula Reyer), Гейл о`Нил (Gail O'Neil), Эвелин Кун (Evelyn Kuhn), Каролин де Мэгрэ (Caroline de Maigret), Дэльфин Бафор (Delfine Bafort), Кирстен Оуэн (Kirsten Owen), Гунилла Линдблад (Gunilla Lindblad).
|
|
||||||
<div class="illustrations">
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="341" height="474" realsrc="//js.cx/lazyimg/3-1.jpg">
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="338" height="474" realsrc="//js.cx/lazyimg/3-2.jpg">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">"Вышитый рентген" Matthew Cox \ Art</div>
|
|
||||||
|
|
||||||
Художник из Филадельфии Мэтью Кокс (Matthew Cox) создал серию работ, в которых объединены медицинский рентген и вышивка. Художник взял рентгенограммы и вышил их предполагаемое содержание частично со скелетными элементами. Получилось зловеще и интригующе. Выставка "Вышитый рентген" будет демонстрироваться в галерее Packer/Schopf в Майами, в рамках Базельской Художественной Недели.
|
|
||||||
|
|
||||||
Эта серия - только треть творческой продукции Кокса. Он также создает традиционные картины и иллюстрации.
|
|
||||||
<div class="illustrations"><img src="//js.cx/lazyimg/1.gif" width="680" height="452" realsrc="//js.cx/lazyimg/4.jpg"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Подарочный каталог Apple 1983 \ Creative</div>
|
|
||||||
|
|
||||||
Etoday предлагает полистать страницы подарочного каталога продукции Apple образца 1983 года. Кажется, это было так давно!
|
|
||||||
Эта серия - только треть творческой продукции Кокса. Он также создает традиционные картины и иллюстрации.
|
|
||||||
<div class="illustrations"><img src="//js.cx/lazyimg/1.gif" width="600" height="393" realsrc="//js.cx/lazyimg/5.jpg"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Винтажные открытки к празднику Halloween \ Illustrations</div>
|
|
||||||
|
|
||||||
Занимательная коллекция старых почтовых открыток праздника Halloween. Открытки взяты из ньюйоркской публичной библиотеки и датируются примерно 1910 г.
|
|
||||||
|
|
||||||
<div class="illustrations"><img src="//js.cx/lazyimg/1.gif" width="680" height="433" realsrc="//js.cx/lazyimg/6.jpg"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Фотограф Emily Lee \ Photography</div>
|
|
||||||
|
|
||||||
Молодой фотограф Эмили Ли (Emily Lee) использует фотографию, чтобы выразить свои чувства. "Когда я смотрю на жизнь через камеру, вижу все более ясно, - пишет она на своем профиле Flickr. - Фотосъемка - это искусство наблюдения." Эмили Ли - обладательница большого таланта и умения глубоко понимать искусство, хотя учится еще только в средней школе.
|
|
||||||
|
|
||||||
<div class="illustrations"><img src="//js.cx/lazyimg/1.gif" width="680" height="453" realsrc="//js.cx/lazyimg/7.jpg"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Иконы моды в Fashimals \ Creative</div>
|
|
||||||
|
|
||||||
Fashimals - tumblr-блог, посвященный иконам моды, превращенным в животных. Здесь есть Анна Винтур, Карл Лагерфельд, Терри Ричардсон, а также много других их коллег.
|
|
||||||
|
|
||||||
<div class="illustrations"><img src="//js.cx/lazyimg/1.gif" width="600" height="622" realsrc="//js.cx/lazyimg/8.jpg"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
/**
|
|
||||||
* Проверяет элемент на попадание в видимую часть экрана.
|
|
||||||
* Для попадания достаточно, чтобы верхняя или нижняя границы элемента были видны.
|
|
||||||
*/
|
|
||||||
function isVisible(elem) {
|
|
||||||
|
|
||||||
var coords = elem.getBoundingClientRect();
|
|
||||||
|
|
||||||
var windowHeight = document.documentElement.clientHeight;
|
|
||||||
|
|
||||||
// верхняя граница elem в пределах видимости ИЛИ нижняя граница видима
|
|
||||||
var topVisible = coords.top > 0 && coords.top < windowHeight;
|
|
||||||
var bottomVisible = coords.bottom < windowHeight && coords.bottom > 0;
|
|
||||||
|
|
||||||
return topVisible || bottomVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Вариант проверки, считающий элемент видимым,
|
|
||||||
если он не более чем -1 страница назад или +1 страница вперед
|
|
||||||
|
|
||||||
function isVisible(elem) {
|
|
||||||
|
|
||||||
var coords = elem.getBoundingClientRect();
|
|
||||||
|
|
||||||
var windowHeight = document.documentElement.clientHeight;
|
|
||||||
|
|
||||||
var extendedTop = -windowHeight;
|
|
||||||
var extendedBottom = 2 * windowHeight;
|
|
||||||
|
|
||||||
// top visible || bottom visible
|
|
||||||
var topVisible = coords.top > extendedTop && coords.top < extendedBottom;
|
|
||||||
var bottomVisible = coords.bottom < extendedBottom && coords.bottom > extendedTop;
|
|
||||||
|
|
||||||
return topVisible || bottomVisible;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
function showVisible() {
|
|
||||||
var imgs = document.getElementsByTagName('img');
|
|
||||||
for(var i=0; i<imgs.length; i++) {
|
|
||||||
|
|
||||||
var img = imgs[i];
|
|
||||||
|
|
||||||
var realsrc = img.getAttribute('realsrc');
|
|
||||||
if (!realsrc) continue;
|
|
||||||
|
|
||||||
if (isVisible(img)) {
|
|
||||||
img.src = realsrc;
|
|
||||||
img.setAttribute('realsrc', '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onscroll = showVisible;
|
|
||||||
showVisible();
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<style>
|
|
||||||
.news-item {
|
|
||||||
width: 700px;
|
|
||||||
text-align: justify;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
.news-item .title {
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<p>Тексты и картинки взяты с сайта http://etoday.ru. </p>
|
|
||||||
|
|
||||||
<h3>Все изображения с realsrc загружаются, когда становятся видимыми.</h3>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Космопорт Америка \ Architecture</div>
|
|
||||||
|
|
||||||
Будущее уже сейчас! Скоро фраза из фантастического фильма "флипнуть до космопорта" станет реальностью. По крайней мере вторую ее часть человечество обеспечило. В октябре состоялась официальная церемония открытия космопорта «Америка», первой в мире коммерческой площадки для частных космических полетов. Космопорт открылся в пустыне штата Нью-Мексико. Проект был реализован английским бюро Foster and Partners. Космопорт включает в себя зал ожидания и подготовки к полетам, диспетчерский пункт и ангар. Также обеспечена взлетно-посадочная полоса длиной в три километра.
|
|
||||||
|
|
||||||
<div class="illustrations">
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="200" height="140" realsrc="//js.cx/lazyimg/1.jpg">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Рокер и супермодель в Vogue Russia \ Celebrities</div>
|
|
||||||
|
|
||||||
Супермодель Анна Вялицына (Anne Vyalitsyna) и музыкант Адам Ливайн (Adam Levine) снялись в ноябрьском номере Vogue Russia. Снимал их Аликс Малка (Alix Malka). Анна и Адам примерили на себя рок-н-ролльные наряды от Alexander Wang, Louis Vuitton, Alexander McQueen, Balmain, Yves Saint Laurent, подобранные для них Катериной Мухиной.
|
|
||||||
<div class="illustrations">
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="200" height="259" realsrc="//js.cx/lazyimg/2-1.jpg">
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="200" height="260" realsrc="//js.cx/lazyimg/2-2.jpg">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Старость - не радость в Vogue Italia \ Fashion Photo</div>
|
|
||||||
|
|
||||||
Стивен Мейзел (Steven Meisel) снял фотосессию для октябрьского Vogue Italia. В съемках приняли участие: Карен Элсон (Karen Elson), Джиневер ван Синус (Guinevere van Seenus), Эмма Балфур (Emma Balfour), Эн Уст (An Oost), Коринна Ингенлеф (Corinna Ingenleuf), Танга Моро (Tanga Moreau), Кордула Рейер (Cordula Reyer), Гейл о`Нил (Gail O'Neil), Эвелин Кун (Evelyn Kuhn), Каролин де Мэгрэ (Caroline de Maigret), Дэльфин Бафор (Delfine Bafort), Кирстен Оуэн (Kirsten Owen), Гунилла Линдблад (Gunilla Lindblad).
|
|
||||||
<div class="illustrations">
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="341" height="474" realsrc="//js.cx/lazyimg/3-1.jpg">
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="338" height="474" realsrc="//js.cx/lazyimg/3-2.jpg">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">"Вышитый рентген" Matthew Cox \ Art</div>
|
|
||||||
|
|
||||||
Художник из Филадельфии Мэтью Кокс (Matthew Cox) создал серию работ, в которых объединены медицинский рентген и вышивка. Художник взял рентгенограммы и вышил их предполагаемое содержание частично со скелетными элементами. Получилось зловеще и интригующе. Выставка "Вышитый рентген" будет демонстрироваться в галерее Packer/Schopf в Майами, в рамках Базельской Художественной Недели.
|
|
||||||
|
|
||||||
Эта серия - только треть творческой продукции Кокса. Он также создает традиционные картины и иллюстрации.
|
|
||||||
<div class="illustrations"><img src="//js.cx/lazyimg/1.gif" width="680" height="452" realsrc="//js.cx/lazyimg/4.jpg"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Подарочный каталог Apple 1983 \ Creative</div>
|
|
||||||
|
|
||||||
Etoday предлагает полистать страницы подарочного каталога продукции Apple образца 1983 года. Кажется, это было так давно!
|
|
||||||
Эта серия - только треть творческой продукции Кокса. Он также создает традиционные картины и иллюстрации.
|
|
||||||
<div class="illustrations"><img src="//js.cx/lazyimg/1.gif" width="600" height="393" realsrc="//js.cx/lazyimg/5.jpg"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Винтажные открытки к празднику Halloween \ Illustrations</div>
|
|
||||||
|
|
||||||
Занимательная коллекция старых почтовых открыток праздника Halloween. Открытки взяты из ньюйоркской публичной библиотеки и датируются примерно 1910 г.
|
|
||||||
|
|
||||||
<div class="illustrations"><img src="//js.cx/lazyimg/1.gif" width="680" height="433" realsrc="//js.cx/lazyimg/6.jpg"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Фотограф Emily Lee \ Photography</div>
|
|
||||||
|
|
||||||
Молодой фотограф Эмили Ли (Emily Lee) использует фотографию, чтобы выразить свои чувства. "Когда я смотрю на жизнь через камеру, вижу все более ясно, - пишет она на своем профиле Flickr. - Фотосъемка - это искусство наблюдения." Эмили Ли - обладательница большого таланта и умения глубоко понимать искусство, хотя учится еще только в средней школе.
|
|
||||||
|
|
||||||
<div class="illustrations"><img src="//js.cx/lazyimg/1.gif" width="680" height="453" realsrc="//js.cx/lazyimg/7.jpg"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="news-item">
|
|
||||||
<div class="title">Иконы моды в Fashimals \ Creative</div>
|
|
||||||
|
|
||||||
Fashimals - tumblr-блог, посвященный иконам моды, превращенным в животных. Здесь есть Анна Винтур, Карл Лагерфельд, Терри Ричардсон, а также много других их коллег.
|
|
||||||
|
|
||||||
<div class="illustrations"><img src="//js.cx/lazyimg/1.gif" width="600" height="622" realsrc="//js.cx/lazyimg/8.jpg"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// ... ваш код ...
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,49 +0,0 @@
|
||||||
# Загрузка видимых изображений
|
|
||||||
|
|
||||||
[importance 4]
|
|
||||||
|
|
||||||
Задача, которая описана ниже, демонстрирует результативный метод оптимизации страницы.
|
|
||||||
|
|
||||||
С целью экономии трафика и более быстрой загрузки страницы изображения на ней заменяются на "макеты".
|
|
||||||
|
|
||||||
Вместо такого изображения:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<img src="yozhik.jpg" width="128" height="128">
|
|
||||||
```
|
|
||||||
|
|
||||||
<img src="//js.cx/clipart/yozhik.jpg" width="128" height="128">
|
|
||||||
|
|
||||||
|
|
||||||
Стоит вот такое:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<img *!*src="1.gif"*/!* width="128" height="128" *!*realsrc="yozhik.jpg"*/!*>
|
|
||||||
```
|
|
||||||
|
|
||||||
<img src="//js.cx/lazyimg/1.gif" width="128" height="128">
|
|
||||||
|
|
||||||
То есть настоящий URL находится в атрибуте `realsrc` (название атрибута можно выбрать любое). А в `src` поставлен серый GIF размера 1x1, и так как `width/height` правильные, то он растягивается, так что вместо изображения виден серый прямоугольник.
|
|
||||||
|
|
||||||
При этом, чтобы браузер загрузил изображение, нужно заменить значение `src` на то, которое находится в `realsrc`.
|
|
||||||
|
|
||||||
**Если страница большая, то замена больших изображений на такие макеты существенно убыстряет полную загрузку страницы.** Это особенно заметно в случае, когда на странице много анонсов новостей с картинками или изображений товаров, из которых многие находятся за пределами прокрутки.
|
|
||||||
|
|
||||||
Кроме того, для мобильных устройств JavaScript может подставлять URL уменьшенного варианта картинки.
|
|
||||||
|
|
||||||
**Напишите код, который при прокрутке окна загружает ставшие видимыми изображения.** То есть, как только изображение попало в видимую часть документа -- в `src` нужно прописать правильный URL из `realsrc`.
|
|
||||||
|
|
||||||
Работать должно так: <a target="_blank" href="/files/tutorial/browser/events/lazyimg/index.html">открыть работающую страницу в новом окне</a>.
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>При начальной загрузке некоторые изображения должны быть видны сразу, до прокрутки. Код должен это учитывать.</li>
|
|
||||||
<li>Некоторые изображения могут быть обычными, без `realsrc`. Их код не должен трогать вообще.</li>
|
|
||||||
<li>Также код не должен перегружать уже показанное изображение.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
**Дополнительно: расширьте код, чтобы загружались изображения не только видимые сейчас, но и на страницу вперед и назад от текущего места.**
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
P.S. Страница прокручивается только вверх или вниз, горизонтальной прокрутки нет.
|
|
|
@ -1,31 +0,0 @@
|
||||||
# Прокрутка: событие scroll
|
|
||||||
|
|
||||||
Событие `onscroll` происходит, когда элемент прокручивается.
|
|
||||||
|
|
||||||
В отличие от события `onwheel` (колесико мыши), его могут генерировать только прокручиваемые элементы или окно `window`. Но зато оно генерируется всегда, при любой прокрутке, не обязательно "мышиной".
|
|
||||||
|
|
||||||
[cut]
|
|
||||||
Например, следующая функция при прокрутке окна выдает количество прокрученных пикселей:
|
|
||||||
|
|
||||||
```js
|
|
||||||
//+ autorun
|
|
||||||
window.onscroll = function() {
|
|
||||||
var scrolled = window.pageYOffset || document.documentElement.scrollTop;
|
|
||||||
document.getElementById('showScroll').innerHTML = scrolled + 'px';
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
В действии:
|
|
||||||
Текущая прокрутка = <b id="showScroll">прокрутите окно</b>
|
|
||||||
|
|
||||||
Каких-либо особенностей события здесь нет, разве что для его использования нужно отлично представлять, как получить текущее значение прокрутки или прокрутить документ. Об этом мы говорили ранее, в главе [](/metrics).
|
|
||||||
|
|
||||||
Событие `onscroll` используется достаточно часто для:
|
|
||||||
<ul>
|
|
||||||
<li>Подгрузки содержимого элементов, ставших видимыми после прокрутки.</li>
|
|
||||||
<li>Показа дополнительных элементов навигации, важных в текущем положении прокрутки.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
Вашему вниманию предлагаются несколько задач, которые вы можете решить сами или посмотреть использование `onscroll` на их примере.
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue