Выполнение скрипта после загрузки страницу javascript и jquery

Содержание:

Событие onprogress в деталях

При обработке события есть ряд важных тонкостей.

Можно, конечно, их игнорировать, но лучше бы знать.

Заметим, что событие, возникающее при , имеет одинаковый вид на стадии отправки (в обработчике ) и при получении ответа (в обработчике ).

Оно представляет собой объект типа со свойствами:

Сколько байт уже переслано.

Имеется в виду только тело запроса, заголовки не учитываются.

Если , то известно полное количество байт для пересылки, и оно хранится в свойстве .

Общее количество байт для пересылки, если известно.

А может ли оно быть неизвестно?

  • При отправке на сервер браузер всегда знает полный размер пересылаемых данных, так что всегда содержит конкретное количество байт, а значение всегда будет .
  • При скачивании данных – обычно сервер в начале сообщает их общее количество в HTTP-заголовке . Но он может и не делать этого, например если сам не знает, сколько данных будет или если генерирует их динамически. Тогда будет равно . А чтобы отличить нулевой размер данных от неизвестного – как раз служит , которое в данном случае равно .

Ещё особенности, которые необходимо учитывать при использовании :

Событие происходит при каждом полученном/отправленном байте, но не чаще чем раз в 50 мс.
Это обозначено в .

В процессе получения данных, ещё до их полной передачи, доступен , но он не обязательно содержит корректную строку.
Можно до окончания запроса заглянуть в него и прочитать текущие полученные данные

Важно, что при пересылке строки в кодировке UTF-8 кириллические символы, как, впрочем, и многие другие, кодируются 2 байтами. Возможно, что в конце одного пакета данных окажется первая половинка символа, а в начале следующего – вторая

Поэтому полагаться на то, что до окончания запроса в находится корректная строка нельзя. Она может быть обрезана посередине символа.
Исключение – заведомо однобайтные символы, например цифры или латиница.

Сработавшее событие не гарантирует, что данные дошли.
Событие срабатывает, когда данные отправлены браузером. Но оно не гарантирует, что сервер получил, обработал и записал данные на диск. Он говорит лишь о самом факте отправки.
Поэтому прогресс-индикатор, получаемый при его помощи, носит приблизительный и оптимистичный характер.

Обмен сообщениями между окнами

Интерфейс позволяет окнам общаться между собой независимо от их происхождения.

Это способ обойти политику «Одинакового источника». Он позволяет обмениваться информацией, скажем и , но только в том случае, если оба сайта согласны и вызывают соответствующие JavaScript-функции. Это делает общение безопасным для пользователя.

Интерфейс имеет две части.

Окно, которое хочет отправить сообщение, должно вызвать метод postMessage окна получателя. Другими словами, если мы хотим отправить сообщение в окно , тогда нам следует вызвать .

Аргументы:

Данные для отправки. Может быть любым объектом, данные клонируются с использованием «алгоритма структурированного клонирования». IE поддерживает только строки, поэтому мы должны использовать метод на сложных объектах, чтобы поддержать этот браузер.
Определяет источник для окна-получателя, только окно с данного источника имеет право получить сообщение.

Указание является мерой безопасности. Как мы помним, если окно (получатель) происходит из другого источника, мы из окна-отправителя не можем прочитать его . Таким образом, мы не можем быть уверены, какой сайт открыт в заданном окне прямо сейчас: пользователь мог перейти куда-то, окно-отправитель не может это знать.

Если указать , то мы можем быть уверены, что окно получит данные только в том случае, если в нём правильный сайт

Особенно это важно, если данные конфиденциальные

Например, здесь получит сообщения только в том случае, если в нём открыт документ из источника :

Если мы не хотим проверять, то в можно указать .

Чтобы получать сообщения, окно-получатель должно иметь обработчик события (сообщение). Оно срабатывает, когда был вызван метод (и проверка пройдена успешно).

Объект события имеет специфичные свойства:

Данные из .
Источник отправителя, например, .
Ссылка на окно-отправитель. Можно сразу отправить что-то в ответ, вызвав .

Чтобы добавить обработчик, следует использовать метод , короткий синтаксис не работает.

Вот пример:

Полный пример:

Результат
iframe.html
index.html

Без задержек

Между и событием не существует задержки. Событие происходит синхронно, быстрее, чем .

Iframes and ownership

The iframe element itself, , is owned by the containing page, and so you may work on it as an element (getting/setting attributes, manipulating its style, moving it around in the DOM, etc.). The object representing the iframe content is the property of the page that was loaded into the iframe. In order for the containing page to access the iframe’s window object in any meaningful way, the domain of the containing page and the iframe page need to be the same (details).

When the domains match, the containing page can access the object for the iframe. The iframe element object has a property called that contains the iframe’s object, so you can use the property to retrieve the object. This is the standard way to retrieve the iframe’s object and is supported by most browsers. Internet Explorer prior to version 8 didn’t support this property and so you had to use the proprietary property. Example:

Additionally, the containing page’s window object can be retrieved from the iframe using the property. The iframe page can also retrieve a reference to the iframe element in which it resides by using the property. This crosses the ownership boundary since the iframe is owned by the containing page but is directly accessible off the iframe’s object.

Защита

Основные превентивные меры:

  • валидация данных
  • преобразование вывода

На практике это должно быть реализовано в виде:

  • исключения всех недоверенных данных из контекста (body, атрибуты, JavaScript, CSS или URL);
  • использование «белых списков» на строне сервера (проверка длины, формата, логики и.д.);
  • использование специализированных средств очистки данных (OWASP AntiSamy или Java HTML Sanitizer Project);
  • использование атрибута HttpOnly;
  • использование Content Security Policy.

Не давайте использовать недоверенные данные:

Не давайте использовать недоверенные данные в содержимом HTML элемента:

Используйте преобразование сущностей:

Методов защиты довольно много, но одним из самых эффективных является использование Content Security Policy.

HTML Reference

HTML by AlphabetHTML by CategoryHTML Browser SupportHTML AttributesHTML Global AttributesHTML EventsHTML ColorsHTML CanvasHTML Audio/VideoHTML Character SetsHTML DoctypesHTML URL EncodeHTML Language CodesHTML Country CodesHTTP MessagesHTTP MethodsPX to EM ConverterKeyboard Shortcuts

HTML Tags

<!—>
<!DOCTYPE>
<a>
<abbr>
<acronym>
<address>
<applet>
<area>
<article>
<aside>
<audio>
<b>
<base>
<basefont>
<bdi>
<bdo>
<big>
<blockquote>
<body>
<br>
<button>
<canvas>
<caption>
<center>
<cite>
<code>
<col>
<colgroup>
<data>
<datalist>
<dd>
<del>
<details>
<dfn>
<dialog>
<dir>
<div>
<dl>
<dt>
<em>
<embed>
<fieldset>
<figcaption>
<figure>
<font>
<footer>
<form>
<frame>
<frameset>
<h1> — <h6>
<head>
<header>
<hr>
<html>
<i>
<iframe>
<img>
<input>
<ins>
<kbd>
<label>
<legend>
<li>
<link>
<main>
<map>
<mark>
<meta>
<meter>
<nav>
<noframes>
<noscript>
<object>
<ol>
<optgroup>
<option>
<output>
<p>
<param>
<picture>
<pre>
<progress>
<q>
<rp>
<rt>
<ruby>
<s>
<samp>
<script>
<section>
<select>
<small>
<source>
<span>
<strike>
<strong>
<style>
<sub>
<summary>
<sup>
<svg>
<table>
<tbody>
<td>
<template>
<textarea>
<tfoot>
<th>
<thead>
<time>
<title>
<tr>
<track>
<tt>
<u>
<ul>
<var>
<video>
<wbr>

Код кроссбраузерной поддержки

«Родное» событие есть не во всех браузерах, поэтому мы рассмотрим код для кроссбраузерной поддержки этого события:

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
	*/
}

Разберем его по шагам.

  1. Код будет пытаться поймать событие различными способами. Вполне может получиться так, что несколько способов сработают независимо.

    Поэтому завернем обработчик в функцию , единственный смысл которой — гарантировать, что будет вызван не более одного раза.

  2. Событие поддерживают достаточно новые Firefox, Opera, Safari/Chrome. Нет гарантии, что версия посетителя поддерживает это событие, но попробовать стоит.
  3. Браузер Internet Explorer не поддерживает , поэтому для него используются обходные пути.
    1. Функция пытается скроллить документ вызовом . Если получается — значит, документ загрузился, если нет — заказывает повторную попытку через setTimeout, и так пока документ наконец не будет готов. На практике это очень надежный способ, но есть проблемы с фреймами, поэтому используется только для окон верхнего уровня.
      Дополнительный фильтр — проверка
    2. Событие с проверкой , как и , срабатывает после загрузки документа. Но, к сожалению, оно происходит уже после загрузки картинок. Поэтому — вообще говоря, не то, что нам надо. Но это событие работает для фреймов, и при этом срабатывает до . Поэтому будем использовать и этот способ.
  4. Для тех браузеров, в которых не сработали предыдущие методы (например, очень старый Firefox), добавим вызов обработчика при событии .
    1. Для совсем древних браузеров, в которых нет , вы можете раскомментировать и строчку (4.1). При этом, разумеется, возможен конфликт с другими обработчиками .

Этот код взят, с небольшими упрощениями, из библиотеки jQuery, а методы придуманы различными авторами.

HTML Tags

<!—><!DOCTYPE><a><abbr><acronym><address><applet><area><article><aside><audio><b><base><basefont><bdi><bdo><big><blockquote><body><br><button><canvas><caption><center><cite><code><col><colgroup><data><datalist><dd><del><details><dfn><dialog><dir><div><dl><dt><em><embed><fieldset><figcaption><figure><font><footer><form><frame><frameset><h1> — <h6><head><header><hr><html><i><iframe><img><input><ins><kbd><label><legend><li><link><main><map><mark><meta><meter><nav><noframes><noscript><object><ol><optgroup><option><output><p><param><picture><pre><progress><q><rp><rt><ruby><s><samp><script><section><select><small><source><span><strike><strong><style><sub><summary><sup><svg><table><tbody><td><template><textarea><tfoot><th><thead><time><title><tr><track><tt><u><ul><var><video>

The Problem – Multiple OnLoad Functions

When a web page loads, all the front end code on the page is processed from top down. This includes any HTML, JavaScript and CSS styles that may have been added to the page. If you added this script to the head section of your page, for example:

function functionA() {
  alert("Alert from Function A.");
}
window.onload = functionA;

OR

window.onload = functionA() {
  alert("Alert from Function A.");
}

When your browser loads the page, it will stop and execute the above script and pop up an alert window that says “Alert from Function A.” The browser will stop loading the page further until the alert window is closed. What if you perform more complicated operations inside of functionA? For example, functionA might want to access page elements that are not yet loaded. Since those elements are not available for processing (yet), the script will produce an error.

An even clearer picture of how the JavaScript onload function could be a problem is seen when two or more independent plugins on a page attempt to call the onload function using any of the regular methods described above.

Let’s say a plugin named PluginA contains this snippet of code:

function FunctionInPluginA() {
  // Some functionality to execute on page load
}
window.onload = FunctionInPluginA;

Let’s further assume that PluginA is a third party plugin you download onto your content management system (CMS). Since you’re a developer, you also built your own plugin (say PluginB) to add a different functionality.

Inside of PluginB, you have a function like this:

function FunctionInPluginB() {
  // Some functionality to execute on page load
}
window.onload = FunctionInPluginB;

When a page containing both PluginA and PluginB loads, only one of the onload functions (the one rendered last in the page) will be executed.

After the first onload event handler is executed, it will be replaced when the second onload event handler is executed. So depending on the rendering sequence, the third-party plugin might break your plugin or vice-versa. This sort of issue often happens with poorly coded WordPress plugins/widgets.

Подробно о window.onload

  1. Иногда, происходит такое, что вы, вроде бы и написали все правильно, но скрипт… просто не работает. И непонятно почему.

    Одна из причин — это загрузка скрипта раньше, чем самой страницы. Ваш скрипт — тупо не видит код ниже себя.

    Для этого существует window.onload

    window — объект.

    onload — это «событие». Иногда, на просторах интернета можно встретить разное название для этого события, но «onload» — это «Event», а в переводе — это событие.

    Использовать window.onload можно самым простым способом, размещаем данный скрипт на странице и после загрузки страницы, вы увидите сообщение о том «скрипт выполнился после загрузки страницы»

    <script>

    window.onload = function() {

    alert(‘Страница загружена’);

    };

    </script>

    Если у вас подключенный скрипт, то теги <script> и </script> не нужны.

    window.onload = function() {

    здесь помещаем все, что угодно…

    };

    object может быть например body или window, естественно к этому объекту, сперва нужно обратиться.

    object.onload=function(){/**код**/};

    В качестве атрибута onload, возможно использование в HTML :

    <element onload=»myFunction»></element>

  2. Давайте попробуем создать эмуляцию window.onload, как это работает в реальном времени.

    Создадим скрипт и разместим его тут на странице:

    <script>

    window.onload = function() {

    alert(‘Страница загружена’);

    // к этому моменту страница загружена

    alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);

    };

    </script>

    <img id=»img» src=»https://dwweb.ru/__a-data/__all_for_scripts/__examples/js/onload/onload.jpg»>

    Нажмите кнопку window.onload :
    window.onload

  3. Несколько вариантов для запуска вашего скрипта, при использовании JQuery

    $(window).load(function() {

    /** код запустится, когда страница будет полностью загружена на 100% **/

    });

    +

    //Вариант 1

    $(document).ready(function() {

    /** код запустится, когда будет готов DOM, исключая картинки **/

    // ваш код

    });

    //Вариант 2

    $(function() {

    /** код запустится, когда будет готов DOM, исключая картинки **/

    //ваш код

    });

    //Вариант 3

    $(document).on(‘ready’, function(){

    /** код запустится, когда будет готов DOM, исключая картинки **/

    //ваш код

    });

    //Вариант 4

    jQuery(document).ready(function(){

    /** код запустится, когда будет готов DOM, исключая картинки **/

    //ваш код

    });

    И!
    Не путаете window load jQuery с методом .

Последняя дата редактирования : 22.01.2021 00:06
//dwweb.ru/comments_1_5/include/img/hand_no_foto.png
no
no

Пример: минималистичное окно

Давайте откроем окно с минимальным набором настроек, просто чтобы посмотреть, какие из них браузер позволит отключить:

В этом примере большинство настроек заблокированы и само окно находится за пределами видимой области экрана. Посмотрим, что получится в результате. Большинство браузеров «исправит» странные значения – как, например, нулевые и отрицательные . Например, Chrome установит высоту и ширину такого окна равной высоте и ширине экрана, так что попап будет занимать весь экран.

Давайте исправим значения и зададим нормальные координаты ( и ) и значения размеров окна ( и ):

Большинство браузеров выведет окно с заданными нами настройками.

Правила для опущенных параметров:

  • Если третий аргумент при вызове отсутствует или он пустой, будут использованы настройки окна по умолчанию.
  • Если строка параметров передана, но некоторые параметры yes/no пропущены, то считается, что указано , так что соответствующие возможности будут отключены, если на это нет ограничений со стороны браузера. Поэтому при задании параметров убедитесь, что вы явно указали все необходимые yes.
  • Если координаты не заданы, браузер попытается открыть новое окно рядом с предыдущим открытым окном.
  • Если не заданы размеры окна , браузер откроет новое окно с теми же размерами, что и предыдущее открытое окно.

Content Security Policy

Ранее, одним из главных принципов безопасности браузеров являлась политика Same Origin Policy. Ее суть заключается в проверке трех компонентов, из которых состоит origin: протокол, хост и порт. Однако при внедрении пейлода с одного сайта на другой SOP будет бесполезен для сайта с внедренным пейлоадом. Поэтому на смену SOP пришел CSP, основное предназначение которого состоит в том, чтобы защитить пользователя от угроз межсайтового выполнения сценариев. CSP описывает безопасные источники загрузки ресурсов, устанавливает правила использования встроенных стилей, скриптов, а также динамической оценки JavaScript. Самое главное — загрузка с ресурсов, не входящих в «белый список», блокируется.

Поддерживаемые директивы:

  • Default-src: определение политики загрузки для всех типов ресурсов в случае, если определенная директива типа ресурса не определена (резервная);
  • Script-src: какие скрипты могут использовать защищенный ресурс;
  • Object-src: откуда ресурс может загружать плагины;
  • Style-src: какие стили (CSS) пользователь применяет к защищенному ресурсу;
  • Img -src: откуда защищенный ресурс может загружать изображения;
  • Media-src: откуда защищенный ресурс может загружать видео и аудио;
  • Frame-src: где защищенный ресурс может вставлять кадры;
  • Font-src: где защищенный ресурс может загружать шрифты;
  • Connect-src: какие URI могут быть загружены защищенным ресурсом;
  • Form-action: какие URI могут использоваться как результат работы HTML-формы;
  • Sandbox: определяет политику «песочницы HTML»;
  • Script-nonce: выполнение сценария, требуя наличия указанного nonce для элементов сценария;
  • Plugin-types: набор плагинов, которые могут быть вызваны защищенным ресурсом, путем ограничения типов ресурсов, которые могут быть встроены;
  • Reflection-xss: активировать или деактивировать любые проверки, используемые для фильтрации или блокирования отраженных атак между сайтами, эквивалентные нестандартному заголовку X-XSS-Protection;
  • Report-uri: указывает URI, на который агент пользователя отправляет отчеты о нарушении правил.

Ошибка в скрипте с другого источника

Есть правило: скрипты с одного сайта не могут получить доступ к содержимому другого сайта. Например, скрипт с не может прочитать почту пользователя на .

Или, если быть более точным, один источник (домен/порт/протокол) не может получить доступ к содержимому с другого источника. Даже поддомен или просто другой порт будут считаться разными источниками, не имеющими доступа друг к другу.

Это правило также касается ресурсов с других доменов.

Если мы используем скрипт с другого домена, и в нем имеется ошибка, мы не сможем узнать детали этой ошибки.

Для примера давайте возьмём мини-скрипт , который состоит из одного-единственного вызова функции, которой не существует:

Теперь загрузим этот скрипт с того же сайта, на котором он лежит:

Мы видим нормальный отчёт об ошибке:

А теперь загрузим этот же скрипт с другого домена:

Отчёт отличается:

Детали отчёта могут варьироваться в зависимости от браузера, но основная идея остаётся неизменной: любая информация о внутреннем устройстве скрипта, включая стек ошибки, спрятана. Именно потому, что скрипт загружен с другого домена.

Зачем нам могут быть нужны детали ошибки?

Существует много сервисов (и мы можем сделать наш собственный), которые обрабатывают глобальные ошибки при помощи , сохраняют отчёт о них и предоставляют доступ к этому отчёту для анализа. Это здорово, потому что мы можем увидеть реальные ошибки, которые случились у наших пользователей. Но если скрипт – с другого домена, то информации об ошибках в нём почти нет, как мы только что видели.

Похожая кросс-доменная политика (CORS) внедрена и в отношении других ресурсов.

Чтобы разрешить кросс-доменный доступ, нам нужно поставить тегу атрибут , и, кроме того, удалённый сервер должен поставить специальные заголовки.

Существует три уровня кросс-доменного доступа:

  1. Атрибут отсутствует – доступ запрещён.
  2. – доступ разрешён, если сервер отвечает с заголовком со значениями или наш домен. Браузер не отправляет авторизационную информацию и куки на удалённый сервер.
  3. – доступ разрешён, если сервер отвечает с заголовками со значением наш домен и . Браузер отправляет авторизационную информацию и куки на удалённый сервер.

Почитать больше о кросс-доменных доступах вы можете в главе Fetch: запросы на другие сайты. Там описан метод для сетевых запросов, но политика там точно такая же.

Такое понятие как «куки» (cookies) не рассматривается в текущей главе, но вы можете почитать о них в главе Куки, document.cookie.

В нашем случае атрибут отсутствовал. Поэтому кросс-доменный доступ был запрещён. Давайте добавим его.

Мы можем выбрать (куки не отправляются, требуется один серверный заголовок) или (куки отправляются, требуются два серверных заголовка) в качестве значения атрибута.

Если куки нас не волнуют, тогда смело выбираем :

Теперь при условии, что сервер предоставил заголовок , всё хорошо. У нас есть полный отчёт по ошибкам.

Полный синтаксис window.open

Полный синтаксис:

Функция возвращает ссылку на объект нового окна, либо , если окно было заблокировано браузером.

Параметры:

URL для загрузки в новое окно.
Имя нового окна. Может быть использовано в параметре в формах. Если позднее вызвать с тем же именем, то браузеры (кроме IE) заменяют существующее окно на новое.
Строка с конфигурацией для нового окна. Состоит из параметров, перечисленных через запятую. Пробелов в ней быть не должно.

Значения параметров .

  1. Настройки расположения окна:
(число)

Координаты верхнего левого угла относительно экрана. Ограничение: новое окно не может быть позиционировано за пределами экрана.

(число)

Ширина/высота нового окна. Минимальные значения ограничены, так что невозможно создать невидимое окно с нулевыми размерами.

Если координаты и размеры не указаны, то обычно браузер открывает не окно, а новую вкладку.

  1. Свойства окна:
(yes/no)
Скрыть или показать строку меню браузера.
(yes/no)
Показать или скрыть панель навигации браузера (кнопки назад, вперёд, обновить страницу и остальные) в новом окне.
(yes/no)
Показать/скрыть поле URL-адреса в новом окне. По умолчанию Firefox и IE не позволяют скрывать строку адреса.
(yes/no)
Показать или скрыть строку состояния. С другой стороны, браузер может в принудительном порядке показать строку состояния.
(yes/no)
Позволяет отключить возможность изменять размеры нового окна. Значение обычно неудобно посетителям.
(yes/no)
Разрешает убрать полосы прокрутки для нового окна. Значение обычно неудобно посетителям.
  1. Ещё есть небольшое количество не кросс-браузерных свойств, которые обычно не используются. Вы можете узнать о них в документации, например MDN: window.open.

Важно:

Браузер подходит к этим параметрам интеллектуально. Он может проигнорировать их часть или даже все, они скорее являются «пожеланиями», нежели «требованиями».

Важные моменты:

  • Если при вызове указан только первый параметр, параметр отсутствует, то используются параметры по умолчанию. Обычно при этом будет открыто не окно, а вкладка, что зачастую более удобно.
  • Если указана строка с параметрами, но некоторые параметры отсутствуют, то браузер выставляет их в . Поэтому убедитесь, что все нужные вам параметры выставлены в .
  • Когда не указан , то браузер откроет окно с небольшим смещением относительно левого верхнего угла последнего открытого окна.
  • Если не указаны , новое окно будет такого же размера, как последнее открытое.

Enter document.domain

I had resigned myself to using one method of detecting an iframe loading for Internet Explorer and another for every other browser, so I continued on my task. Next, I had to set on the containing page because I had a couple of different subdomains from which I needed to load iframes. When using different subdomains, setting to the root of the hostname allows iframes to communicate with their parent and each other. For example, if I had to load an iframe page from , that is technically considered a different domain and would not be allowed. However, if I set to “nczonline.net” in both the containing page and the iframe page, the two are allowed to communicate. A single line of code, ideally placed at the top of the page, is all it takes:

This equalizes the domain difference and allows everything to work as if both pages were from the same domain. Or so I thought.

The problem with this approach is that prior to the iframe being loaded, it’s still considered to be owned by the domain as specific in its attribute. A relative path automatically prepends the domain on which the containing page was loaded from () versus the one assigned to . That means a comparison of to fails the same-domain check and causes a JavaScript error when you try to access the iframe’s object (experiment). The iframe page won’t have its associated domain changed until it’s loaded and the JavaScript command to change the domain has been executed. Once the iframe page has been loaded, however, everything works fine. But how do you know once the iframe page has been loaded?

Политика «Одинакового источника»

Два URL имеют «одинаковый источник» в том случае, если они имеют совпадающие протокол, домен и порт.

  • (другой домен: важен)
  • (другой домен: важен)
  • (другой протокол: )
  • (другой порт: )

Политика «Одинакового источника» говорит, что:

  • если у нас есть ссылка на другой объект , например, на всплывающее окно, созданное с помощью или на из и у этого окна тот же источник, то к нему будет полный доступ.
  • в противном случае, если у него другой источник, мы не сможем обращаться к его переменным, объекту и так далее. Единственное исключение – объект : его можно изменять (таким образом перенаправляя пользователя). Но нельзя читать (нельзя узнать, где находится пользователь, чтобы не было никаких утечек информации).

Внутри находится по сути отдельное окно с собственными объектами и .

Мы можем обращаться к ним, используя свойства:

  • ссылка на объект внутри .
  • – ссылка на объект внутри , короткая запись для .

Когда мы обращаемся к встроенному в ифрейм окну, браузер проверяет, имеет ли ифрейм тот же источник. Если это не так, тогда доступ будет запрещён (разрешена лишь запись в , это исключение).

Для примера давайте попробуем чтение и запись в ифрейм с другим источником:

Код выше выведет ошибку для любых операций, кроме:

  • Получения ссылки на внутренний объект из
  • Изменения .

С другой стороны, если у ифрейма тот же источник, то с ним можно делать всё, что угодно:

и

Событие – по сути то же, что и . Оно сработает, когда встроенное окно полностью загрузится со всеми ресурсами.

…Но всегда доступно извне ифрейма, в то время как доступ к разрешён только из окна с тем же источником.

The Best Solution – AddOnLoadEvent Function

The best solution I have seen for this problem is to write a completely new function like this:

function AddOnLoadEvent(functionX)
{
  var oldonloadevent = window.onload;
  if (typeof window.onload != 'function')
  {
    window.onload = functionX;
  }
  else
  {
    window.onload = function()
    {
      if (oldonloadevent)
      {
        oldonloadevent();
      }
      functionX();
    }
  }
}
AddOnLoadEvent(FunctionToRunOnLoad);
AddOnLoadEvent(function() {
  /* more stuff to do when the page loads */
});

I used this function in my popular Actual Size Online Ruler application and I have been using it in a number of other applications since I discovered it.

This function does not have any of the three issues described earlier. It is completely unobtrusive. So the code can be placed in an external file along with other scripts. If you put it in its own separate file, just make sure you call it after the files that hold the functions so that they are available.

This function works even if the onload event handler has been previously assigned (say by a third-party plugin).

If a function has not been assigned to window.onload already, the function passed to AddOnLoadEvent will be assigned to the window.onload event. But if a function has already been assigned to window.onload, a brand new function will be created that first calls the original onload event handler, and then calls the new onload event handler afterwards.

So, if you already have a script that uses the onload event handler, you don’t need to dig it out and change it, unless you want to.

Have you needed to play around with multiple JavaScript onload events? What was your experience? Please add your comments using the comment form below.

Found this article valuable? Want to show your appreciation? Here are some options:

  1. Spread the word! Use these buttons to share this link on your favorite social media sites.
  2. Sign up to join my audience and receive email notifications when I publish new content.
  3. Contribute by adding a comment using the comments section below.
  4. Follow me on , LinkedIn, and .

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.

Итого

Говоря о стандартах, у нас есть:

Спецификация 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, так как страница – это основа всего.

Итого

  • Всплывающее окно открывается с помощью вызова .
  • Метод возвращает ссылку на новое окно или , если окно было заблокировано.
  • Современные браузеры блокируют окна, если вызвано не в результате действия посетителя.
  • Обычно открывается вкладка, но если заданы размеры и позиция – то именно окно.
  • Новое окно имеет ссылку на родительское в .
  • Окна могут общаться между собой как угодно, если они из одного источника. Иначе действуют жёсткие ограничения безопасности.

Всплывающие окна используются нечасто. Ведь загрузить новую информацию можно динамически, с помощью технологии AJAX, а показать – в элементе , расположенным над страницей (). Ещё одна альтернатива – тег .

Но в некоторых случаях всплывающие окна бывают очень даже полезны. Например, отдельное окно сервиса онлайн-консультаций. Посетитель может ходить по сайту в основном окне, а общаться в чате – во вспомогательном.

Если вы хотите использовать всплывающее окно, предупредите посетителя об этом, так же и при использовании в ссылках или формах. Иконка открывающегося окошка на ссылке поможет посетителю понять, что происходит и не потерять оба окна из поля зрения.

Итого

Типичный код GET-запроса с использованием :

Событий на самом деле больше, в они все перечислены в том порядке, в каком генерируются во время запроса:

  • – начало запроса.
  • – прибыла часть данных ответа, тело ответа полностью на данный момент можно получить из свойства .
  • – запрос был прерван вызовом .
  • – произошла ошибка соединения, например неправильное доменное имя. Событие не генерируется для HTTP-ошибок как, например, 404.
  • – запрос успешно завершён.
  • – запрос был отменён по причине истечения отведённого для него времени (происходит, только если был установлен таймаут).
  • – срабатывает после , , или .

События , , и взаимно исключают друг друга – может произойти только одно из них.

Наиболее часто используют события завершения загрузки (), ошибки загрузки (), или мы можем использовать единый обработчик для всего и смотреть в свойствах объекта запроса детали произошедшего.

Также мы уже видели событие: . Исторически оно появилось одним из первых, даже раньше, чем была составлена спецификация. Сегодня нет необходимости использовать его, так как оно может быть заменено современными событиями, но на него можно часто наткнуться в старом коде.

Если же нам нужно следить именно за процессом отправки данных на сервер, тогда можно использовать те же события, но для объекта .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *