Статьи

Создание всплывающих окон без HTML-файлов

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

Одна вещь, которая всегда беспокоила меня о динамических всплывающих окнах по сравнению с динамическими фреймами: вам нужен отдельный файл для использования в качестве цели всплывающего окна. Я задокументировал этот процесс, потому что он может помочь кому-то еще. Я не говорю, что вы должны использовать эти методы, метод 2 особенно неприятен — я просто говорю: вы можете !.html

Вот два метода, где вам не нужен отдельный файл.

Почему вы хотите динамически генерируемое всплывающее окно?

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

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

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

Способ 1: использование URL-адреса данных

URL данных, красивая вещь:

Схема URI данных — это схема URI, которая обеспечивает способ включения данных на веб-страницах, как если бы они были внешними ресурсами.

Источник: Википедия

Одним из распространенных вариантов использования URL-адресов данных являются встроенные изображения в файлах HTML или CSS, которые обычно выглядят примерно так:

data:image/png;base64,iVBORw0KG......

Вы также можете использовать эту же технику для файлов HTML :

data:text/html,<title>Hello Data URL</title><p>File-less HTML page!</p>

При этом это означает, что мы можем динамически генерировать всплывающее окно без засорения файла нашим моджо:.html

window.open('data:text/html,<title>Hello Data URL</title><p>File-less HTML page!</p>', 'Hello World', 'width=400,height=200');

Это прекрасно работает, если все, что вам нужно, это динамическое всплывающее окно (это поддерживается в IE8 и других).

Однако, если вы хотите, чтобы это всплывающее окно говорило с родительским окном, которое сгенерировало всплывающее окно в первом случае (что в моем случае было истинным), вам не повезло, поскольку источник URL-адреса данных не совпадает с источником созданного домена. всплывающее окно , которое в основном не равно кости . Так вот как у меня появилось сумасшествие, которое вы собираетесь увидеть.

Способ 2: использование родительской страницы в качестве дочернего всплывающего окна

Хм что? Это решение использует файл HTML, который создает всплывающее окно в качестве цели всплывающего окна. После открытия всплывающее окно уничтожает DOM и переписывает его своим собственным.

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

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

Несколько дополнительных предостережений в уже безумно звучащем решении:

  1. Вам нужен какой-то идентификатор в URL, чтобы указать, что это всплывающая версия
  2. Любой JavaScript, который выполняется до того, как ваш скрипт будет найден, будет выполнен. Если вы можете быть уверены, что ваш скрипт первым, вы можете запретить запуск следующих скриптов.

Один единственный скрипт включен в качестве первого скрипта для включения на этой странице со следующим кодом ( и демо ):

if (window.location.hash.indexOf('#popup') === -1) {
  window.open(window.location + '#popup', 'Popup', 'width=300,height=300');
} else {
  // we are the popup
  initPopupClient();
}

function initPopupClient() {
  // here we're overwriting the contents of the HTML element
  // causing any successive scripts to be removed - thus if
  // we can be first, it's a good thing.
  document.documentElement.innerHTML = [
    '<title>Popup tool</title>',
    '<style>* { font-family: comic sans; }</style>',
    '<p>Welcome to our dynamically generated popup</p>'
  ].join('');

  // now trigger any function on our parent window
  window.opener.alert('Hello from the popup');

  // or send it messages nicely
  window.opener.postMessage('This is less invasive I guess!');
}

Уничтожение оригинального DOM.

Поскольку мы используем родительскую страницу в качестве источника всплывающих окон, нам нужно полностью удалить DOM и заменить его на наш. Перезаписав содержимое элемента HTML, мы преуспели в этом:

document.documentElement.innerHTML = ...some new markup...

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

Ссылаясь на родительское окно

Мы делаем это обычным способом доступа к openerсобственности. Это дает нам прямой доступ к любому методу, и, если вам это нужно, вы просто используете postMessageразрешение родителю просто прослушивать события сообщения:

window.opener.postMessage(JSON.stringify(someData));

отказ

Оба эти метода довольно экстремальны, и вам следует подумать, что у вас есть веские основания для их практического использования. Для моей конкретной проблемы (которая должна быть подробно описана в моем следующем посте) это было необходимым злом. Убедитесь, что вы действительно не хотите этот размещенный файл! Единственная причина, по которой я пришел к такому выводу (о сумасшедших прыжках с обручем), заключалась в моих требованиях к скрипту polyfill для remote-tilt.com..html