Javascript onload
Содержание:
- Пример: загрузка файла с индикатором прогресса
- Loading a script
- Example HTML code 2:
- Ошибка в скрипте с другого источника
- Обмен сообщениями между окнами
- DOM (Document Object Model)
- Полный синтаксис window.open
- Несколько обработчиков
- Синхронные запросы
- Атрибут ифрейма sandbox
- Блокировка попапов
- Событие onprogress в деталях
- Стадия скачивания
- readyState
- Код кроссбраузерной поддержки
- Итого
Пример: загрузка файла с индикатором прогресса
Современный XMLHttpRequest позволяет отправить на сервер всё, что вы пожелаете. Текст, файл, форму.
Мы, для примера, рассмотрим загрузку файла с индикацией прогресса. Это требует от браузера поддержки >File API.
File API позволяет получить доступ к содержимому файла, который перенесён в браузер при помощи Drag’n’Drop или выбран в поле формы, и отправить его при помощи XMLHttpRequest.
Форма для выбора файла с обработчиком submit:
<form name="upload"> <input type="file" name="myfile"> <input type="submit" value="Загрузить"> </form> <script> document.forms.upload.onsubmit = function() { var input = this.elements.myfile; var file = input.files; if (file) { upload(file); } return false; } </script>
Мы получаем файл из формы через свойство files элемента <input> и передаём его в функцию upload:
function upload(file) { var xhr1 = new XMLHttpRequest(); // обработчик для закачки xhr1.upload.onprogress = function(event) { log(event.loaded + ' / ' + event.total); } // обработчики успеха и ошибки // если status == 200, то это успех, иначе ошибка xhr1.onload = xhr1.onerror = function() { if (this.status == 200) { log("success"); } else { log("error " + this.status); } }; xhr1.open("POST", "upload", true); xhr1.send(file); }
Этот код отправит файл на сервер и будет сообщать о прогрессе при его закачке (xhr.upload.onprogress), а также об окончании запроса (xhr.onload, xhr.onerror).
Loading a script
Let’s say we need to load a third-party script and call a function that resides there.
We can load it dynamically, like this:
…But how to run the function that is declared inside that script? We need to wait until the script loads, and only then we can call it.
Please note:
For our own scripts we could use JavaScript modules here, but they are not widely adopted by third-party libraries.
The main helper is the event. It triggers after the script was loaded and executed.
For instance:
So in we can use script variables, run functions etc.
…And what if the loading failed? For instance, there’s no such script (error 404) or the server is down (unavailable).
Errors that occur during the loading of the script can be tracked in an event.
For instance, let’s request a script that doesn’t exist:
Please note that we can’t get HTTP error details here. We don’t know if it was an error 404 or 500 or something else. Just that the loading failed.
Important:
Events / track only the loading itself.
Errors that may occur during script processing and execution are out of scope for these events. That is: if a script loaded successfully, then triggers, even if it has programming errors in it. To track script errors, one can use global handler.
Example HTML code 2:
This example illustrates the use of the onload event for img elements:
<head><scripttype="text/javascript">// Internet Explorer specific function OnAbortImage () { var info = document.getElementById ("info"); info.innerHTML += "<br />The loading of the image has been aborted."; RemoveEsc (); } function OnLoadImage () { var info = document.getElementById ("info"); info.innerHTML += "<br />The image has been loaded."; RemoveEsc (); } // Internet Explorer specific function OnStateChangeImage (image) { var info = document.getElementById ("info"); info.innerHTML += "<br />readyState: " + image.readyState; } function RemoveEsc () { var esc = document.getElementById ("esc"); esc.parentNode.removeChild (esc); } </script></head><body><spanid="info"style="color:red">The image is loading.</span><br/><br/><spanid="esc">Press the Escape key to abort the process.</span><br/><br/><imgsrc="large.bmp"width="200px"height="150px"onabort="OnAbortImage ()"onload="OnLoadImage ()"onreadystatechange="OnStateChangeImage (this)"/></body> |
Did you find this example helpful? yes |
Ошибка в скрипте с другого источника
Есть правило: скрипты с одного сайта не могут получить доступ к содержимому другого сайта. Например, скрипт с не может прочитать почту пользователя на .
Или, если быть более точным, один источник (домен/порт/протокол) не может получить доступ к содержимому с другого источника. Даже поддомен или просто другой порт будут считаться разными источниками, не имеющими доступа друг к другу.
Это правило также касается ресурсов с других доменов.
Если мы используем скрипт с другого домена, и в нем имеется ошибка, мы не сможем узнать детали этой ошибки.
Для примера давайте возьмём мини-скрипт , который состоит из одного-единственного вызова функции, которой не существует:
// error.js noSuchFunction();
Теперь загрузим этот скрипт с того же сайта, на котором он лежит:
<script> window.onerror = function(message, url, line, col, errorObj) { alert(`${message}\n${url}, ${line}:${col}`); }; </script> <script src="/article/onload-onerror/crossorigin/error.js"></script>
Мы видим нормальный отчёт об ошибке:
А теперь загрузим этот же скрипт с другого домена:
<script> window.onerror = function(message, url, line, col, errorObj) { alert(`${message}\n${url}, ${line}:${col}`); }; </script> <script src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>
Отчёт отличается:
Детали отчёта могут варьироваться в зависимости от браузера, но основная идея остаётся неизменной: любая информация о внутреннем устройстве скрипта, включая стек ошибки, спрятана. Именно потому, что скрипт загружен с другого домена.
Зачем нам могут быть нужны детали ошибки?
Существует много сервисов (и мы можем сделать наш собственный), которые обрабатывают глобальные ошибки при помощи , сохраняют отчёт о них и предоставляют доступ к этому отчёту для анализа. Это здорово, потому что мы можем увидеть реальные ошибки, которые случились у наших пользователей. Но если скрипт — с другого домена, то информации об ошибках в нём почти нет, как мы только что видели.
Похожая кросс-доменная политика (CORS) внедрена и в отношении других ресурсов.
Чтобы разрешить кросс-доменный доступ, нам нужно поставить тегу атрибут , и, кроме того, удалённый сервер должен поставить специальные заголовки.
Существует три уровня кросс-доменного доступа:
- Атрибут отсутствует — доступ запрещён.
- — доступ разрешён, если сервер отвечает с заголовком со значениями или наш домен. Браузер не отправляет авторизационную информацию и куки на удалённый сервер.
- — доступ разрешён, если сервер отвечает с заголовками со значением наш домен и . Браузер отправляет авторизационную информацию и куки на удалённый сервер.
В нашем случае атрибут отсутствовал. Поэтому кросс-доменный доступ был запрещён. Давайте добавим его.
Мы можем выбрать (куки не отправляются, требуется один серверный заголовок) или (куки отправляются, требуются два серверных заголовка) в качестве значения атрибута.
Если куки нас не волнуют, тогда смело выбираем :
<script> window.onerror = function(message, url, line, col, errorObj) { alert(`${message}\n${url}, ${line}:${col}`); }; </script> <script *!*crossorigin="anonymous"*/!* src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>
Теперь при условии, что сервер предоставил заголовок , всё хорошо. У нас есть полный отчёт по ошибкам.
Обмен сообщениями между окнами
Интерфейс позволяет окнам общаться между собой независимо от их происхождения.
Это способ обойти политику «Одинакового источника». Он позволяет обмениваться информацией, скажем и , но только в том случае, если оба сайта согласны и вызывают соответствующие JavaScript-функции. Это делает общение безопасным для пользователя.
Интерфейс имеет две части.
Окно, которое хочет отправить сообщение, должно вызвать метод postMessage окна получателя. Другими словами, если мы хотим отправить сообщение в окно , тогда нам следует вызвать .
Аргументы:
- Данные для отправки. Может быть любым объектом, данные клонируются с использованием «алгоритма структурированного клонирования». IE поддерживает только строки, поэтому мы должны использовать метод на сложных объектах, чтобы поддержать этот браузер.
- Определяет источник для окна-получателя, только окно с данного источника имеет право получить сообщение.
Указание является мерой безопасности. Как мы помним, если окно (получатель) происходит из другого источника, мы из окна-отправителя не можем прочитать его . Таким образом, мы не можем быть уверены, какой сайт открыт в заданном окне прямо сейчас: пользователь мог перейти куда-то, окно-отправитель не может это знать.
Если указать , то мы можем быть уверены, что окно получит данные только в том случае, если в нём правильный сайт
Особенно это важно, если данные конфиденциальные
Например, здесь получит сообщения только в том случае, если в нём открыт документ из источника :
Если мы не хотим проверять, то в можно указать .
Чтобы получать сообщения, окно-получатель должно иметь обработчик события (сообщение). Оно срабатывает, когда был вызван метод (и проверка пройдена успешно).
Объект события имеет специфичные свойства:
- Данные из .
- Источник отправителя, например, .
- Ссылка на окно-отправитель. Можно сразу отправить что-то в ответ, вызвав .
Чтобы добавить обработчик, следует использовать метод , короткий синтаксис не работает.
Вот пример:
Полный пример:
Результат
iframe.html
index.html
Без задержек
Между и событием не существует задержки. Событие происходит синхронно, быстрее, чем .
DOM (Document Object Model)
Document Object Model, сокращённо DOM – объектная модель документа, которая представляет все содержимое страницы в виде объектов, которые можно менять.
Объект – основная «входная точка». С его помощью мы можем что-то создавать или менять на странице.
Например:
Мы использовали в примере только , но на самом деле возможности по управлению страницей намного шире. Различные свойства и методы описаны в спецификации:
DOM Living Standard на https://dom.spec.whatwg.org
DOM – не только для браузеров
Спецификация DOM описывает структуру документа и предоставляет объекты для манипуляций со страницей. Существует и другие, отличные от браузеров, инструменты, использующие DOM.
Например, серверные скрипты, которые загружают и обрабатывают HTML-страницы, также могут использовать DOM. При этом они могут поддерживать спецификацию не полностью.
CSSOM для стилей
Правила стилей CSS структурированы иначе чем HTML. Для них есть отдельная спецификация CSSOM, которая объясняет, как стили должны представляться в виде объектов, как их читать и писать.
CSSOM используется вместе с DOM при изменении стилей документа. В реальности CSSOM требуется редко, обычно правила CSS статичны. Мы редко добавляем/удаляем стили из JavaScript, но и это возможно.
Полный синтаксис window.open
Полный синтаксис:
Функция возвращает ссылку на объект нового окна, либо , если окно было заблокировано браузером.
Параметры:
- URL для загрузки в новое окно.
- Имя нового окна. Может быть использовано в параметре в формах. Если позднее вызвать с тем же именем, то браузеры (кроме IE) заменяют существующее окно на новое.
- Строка с конфигурацией для нового окна. Состоит из параметров, перечисленных через запятую. Пробелов в ней быть не должно.
Значения параметров .
- Настройки расположения окна:
- (число)
-
Координаты верхнего левого угла относительно экрана. Ограничение: новое окно не может быть позиционировано за пределами экрана.
- (число)
-
Ширина/высота нового окна. Минимальные значения ограничены, так что невозможно создать невидимое окно с нулевыми размерами.
Если координаты и размеры не указаны, то обычно браузер открывает не окно, а новую вкладку.
- Свойства окна:
- (yes/no)
- Скрыть или показать строку меню браузера.
- (yes/no)
- Показать или скрыть панель навигации браузера (кнопки назад, вперёд, обновить страницу и остальные) в новом окне.
- (yes/no)
- Показать/скрыть поле URL-адреса в новом окне. По умолчанию Firefox и IE не позволяют скрывать строку адреса.
- (yes/no)
- Показать или скрыть строку состояния. С другой стороны, браузер может в принудительном порядке показать строку состояния.
- (yes/no)
- Позволяет отключить возможность изменять размеры нового окна. Значение обычно неудобно посетителям.
- (yes/no)
- Разрешает убрать полосы прокрутки для нового окна. Значение обычно неудобно посетителям.
- Ещё есть небольшое количество не кросс-браузерных свойств, которые обычно не используются. Вы можете узнать о них в документации, например MDN: window.open.
Важно:
Браузер подходит к этим параметрам интеллектуально. Он может проигнорировать их часть или даже все, они скорее являются «пожеланиями», нежели «требованиями».
Важные моменты:
- Если при вызове указан только первый параметр, параметр отсутствует, то используются параметры по умолчанию. Обычно при этом будет открыто не окно, а вкладка, что зачастую более удобно.
- Если указана строка с параметрами, но некоторые параметры отсутствуют, то браузер выставляет их в . Поэтому убедитесь, что все нужные вам параметры выставлены в .
- Когда не указан , то браузер откроет окно с небольшим смещением относительно левого верхнего угла последнего открытого окна.
- Если не указаны , новое окно будет такого же размера, как последнее открытое.
Несколько обработчиков
Код из примера выше позволяет навешивать только один обработчик. Для поддержки нескольких — добавим дополнительную обертку:
readyList = [] function onReady(handler) { if (!readyList.length) { bindReady(function() { for(var i=0; i<readyList.length; i++) { readyList() } }) } readyList.push(handler) }
Функция при первом вызове вешает обработчик , который запускает все функции из списка , а в дальнейшем просто добавляет новый обработчик в этот список.
Следующий пример демонстрирует использование :
<html> <head> <script src="bindReady.js"></script> <script src="onReady.js"></script> <script> onReady(function() { var divs = document.body.getElementsByTagName('div') alert(divs.innerHTML) }) </script> <link rel="stylesheet" href="my.css" type="text/css"> </head> <body> <img src="img5.php"/> <div>done</div> </body> </html>
Обработчик выводит содержимое последнего тэга , так что мы видим, что документ действительно загружен и разобран.
Картинка загружается скриптом, который ждет 5 секунд. Это сделано для демонстрации, что вызывается до полной загрузки.
Синхронные запросы
Если в методе третий параметр установлен на , запрос выполняется синхронно.
Другими словами, выполнение JavaScript останавливается на и возобновляется после получения ответа. Так ведут себя, например, функции или .
Вот переписанный пример с параметром , равным :
Выглядит, может быть, и неплохо, но синхронные запросы используются редко, так как они блокируют выполнение JavaScript до тех пор, пока загрузка не завершена. В некоторых браузерах нельзя прокручивать страницу, пока идёт синхронный запрос. Ну а если же синхронный запрос по какой-то причине выполняется слишком долго, браузер предложит закрыть «зависшую» страницу.
Многие продвинутые возможности , такие как выполнение запроса на другой домен или установка таймаута, недоступны для синхронных запросов. Также, как вы могли заметить, ни о какой индикации прогресса речь тут не идёт.
Из-за всего этого синхронные запросы используют очень редко. Мы более не будем рассматривать их.
Атрибут ифрейма sandbox
Атрибут позволяет наложить ограничения на действия внутри , чтобы предотвратить выполнение ненадёжного кода. Атрибут помещает ифрейм в «песочницу», отмечая его как имеющий другой источник и/или накладывая на него дополнительные ограничения.
Существует список «по умолчанию» ограничений, которые накладываются на . Их можно уменьшить, если указать в атрибуте список исключений (специальными ключевыми словами), которые не нужно применять, например: .
Другими словами, если у атрибута нет значения, то браузер применяет максимум ограничений, но через пробел можно указать те из них, которые мы не хотим применять.
Вот список ограничений:
- принудительно устанавливает «другой источник» для ифрейма. Другими словами, он заставляет браузер воспринимать , как пришедший из другого источника, даже если содержит тот же сайт. Со всеми сопутствующими ограничениями для скриптов. Эта опция отключает это ограничение.
- Позволяет ифрейму менять .
- Позволяет отправлять формы из ифрейма.
- Позволяет запускать скрипты из ифрейма.
- Позволяет открывать всплывающие окна из ифрейма с помощью .
Больше опций можно найти в справочнике.
Пример ниже демонстрирует ифрейм, помещённый в песочницу со стандартным набором ограничений: . На странице содержится JavaScript и форма.
Обратите внимание, что ничего не работает. Таким образом, набор ограничений по умолчанию очень строгий:. Результат
index.html
sandboxed.html
Результат
index.html
sandboxed.html
Атрибут создан только для того, чтобы добавлять ограничения. Он не может удалять их. В частности, он не может ослабить ограничения, накладываемые браузером на ифрейм, приходящий с другого источника.
Блокировка попапов
В прошлом злонамеренные сайты заваливали посетителей всплывающими окнами. Такие страницы могли открывать сотни попапов с рекламой. Поэтому теперь большинство браузеров пытаются заблокировать всплывающие окна, чтобы защитить пользователя.
Всплывающее окно блокируется в том случае, если вызов window.open произошёл не в результате действия посетителя (например, события ).
Например:
Таким образом браузеры могут защитить пользователя от появления нежелательных попапов, при этом не отключая попапы полностью.
Что, если попап должен открываться в результате , но не сразу, а только после выполнения ? Здесь все не так-то просто.
Запустим код:
Попап откроется в Chrome, но будет заблокирован в Firefox.
Но если мы уменьшим тайм-аут до одной секунды, то попап откроется и в Firefox:
Мы получили два разных результата из-за того, что Firefox «допускает» таймаут в 2000 мс или менее, но все, что свыше этого – не вызывает его доверия, т.к. предполагается, что в таком случае открытие окна происходит без ведома пользователя. Именно поэтому попап из первого примера будет заблокирован, а из второго – нет.
Событие onprogress в деталях
При обработке события есть ряд важных тонкостей.
Можно, конечно, их игнорировать, но лучше бы знать.
Заметим, что событие, возникающее при , имеет одинаковый вид на стадии отправки (в обработчике ) и при получении ответа (в обработчике ).
Оно представляет собой объект типа со свойствами:
-
Сколько байт уже переслано.
Имеется в виду только тело запроса, заголовки не учитываются.
-
Если , то известно полное количество байт для пересылки, и оно хранится в свойстве .
-
Общее количество байт для пересылки, если известно.
А может ли оно быть неизвестно?
- При отправке на сервер браузер всегда знает полный размер пересылаемых данных, так что всегда содержит конкретное количество байт, а значение всегда будет .
- При скачивании данных – обычно сервер в начале сообщает их общее количество в HTTP-заголовке . Но он может и не делать этого, например если сам не знает, сколько данных будет или если генерирует их динамически. Тогда будет равно . А чтобы отличить нулевой размер данных от неизвестного – как раз служит , которое в данном случае равно .
Ещё особенности, которые необходимо учитывать при использовании :
Событие происходит при каждом полученном/отправленном байте, но не чаще чем раз в 50 мс.
Это обозначено в .
В процессе получения данных, ещё до их полной передачи, доступен , но он не обязательно содержит корректную строку.
Можно до окончания запроса заглянуть в него и прочитать текущие полученные данные
Важно, что при пересылке строки в кодировке UTF-8 кириллические символы, как, впрочем, и многие другие, кодируются 2 байтами. Возможно, что в конце одного пакета данных окажется первая половинка символа, а в начале следующего – вторая
Поэтому полагаться на то, что до окончания запроса в находится корректная строка нельзя. Она может быть обрезана посередине символа.
Исключение – заведомо однобайтные символы, например цифры или латиница.
Сработавшее событие не гарантирует, что данные дошли.
Событие срабатывает, когда данные отправлены браузером. Но оно не гарантирует, что сервер получил, обработал и записал данные на диск. Он говорит лишь о самом факте отправки.
Поэтому прогресс-индикатор, получаемый при его помощи, носит приблизительный и оптимистичный характер.
Стадия скачивания
После того, как загрузка завершена, и сервер соизволит ответить на запрос, XMLHttpRequest инициирует скачивание ответа сервера.
На этой фазе xhr.upload уже не нужен, а в дело вступают обработчики событий на самом объекте xhr. В частности, событие xhr.onprogress, которое содержит информацию о количестве принятых байт ответа.
Пример обработчика:
xhr.onprogress = function(event) { alert( 'Получено с сервера ' + event.loaded + ' байт из ' + event.total ); }
Все события, возникающие в этих обработчиках, имеют тип ProgressEvent, то есть имеют свойства loaded – количество уже пересланных данных в байтах и total – общее количество данных.
readyState
В заключение
занятия отметим свойство
document.readyState
которое в момент
загрузки HTML-документа принимает
следующие значения:
-
«loading»
– документ в процессе загрузки; -
«interactive»
– документ был полностью прочитан (парсинг документа завершен); -
«complete»
– документ был полностью прочитан и все ресурсы (изображения, стили и т.п.)
тоже загружены.
В ряде случаев
это свойство бывает весьма полезно. Например, мы вызываем функцию, но не
уверены, что DOM-дерево
полностью построено. Поэтому, делаем такую проверку:
removeImage(); function removeImage() { if(document.readyState == "loading") { console.log("документ грузится, вешаем обработчик"); document.addEventListener("DOMContentLoaded", removeImage); } else { console.log("удаляем изображение"); document.body.remove(image); } }
По аналогии
могут быть обработаны и остальные свойства.
Для полноты картины
пару слов о событии readystatechange, которое появилось до событий
DOMContentLoaded, load, unload, beforeunload
и в старых версиях
JavaScript процесс
загрузки документа контролировался через него. Например, так:
document.addEventListener('readystatechange', function() { console.log(document.readyState); });
Теперь при
обновлении страницы мы можем увидеть изменение состояний свойства document.readyState в процессе
загрузки. Однако такой механизм отслеживания ушел в прошлое и сейчас уже нет смысла
о нем подробно говорить.
Итак, на этом
занятии мы с вами рассмотрели события
DOMContentLoaded,
load, unload, beforeunload
и поговорили о свойстве
document.readyState
которое
дополняет работу с этими событиями.
Видео по теме
JavaScipt (DOM) #1: объектная модель документа DOM и BOM
JavaScipt (DOM) #2: навигация по DOM — parentNode, nextSibling, previousSibling, chidNodes
JavaScipt (DOM) #3: методы поиска элементов в DOM: querySelector, querySelectorAll, getElementById
JavaScipt (DOM) #4: свойства DOM-узлов: nodeName, innerHTML, outerHTML, data, textContent, hidden
JavaScipt (DOM) #5: работа с нестандартными свойствами DOM-элементов: getAttribute, setAttribute, dataset
JavaScipt (DOM) #6: создание и добавление элементов DOM createElement, append, remove, insertAdjacentHTML
JavaScipt (DOM) #7: управление стилями — className, style, classList, getComputedStyle
JavaScipt (DOM) #8: метрики — clientWidth, scrollTop, scrollHeight, offsetLeft, offsetTop, clientLeft
JavaScipt (DOM) #9: HTML-документ: размеры (clientWidth, innerWidth), положение (pageYOffset, scrollBy)
JavaScipt (DOM) #10: расположение элементов — fixed, absolute, getBoundingClientRect, elementFromPoint
JavaScipt (DOM) #11: обработчики событий: onclick, addEventListener, removeEventListener, event
JavaScipt (DOM) #12: погружение и всплытие событий: stopPropagation, stopImmediatePropagation, eventPhase
JavaScipt (DOM) #13: делегирование событий, отмена действия браузера по умолчанию — preventDefault
JavaScipt (DOM) #14: события мыши mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter
JavaScipt (DOM) #15: события клавиатуры keydown, keyup, событие скроллинга scroll
JavaScipt (DOM) #16: навигация и обработка элементов форм (form) — document.forms, form.elements
JavaScipt (DOM) #17: фокусировка — focus, blur, focusin, focusout, tabindex, activeElement
JavaScipt (DOM) #18: события change, input, cut, copy, paste, submit элементов input и select
JavaScipt (DOM) #19: события при загрузке — DOMContentLoaded, load, unload, beforeunload, readyState
JavaScipt (DOM) #20: события load, error; атрибуты async, defer тега script
JavaScipt (DOM) #21: пример предзагрузки изображений с помощью javascript
JavaScipt (DOM) #22: пример создания начала игры арканоид
Код кроссбраузерной поддержки
«Родное» событие есть не во всех браузерах, поэтому мы рассмотрим код для кроссбраузерной поддержки этого события:
function bindReady(handler){ var called = false function ready() { // (1) if (called) return called = true handler() } if ( document.addEventListener ) { // (2) document.addEventListener( "DOMContentLoaded", function(){ ready() }, false ) } else if ( document.attachEvent ) { // (3) // (3.1) if ( document.documentElement.doScroll && window == window.top ) { function tryScroll(){ if (called) return if (!document.body) return try { document.documentElement.doScroll("left") ready() } catch(e) { setTimeout(tryScroll, 0) } } tryScroll() } // (3.2) document.attachEvent("onreadystatechange", function(){ if ( document.readyState === "complete" ) { ready() } }) } // (4) if (window.addEventListener) window.addEventListener('load', ready, false) else if (window.attachEvent) window.attachEvent('onload', ready) /* else // (4.1) window.onload=ready */ }
Разберем его по шагам.
- Код будет пытаться поймать событие различными способами. Вполне может получиться так, что несколько способов сработают независимо.
Поэтому завернем обработчик в функцию , единственный смысл которой — гарантировать, что будет вызван не более одного раза.
- Событие поддерживают достаточно новые Firefox, Opera, Safari/Chrome. Нет гарантии, что версия посетителя поддерживает это событие, но попробовать стоит.
- Браузер Internet Explorer не поддерживает , поэтому для него используются обходные пути.
- Функция пытается скроллить документ вызовом . Если получается — значит, документ загрузился, если нет — заказывает повторную попытку через setTimeout, и так пока документ наконец не будет готов. На практике это очень надежный способ, но есть проблемы с фреймами, поэтому используется только для окон верхнего уровня.
Дополнительный фильтр — проверка - Событие с проверкой , как и , срабатывает после загрузки документа. Но, к сожалению, оно происходит уже после загрузки картинок. Поэтому — вообще говоря, не то, что нам надо. Но это событие работает для фреймов, и при этом срабатывает до . Поэтому будем использовать и этот способ.
- Функция пытается скроллить документ вызовом . Если получается — значит, документ загрузился, если нет — заказывает повторную попытку через setTimeout, и так пока документ наконец не будет готов. На практике это очень надежный способ, но есть проблемы с фреймами, поэтому используется только для окон верхнего уровня.
- Для тех браузеров, в которых не сработали предыдущие методы (например, очень старый Firefox), добавим вызов обработчика при событии .
- Для совсем древних браузеров, в которых нет , вы можете раскомментировать и строчку (4.1). При этом, разумеется, возможен конфликт с другими обработчиками .
Этот код взят, с небольшими упрощениями, из библиотеки jQuery, а методы придуманы различными авторами.
Итого
Говоря о стандартах, у нас есть:
- Спецификация DOM
- описывает структуру документа, манипуляции с контентом и события, подробнее на https://dom.spec.whatwg.org.
- Спецификация CSSOM
- Описывает файлы стилей, правила написания стилей и манипуляций с ними, а также то, как это всё связано со страницей, подробнее на https://www.w3.org/TR/cssom-1/.
- Спецификация HTML
- Описывает язык HTML (например, теги) и BOM (объектную модель браузера) – разные функции браузера: , , и так далее, подробнее на https://html.spec.whatwg.org. Тут берётся за основу спецификация DOM и расширяется дополнительными свойствами и методами.
Кроме того, некоторые классы описаны отдельно на https://spec.whatwg.org/.
Пожалуйста, заметьте для себя эти ссылки, так как по ним содержится очень много информации, которую невозможно изучить полностью и держать в уме.
Когда вам нужно будет прочитать о каком-то свойстве или методе, справочник на сайте Mozilla https://developer.mozilla.org/ru/search тоже очень хороший ресурс, хотя ничто не сравнится с чтением спецификации: она сложная и объёмная, но сделает ваши знания максимально полными.
Для поиска чего-либо обычно удобно использовать интернет-поиск со словами «WHATWG » или «MDN », например https://google.com?q=whatwg+localstorage, https://google.com?q=mdn+localstorage.
А теперь давайте перейдём к изучению DOM, так как страница – это основа всего.