up
This commit is contained in:
parent
4bca225593
commit
547854a151
1655 changed files with 847 additions and 89231 deletions
|
@ -1,8 +0,0 @@
|
|||
# Подсказка
|
||||
|
||||
Текст на странице пусть будет изначально `DIV`, с классом `img-replace` и атрибутом `data-src` для картинки.
|
||||
|
||||
Функция `replaceImg()` должна искать такие `DIV` и загружать изображение с указанным `src`. По `onload` осуществляется замена `DIV` на картинку.
|
||||
|
||||
# Решение
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.img-replace {
|
||||
float: left;
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<button onclick="window.location.reload(true)">Перезагрузить ифрейм</button>
|
||||
<hr>
|
||||
<div style="width:114px;height:40px;font-size:32px;letter-spacing:3px" data-src="https://js.cx/search/google.png" class="img-replace">
|
||||
<span style="color:#1A53F7">G</span><span style="color:#E42131">o</span><span style="color:#FEB819">o</span><span style="color:#164AF2">g</span><span style="color:#00a315">l</span><span style="color:#E42131">e</span>
|
||||
</div>
|
||||
|
||||
<div style="width:101px;height:40px;font-size:32px" data-src="https://js.cx/search/yandex.png" class="img-replace">
|
||||
<span style="color:#F00">Я</span>ндекс
|
||||
</div>
|
||||
|
||||
<div style="width:100;height:40px;font-size:32px;color:#006dd4;font-weight:bold;letter-spacing:3px;font-family:Arial" data-src="bing.png" class="img-replace">bing</div>
|
||||
|
||||
|
||||
<script>
|
||||
function replaceImg() {
|
||||
var divs = document.querySelectorAll('div.img-replace');
|
||||
for (var i = 0; i < divs.length; i++)(function(i) {
|
||||
var img = document.createElement('img');
|
||||
img.src = divs[i].getAttribute('data-src');
|
||||
img.className = 'img-replace';
|
||||
|
||||
img.onload = function() {
|
||||
divs[i].parentNode.replaceChild(img, divs[i]);
|
||||
}
|
||||
|
||||
}(i))
|
||||
}
|
||||
|
||||
setTimeout(replaceImg, 1000); // задержка на 1 сек для демонстрации
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,40 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.img-replace {
|
||||
float: left;
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- Google -->
|
||||
|
||||
<div style="width:114px;height:40px;font-size:32px;letter-spacing:3px" class="img-replace">
|
||||
<span style="color:#1A53F7">G</span><span style="color:#E42131">o</span><span style="color:#FEB819">o</span><span style="color:#164AF2">g</span><span style="color:#00a315">l</span><span style="color:#E42131">e</span>
|
||||
</div>
|
||||
|
||||
<!-- Яндекс -->
|
||||
<div style="width:101px;height:40px;font-size:32px" class="img-replace">
|
||||
<span style="color:#F00">Я</span>ндекс
|
||||
</div>
|
||||
|
||||
<!-- Bing -->
|
||||
<div style="width:100;height:40px;font-size:32px;color:#006dd4;font-weight:bold;letter-spacing: 3px; font-family:Arial">bing</div>
|
||||
|
||||
<hr>
|
||||
<!-- картинки (для bing картинки специально нет, чтобы протестировать случай "загрузка не удалась") -->
|
||||
|
||||
<img src="https://js.cx/search/yandex.png" width="114" height="40" alt="Яндекс">
|
||||
<img src="https://js.cx/search/google.png" width="101" height="40" alt="Google">
|
||||
<img src="https://js.cx/search/bing.png" width="101" height="40" alt="Файла нет (bing)">
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,17 +0,0 @@
|
|||
# Красивый "ALT"
|
||||
|
||||
[importance 5]
|
||||
|
||||
Обычно, до того как изображение загрузится (или при отключенных картинках), посетитель видит пустое место с текстом из "ALT". Но этот атрибут не допускает HTML-форматирования.
|
||||
|
||||
При мобильном доступе скорость небольшая, и хочется, чтобы посетитель сразу видел красивый текст.
|
||||
|
||||
**Реализуйте "красивый" (HTML) аналог `alt` при помощи CSS/JavaScript, который затем будет заменён картинкой сразу же как только она загрузится.** А если загрузка не состоится -- то не заменён.
|
||||
|
||||
Демо: (нажмите "перезагрузить", чтобы увидеть процесс загрузки и замены)
|
||||
[iframe src="solution" height="100"]
|
||||
|
||||
Картинки для `bing` специально нет, так что текст остается "как есть".
|
||||
|
||||
Исходный документ содержит разметку текста и ссылки на изображения.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# Подсказка
|
||||
|
||||
Создайте переменную-счетчик для подсчёта количества загруженных картинок, и увеличивайте при каждом `onload/onerror`.
|
||||
|
||||
Когда счетчик станет равен количеству картинок -- вызывайте `callback`.
|
||||
|
||||
# Решение
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function preloadImages(sources, callback) {
|
||||
var counter = 0;
|
||||
|
||||
function onLoad() {
|
||||
counter++;
|
||||
if (counter == sources.length) callback();
|
||||
}
|
||||
|
||||
for (var i = 0; i < sources.length; i++) {
|
||||
var img = document.createElement('img');
|
||||
// сначала onload/onerror, затем src - важно для IE8-
|
||||
img.onload = img.onerror = onLoad;
|
||||
img.src = sources[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ---------- Проверка ----------
|
||||
|
||||
var sources = [
|
||||
"https://js.cx/images-load/1.jpg",
|
||||
"https://js.cx/images-load/2.jpg",
|
||||
"https://js.cx/images-load/3.jpg"
|
||||
];
|
||||
for (var i = 0; i < sources.length; i++) {
|
||||
sources[i] += '?' + Math.random();
|
||||
}
|
||||
|
||||
function testLoaded() {
|
||||
var widthSum = 0;
|
||||
for (var i = 0; i < sources.length; i++) {
|
||||
var img = document.createElement('img');
|
||||
img.src = sources[i];
|
||||
widthSum += img.width;
|
||||
}
|
||||
alert(widthSum); // 300!
|
||||
}
|
||||
|
||||
// до загрузки - 0
|
||||
testLoaded();
|
||||
// после загрузки - 300
|
||||
preloadImages(sources, testLoaded);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,50 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function preloadImages(sources, callback) {
|
||||
/* ваш код */
|
||||
}
|
||||
|
||||
// ---------- Проверка ----------
|
||||
|
||||
/* файлы для загрузки */
|
||||
var sources = [
|
||||
"https://js.cx/images-load/1.jpg",
|
||||
"https://js.cx/images-load/2.jpg",
|
||||
"https://js.cx/images-load/3.jpg"
|
||||
];
|
||||
for (var i = 0; i < sources.length; i++) {
|
||||
sources[i] += '?' + Math.random(); // добавляем параметр, чтобы без кеша (для теста)
|
||||
}
|
||||
|
||||
/** если картинка загружена, то можно будет сразу получить её ширину
|
||||
* создадим все картинки и проверим, есть ли у них ширина
|
||||
*/
|
||||
function testLoaded() {
|
||||
var widthSum = 0;
|
||||
for (var i = 0; i < sources.length; i++) {
|
||||
var img = document.createElement('img');
|
||||
img.src = sources[i];
|
||||
widthSum += img.width;
|
||||
}
|
||||
// каждое изображение 100x100, общая ширина должна быть 300px
|
||||
alert(widthSum);
|
||||
}
|
||||
|
||||
// до загрузки - выведет 0
|
||||
testLoaded();
|
||||
|
||||
// после загрузки - выведет 300
|
||||
preloadImages(sources, testLoaded);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,23 +0,0 @@
|
|||
# Загрузить изображения с коллбэком
|
||||
|
||||
[importance 4]
|
||||
|
||||
Создайте функцию `preloadImages(sources, callback)`, которая предзагружает изображения из массива `sources`, и после загрузки вызывает функцию `callback`.
|
||||
|
||||
Пример использования:
|
||||
|
||||
```js
|
||||
addScripts(["1.jpg", "2.jpg", "3.jpg"], callback);
|
||||
```
|
||||
|
||||
Если вдруг возникает ошибка при загрузке -- считаем такое изображение загруженным, чтобы не ломать поток выполнения.
|
||||
|
||||
Такая функция может полезна, например, для фоновой загрузки картинок в онлайн-галерею.
|
||||
|
||||
В исходном документе содержатся ссылки на картинки, а также код для проверки, действительно ли изображения загрузились. Он должен выводить "0", затем "300".
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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`.
|
||||
|
||||
# Решение
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
function go() {
|
||||
alert("ok");
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function addScript(src, callback) {
|
||||
var script = document.createElement('script');
|
||||
script.src = src;
|
||||
var s = document.getElementsByTagName('script')[0]
|
||||
s.parentNode.insertBefore(script, s);
|
||||
|
||||
var loaded = false;
|
||||
|
||||
function onload() {
|
||||
if (loaded) return; // повторный вызов
|
||||
loaded = true;
|
||||
callback();
|
||||
}
|
||||
|
||||
script.onload = onload; // все браузеры, IE с версии 9
|
||||
|
||||
script.onreadystatechange = function() { // IE8-
|
||||
if (this.readyState == 'loaded' || this.readyState == 'complete') {
|
||||
setTimeout(onload, 0);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
addScript("go.js", function() {
|
||||
go();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,3 +0,0 @@
|
|||
function go() {
|
||||
alert("ok");
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function addScript(src, callback) {
|
||||
/* ваш код */
|
||||
}
|
||||
|
||||
addScript("go.js", function() {
|
||||
go();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,19 +0,0 @@
|
|||
# Скрипт с коллбэком
|
||||
|
||||
[importance 4]
|
||||
|
||||
Создайте функцию `addScript(src, callback)`, которая загружает скрипт с данным `src`, и после его загрузки и выполнения вызывает функцию `callback`.
|
||||
|
||||
Скрипт может быть любым, работа функции не должна зависеть от его содержимого.
|
||||
|
||||
Пример использования:
|
||||
|
||||
```js
|
||||
// go.js содержит функцию go()
|
||||
addScript("go.js", function() {
|
||||
go();
|
||||
});
|
||||
```
|
||||
|
||||
Ошибки загрузки обрабатывать не нужно.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# Подсказки
|
||||
|
||||
Создайте переменную-счетчик для подсчёта количества загруженных скриптов.
|
||||
|
||||
Чтобы один скрипт не учитывался два раза (например, `onreadystatechange` запустился при `loaded` и `complete`), учитывайте его состояние в объекте `loaded`. Свойство `loaded[i] = true` означает что `i`-й скрипт уже учтён.
|
||||
|
||||
# Решение
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
function a() {
|
||||
b();
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
function b() {
|
||||
c();
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
function c() {
|
||||
alert('ok');
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function addScript(src) {
|
||||
var script = document.createElement('script');
|
||||
script.src = src;
|
||||
var s = document.getElementsByTagName('script')[0]
|
||||
s.parentNode.insertBefore(script, s);
|
||||
return script;
|
||||
}
|
||||
|
||||
function addScripts(scripts, callback) {
|
||||
var loaded = {}; // Для загруженных файлов loaded[i] = true
|
||||
var counter = 0;
|
||||
|
||||
function onload(i) {
|
||||
if (loaded[i]) return; // лишний вызов onload/onreadystatechange
|
||||
loaded[i] = true;
|
||||
counter++;
|
||||
if (counter == scripts.length) callback();
|
||||
}
|
||||
|
||||
for (var i = 0; i < scripts.length; i++)(function(i) {
|
||||
var script = addScript(scripts[i]);
|
||||
|
||||
script.onload = function() {
|
||||
onload(i);
|
||||
};
|
||||
|
||||
script.onreadystatechange = function() { // IE8-
|
||||
if (this.readyState == 'loaded' || this.readyState == 'complete') {
|
||||
setTimeout(this.onload, 0); // возможны повторные вызовы onload
|
||||
}
|
||||
};
|
||||
|
||||
}(i));
|
||||
|
||||
}
|
||||
|
||||
addScripts(["a.js", "b.js", "c.js"], function() {
|
||||
a()
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,3 +0,0 @@
|
|||
function a() {
|
||||
b();
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
function b() {
|
||||
c();
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
function c() {
|
||||
alert('ok');
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
/* ваш код */
|
||||
|
||||
// функция a() сработает только если загружены a.js, b.js, c.js
|
||||
addScripts(["a.js", "b.js", "c.js"], function() {
|
||||
a()
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,24 +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 */
|
||||
```
|
||||
|
||||
<ul>
|
||||
<li>Ошибки загрузки обрабатывать не нужно.</li>
|
||||
<li>Один скрипт не ждёт другого. Они все загружаются, а по окончании вызывается обработчик `callback`.</li>
|
||||
|
||||
Исходный содержит скрипты `a.js`, `b.js`, `c.js`:
|
||||
|
||||
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
# Загрузка скриптов, картинок, фреймов: onload и onerror
|
||||
|
||||
Браузер позволяет отслеживать загрузку внешних ресурсов -- скриптов, ифреймов, картинок и других.
|
||||
|
||||
Для этого есть два события:
|
||||
<ul>
|
||||
<li>`onload` -- если загрузка успешна.</li>
|
||||
<li>`onerror` -- если при загрузке произошла ошибка.</li>
|
||||
</ul>
|
||||
|
||||
## Загрузка SCRIPT
|
||||
|
||||
Рассмотрим следующую задачу.
|
||||
|
||||
В браузере работает сложный интерфейс и, чтобы создать очередной компонент, нужно загрузить скрипт с сервера.
|
||||
|
||||
Подгрузить внешний скрипт -- достаточно просто:
|
||||
|
||||
```js
|
||||
var script = document.createElement('script');
|
||||
script.src = "my.js";
|
||||
|
||||
document.body.appendChild(script);
|
||||
```
|
||||
|
||||
...Но как после подгрузки выполнить функцию, которая объявлена в этом скрипте? Для этого нужно отловить момент окончания загрузки и выполнения тега `<script>`.
|
||||
|
||||
### script.onload
|
||||
|
||||
Главным помощником станет событие `onload`. Оно сработает, когда скрипт загрузился и выполнился.
|
||||
|
||||
Например:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var script = document.createElement('script');
|
||||
script.src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js"
|
||||
document.body.appendChild(script);
|
||||
|
||||
*!*
|
||||
script.onload = function() {
|
||||
// после выполнения скрипта становится доступна функция _
|
||||
alert( _ ); // её код
|
||||
}
|
||||
*/!*
|
||||
```
|
||||
|
||||
Это даёт возможность, как в примере выше, получить переменные из скрипта и выполнять объявленные в нём функции.
|
||||
|
||||
...А что, если загрузка скрипта не удалась? Например, такого скрипта на сервере нет (ошибка 404) или сервер "упал" (ошибка 500).
|
||||
|
||||
Такую ситуацию тоже нужно как-то обрабатывать, хотя бы сообщить посетителю о возникшей проблеме.
|
||||
|
||||
### script.onerror
|
||||
|
||||
Любые ошибки загрузки (но не выполнения) скрипта отслеживаются обработчиком `onerror`.
|
||||
|
||||
Например, сделаем запрос заведомо отсутствующего скрипта:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var script = document.createElement('script');
|
||||
script.src = "https://example.com/404.js"
|
||||
document.body.appendChild(script);
|
||||
|
||||
*!*
|
||||
script.onerror = function() {
|
||||
alert( "Ошибка: " + this.src );
|
||||
};
|
||||
*/!*
|
||||
```
|
||||
|
||||
### IE8-: script.onreadystatechange [#onreadystatechange]
|
||||
|
||||
Примеры выше работают во всех браузерах, кроме IE8-.
|
||||
|
||||
В IE для отслеживания загрузки есть другое событие: `onreadystatechange`. Оно срабатывает многократно, при каждом обновлении состояния загрузки.
|
||||
|
||||
Текущая стадия процесса находится в `script.readyState`:
|
||||
<dl>
|
||||
<dt>`loading`</dt>
|
||||
<dd>В процессе загрузки.</dd>
|
||||
<dt>`loaded`</dt>
|
||||
<dd>Получен ответ с сервера -- скрипт или ошибка. Скрипт на фазе `loaded` может быть ещё не выполнен.</dd>
|
||||
<dt>`complete`</dt>
|
||||
<dd>Скрипт выполнен.</dd>
|
||||
</dl>
|
||||
|
||||
Например, рабочий скрипт:
|
||||
|
||||
```js
|
||||
//+ run no-beautify
|
||||
var script = document.createElement('script');
|
||||
script.src = "https://code.jquery.com/jquery.js";
|
||||
document.documentElement.appendChild(script);
|
||||
|
||||
*!*
|
||||
script.onreadystatechange = function() {
|
||||
alert(this.readyState); // loading -> loaded -> complete
|
||||
}
|
||||
*/!*
|
||||
```
|
||||
|
||||
Скрипт с ошибкой:
|
||||
|
||||
```js
|
||||
//+ run no-beautify
|
||||
var script = document.createElement('script');
|
||||
script.src = "http://ajax.googleapis.com/404.js";
|
||||
document.documentElement.appendChild(script);
|
||||
|
||||
*!*
|
||||
script.onreadystatechange = function() {
|
||||
alert(this.readyState); // loading -> loaded
|
||||
}
|
||||
*/!*
|
||||
```
|
||||
|
||||
Обратим внимание на две особенности:
|
||||
<ul>
|
||||
<li>**Стадии могут пропускаться.**
|
||||
|
||||
Если скрипт в кэше браузера -- он сразу даст `complete`. Вы можете увидеть это, если несколько раз запустите первый пример.</li>
|
||||
<li>**Нет особой стадии для ошибки.**
|
||||
|
||||
В примере выше это видно, обработка останавливается на `loaded`.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Итак, самое надёжное средство для IE8- поймать загрузку (или ошибку загрузки) -- это повесить обработчик на событие `onreadystatechange`, который будет срабатывать и на стадии `complete` и на стадии `loaded`. Так как скрипт может быть ещё не выполнен к этому моменту, то вызов функции лучше сделать через `setTimeout(.., 0)`.
|
||||
|
||||
Пример ниже вызывает `afterLoad` после загрузки скрипта и работает только в IE:
|
||||
|
||||
```js
|
||||
//+ run no-beautify
|
||||
var script = document.createElement('script');
|
||||
script.src = "https://code.jquery.com/jquery.js";
|
||||
document.documentElement.appendChild(script);
|
||||
|
||||
function afterLoad() {
|
||||
alert("Загрузка завершена: " + typeof(jQuery));
|
||||
}
|
||||
|
||||
*!*
|
||||
script.onreadystatechange = function() {
|
||||
if (this.readyState == "complete") { // на случай пропуска loaded
|
||||
afterLoad(); // (2)
|
||||
}
|
||||
|
||||
if (this.readyState == "loaded") {
|
||||
setTimeout(afterLoad, 0); // (1)
|
||||
|
||||
// убираем обработчик, чтобы не сработал на complete
|
||||
this.onreadystatechange = null;
|
||||
}
|
||||
}
|
||||
*/!*
|
||||
```
|
||||
|
||||
Вызов `(1)` выполнится при первой загрузке скрипта, а `(2)` -- при второй, когда он уже будет в кеше, и стадия станет сразу `complete`.
|
||||
|
||||
Функция `afterLoad` может и не обнаружить `jQuery`, если при загрузке была ошибка, причём не важно какая -- файл не найден или синтаксис скрипта ошибочен.
|
||||
|
||||
### Кросс-браузерное решение
|
||||
|
||||
Для кросс-браузерной обработки загрузки скрипта или её ошибки поставим обработчик на все три события: `onload`, `onerror`, `onreadystatechange`.
|
||||
|
||||
Пример ниже выполняет функцию `afterLoad` после загрузки скрипта *или* при ошибке.
|
||||
|
||||
Работает во всех браузерах:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var script = document.createElement('script');
|
||||
script.src = "https://code.jquery.com/jquery.js";
|
||||
document.documentElement.appendChild(script);
|
||||
|
||||
function afterLoad() {
|
||||
alert( "Загрузка завершена: " + typeof(jQuery) );
|
||||
}
|
||||
|
||||
script.onload = script.onerror = function() {
|
||||
if (!this.executed) { // выполнится только один раз
|
||||
this.executed = true;
|
||||
afterLoad();
|
||||
}
|
||||
};
|
||||
|
||||
script.onreadystatechange = function() {
|
||||
var self = this;
|
||||
if (this.readyState == "complete" || this.readyState == "loaded") {
|
||||
setTimeout(function() {
|
||||
self.onload()
|
||||
}, 0); // сохранить "this" для onload
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Загрузка других ресурсов
|
||||
|
||||
Поддержка этих событий для других типов ресурсов различна:
|
||||
|
||||
<dl>
|
||||
<dt>`<img>`, `<link>` (стили)</dt>
|
||||
<dd>Поддерживает `onload/onerror` во всех браузерах.</dd>
|
||||
<dt>`<iframe>`</dt>
|
||||
<dd>Поддерживает `onload` во всех браузерах. Это событие срабатывает как при успешной загрузке, так и при ошибке.
|
||||
|
||||
Обратим внимание, что если `<iframe>` загружается с того же домена, то можно, используя `iframe.contentWindow.document` получить ссылку на документ и поставить обработчик `DOMContentLoaded`. А вот если `<iframe>` -- с другого домена, то так не получится, однако сработает `onload`.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
## Итого
|
||||
|
||||
В этой статье мы рассмотрели события `onload/onerror` для ресурсов.
|
||||
|
||||
Их можно обобщить, разделив на рецепты:
|
||||
|
||||
<dl>
|
||||
<dt>Отловить загрузку скрипта (включая ошибку)</dt>
|
||||
<dd>Ставим обработчики на `onload` + `onerror` + (для IE8-) `onreadystatechange`, как указано в рецепте выше</dd>
|
||||
<dt>Отловить загрузку картинки `<img>` или стиля `<link>`</dt>
|
||||
<dd>Ставим обработчики на `onload` + `onerror`
|
||||
|
||||
```js
|
||||
//+ no-beautify
|
||||
var img = document.createElement('img');
|
||||
img.onload = function() { alert("Успех "+this.src };
|
||||
img.onerror = function() { alert("Ошибка "+this.src };
|
||||
img.src = ...
|
||||
```
|
||||
|
||||
Изображения начинают загружаться сразу при создании, не нужно их для этого вставлять в HTML.
|
||||
|
||||
**Чтобы работало в IE8-, `src` нужно ставить *после* `onload/onerror`.**
|
||||
</dd>
|
||||
<dt>Отловить загрузку `<iframe>`</dt>
|
||||
<dd>Поддерживается только обработчик `onload`. Он сработает, когда `IFRAME` загрузится, со всеми подресурсами, а также в случае ошибки.
|
||||
</dd>
|
||||
</dl>
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue