0
Предотвратить выход со страницы
Функция-конструктор Unloader(), содержит в себе несколько «методов»: unload – срабатывает при закрытии окна или вкладки и показывает всплывающее окно с вопросом, текст которого хранится в переменой message. Правда, некоторые браузеры заменяют текст сообщения своим.resetUnload – предотвращает показ всплывающего окна при клике по ссылкам и отправке форм.init – «запускает» работу перечисленных методов после загрузки страницы. Вот, собственно, и весь скрипт. https://code.sololearn.com/W4n0bQ8kNiO7/?ref=app
15 ответов
+ 1
Очень важно чтобы в процессе оформления заказа в интернет-магазине посетитель случайно не закрыл страницу или не перешел на другую страницу. Существует JS-скрипт, который может предотвратить эти нежелательные действия. Например, он используется на Яндекс.Маркете. Смысл его работы заключается в том, что при попытке закрыть окно или вкладку браузера, появляется стандартное всплывающее окно с 2 кнопками «закрыть окно» и «остаться на странице». Правда в нем есть небольшой недостаток, он срабатывает не только на закрытие вкладки в окне браузера, но и при клике по ссылкам на странице, а также при отправке формы.
Обычно процесс оформления заказа происходит в несколько шагов, поэтому подтверждение своих действий на каждом шаге оформления заказа неуместно.
Благо, что существует усовершенствованный JS-скрипт, который срабатывает только на закрытие вкладок или окна. Его код я и приведу в этой заметке.
+ 1
Процесс загрузки HTML-документа, условно, состоит из трёх стадий:
DOMContentLoaded – браузер полностью загрузил HTML и построил DOM-дерево.load – браузер загрузил все ресурсы.beforeunload/unload – уход со страницы.
Все эти стадии очень важны. На каждую можно повесить обработчик, чтобы совершить полезные действия:
DOMContentLoaded – означает, что все DOM-элементы разметки уже созданы, можно их искать, вешать обработчики, создавать интерфейс, но при этом, возможно, ещё не догрузились какие-то картинки или стили.load – страница и все ресурсы загружены, используется редко, обычно нет нужды ждать этого момента.beforeunload/unload – можно проверить, сохранил ли посетитель изменения, уточнить, действительно ли он хочет покинуть страницу.
Далее мы рассмотрим важные детали этих событий.
+ 1
DOMContentLoaded
Событие DOMContentLoaded происходит на document и поддерживается во всех браузерах, кроме IE8-. Про поддержку аналогичного функционала в старых IE мы поговорим в конце главы.
Обработчик на него вешается только через addEventListener:
document.addEventListener("DOMContentLoaded", ready);
Пример:
<script> function ready() { alert( 'DOM готов' ); alert( "Размеры картинки: " + img.offsetWidth + "x" + img.offsetHeight ); } document.addEventListener("DOMContentLoaded", ready); </script> <img id="img" src="https://js.cx/clipart/yozhik.jpg?speed=1">
+ 1
В примере выше обработчик DOMContentLoadedсработает сразу после загрузки документа, не дожидаясь получения картинки.
Поэтому на момент вывода alert и сама картинка будет невидна и её размеры – неизвестны (кроме случая, когда картинка взята из кеша браузера).
В своей сути, событие onDOMContentLoaded – простое, как пробка. Полностью создано DOM-дерево – и вот событие. Но с ним связан ряд существенных тонкостей.
+ 1
DOMContentLoaded и скрипты
Если в документе есть теги <script>, то браузер обязан их выполнить до того, как построит DOM. Поэтому событие DOMContentLoaded ждёт загрузки и выполнения таких скриптов.
Исключением являются скрипты с атрибутами async и defer, которые подгружаются асинхронно.
Побочный эффект: если на странице подключается скрипт с внешнего ресурса (к примеру, реклама), и он тормозит, то событие DOMContentLoaded и связанные с ним действия могут сильно задержаться.
Современные системы рекламы используют атрибут async, либо вставляют скрипты через DOM: document.createElement('script')..., что работает так же как async: такой скрипт выполняется полностью независимо от страницы и от других скриптов – сам ничего не ждёт и ничего не блокирует.
+ 1
DOMContentLoaded и стили
Внешние стили никак не влияют на событие DOMContentLoaded. Но есть один нюанс.
Если после стиля идёт скрипт, то этот скрипт обязан дождаться, пока стиль загрузится:
<link type="text/css" rel="stylesheet" href="style.css"> <script> // сработает после загрузки style.css </script>
Такое поведение прописано в стандарте. Его причина – скрипт может захотеть получить информацию со страницы, зависящую от стилей, например, ширину элемента, и поэтому обязан дождаться загрузки style.css.
Побочный эффект – так как событие DOMContentLoaded будет ждать выполнения скрипта, то оно подождёт и загрузки стилей, которые идут перед <script>.
+ 1
Автозаполнение
Firefox/Chrome/Opera автозаполняют формы по DOMContentLoaded.
Это означает, что если на странице есть форма для ввода логина-пароля, то браузер введёт в неё запомненные значения только по DOMContentLoaded.
Побочный эффект: если DOMContentLoadedожидает множества скриптов и стилей, то автозаполнение не сработает до полной их загрузки.
Конечно, это довод в пользу того, чтобы не задерживать DOMContentLoaded, в частности – использовать у скриптов атрибуты async и defer.
+ 1
window.onload
Событие onload на window срабатывает, когда загружается вся страница, включая ресурсы на ней – стили, картинки, ифреймы и т.п.
Пример ниже выведет alert лишь после полной загрузки окна, включая IFRAME и картинку:
<script> window.onload = function() { alert( 'Документ и все ресурсы загружены' ); }; </script> <iframe src="https://example.com/" style="height:60px"></iframe> <img src="https://js.cx/clipart/yozhik.jpg?speed=1">
0
window.onunload
Когда человек уходит со страницы или закрывает окно, на window срабатывает событие unload. В нём можно сделать что-то, не требующее ожидания, например, закрыть вспомогательные popup-окна, но отменить сам переход нельзя.
Это позволяет другое событие – onbeforeunload, которое поэтому используется гораздо чаще.
0
window.onbeforeunload
Если посетитель инициировал переход на другую страницу или нажал «закрыть окно», то обработчик onbeforeunload может приостановить процесс и спросить подтверждение.
Для этого ему нужно вернуть строку, которую браузеры покажут посетителю, спрашивая – нужно ли переходить.
Например:
window.onbeforeunload = function() {
return "Данные не сохранены. Точно перейти?";
};
0
Firefox игнорирует текст, он показывает своё сообщение
Firefox игнорирует текст, а всегда показывает своё сообщение. Это сделано в целях большей безопасности посетителя, чтобы его нельзя было ввести в заблуждение сообщением.
Кликните на кнопку в IFRAME'е ниже, чтобы поставить обработчик, а затем по ссылке, чтобы увидеть его в действии:
0
Эмуляция DOMContentLoaded для IE8-
Прежде чем что-то эмулировать, заметим, что альтернативой событию onDOMContentLoadedявляется вызов функции init из скрипта в самом конце BODY, когда основная часть DOM уже готова:
<body> ...
<script>
init();
</script>
</body>
Причина, по которой обычно предпочитают именно событие – одна: удобство. Вешается обработчик и не надо ничего писать в конец BODY.
0
<body> ... <script> init(); </script> </body>
Причина, по которой обычно предпочитают именно событие – одна: удобство. Вешается обработчик и не надо ничего писать в конец BODY.
Мини-скрипт documentReady
Если вы всё же хотите использовать onDOMContentLoaded кросс-браузерно, то нужно либо подключить какой-нибудь фреймворк – почти все предоставляют такой функционал, либо использовать функцию из мини-библиотеки jquery.documentReady.js.
Несмотря на то, что в названии содержится слово «jquery», эта библиотечка не требует jQuery. Наоборот, она представляет собой единственную функцию с названием $, вызов которой $(callback) добавляет обработчик callbackна DOMContentLoaded (можно вызывать много раз), либо, если документ уже загружен – выполняет его тут же.
Пример использования:
<script src="https://js.cx/script/jquery.documentReady.js"></script> <script> $(function() { alert( "DOMContentLoaded" ); }); </script> <img src="https://js.cx/clipart/yozhik.jpg?speed=1"> <div>Текст страницы</div>
Здесь alert сработает до загрузки картинки, но после создания DOM, в частности, после появления текста. И так будет для всех браузеров, включая даже очень старые IE.
0
Как именно эмулируетсяDOMContentLoaded?
Технически, эмуляция DOMContentLoadedдля старых IE осуществляется очень забавно.
Основной приём – это попытка прокрутить документ вызовом:
document.documentElement.doScroll("left");
Метод doScroll работает только в IE и «методом тыка» было обнаружено, что он бросает исключение, если DOM не полностью создан.
Поэтому библиотека пытается вызвать прокрутку, если не получается – через setTimeout(.., 1) пытается прокрутить его ещё раз, и так до тех пор, пока действие не перестанет вызывать ошибку. На этом этапе документ считается загрузившимся.
Внутри фреймов и в очень старых браузерах такой подход может ошибаться, поэтому дополнительно ставится резервный обработчик на onload, чтобы уж точно сработал.
0
Итого
Самое востребованное событие из описанных – без сомнения, DOMContentLoaded. Многие страницы сделаны так, что инициализуют интерфейсы именно по этому событию.
Это удобно, ведь можно в <head> написать скрипт, который будет запущен в момент, когда все DOM-элементы доступны.
С другой стороны, следует иметь в виду, что событие DOMContentLoaded будет ждать не только, собственно, HTML-страницу, но и внешние скрипты, подключенные тегом <script> без атрибутов defer/async, а также стили перед такими скриптами.
Событие DOMContentLoaded не поддерживается в IE8-, но почти все фреймворки умеют его эмулировать. Если нужна отдельная функция только для кросс-браузерного аналога DOMContentLoaded – можно использовать jquery.documentReady.js.
Событие window.onload используют редко, поскольку обычно нет нужды ждать подгрузки всех ресурсов. Если же нужен конкретный ресурс (картинка или ифрейм), то можно поставить событие onload непосредственно на нём, мы посмотрим, как это сделать, далее.
Событие window.onunload почти не используется, как правило, оно бесполезно – мало что можно сделать, зная, что окно браузера прямо сейчас закроется.
Гораздо чаще применяется window.onbeforeunload – это де-факто стандарт для того, чтобы проверить, сохранил ли посетитель данные, действительно ли он хочет покинуть страницу. В системах редактирования документов оно используется повсеместно.