Unetway
Обмен данными между iframe через postMessage JavaScript

Обмен данными между iframe через postMessage

Политика конфиденциальности браузеров не позволяет обращаться к содержимому Iframe с другого домена. Это называется кросс-доменным ограничением или принципом одинакового источника (Same Origin Policy), что ограничивает запросы к серверу на получение доступа сайтов друг к другу в фреймах.

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

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

Один из таких способов обмена информацией между iframe разных доменов, является использование postMessage через JavaScript.

Работу postMessage можно показать на примере прокрутки родительской страницы фрейма при нажатии на ссылку в дочерней странице. Вся суть заключается в отправке и получении специальных сообщений, позволяющим общаться страницам разных доменов между собой. Для начала разместим на странице сайта, который загружается внутри фрейма следующий код:

<a class="js-scroll-block" href="#block">Нажми на меня</a>

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

$(document).ready(function(){
  window.parent.postMessage("ready", "*");

  $('.js-scroll-block').click(function(){
    event.preventDefault();
    blockId = $(this).attr('href').replace('#', '');
    window.parent.postMessage({"setBlockId": blockId}, "*");
  })
});

В родительской странице, где установлен фрейм, необходимо установить прослушиватель отправленного сообщения, который принимает отправленный параметр setBlockId. Событие hashchange вызывает функцию отправки назад в iframe:

window.addEventListener('message', function(event) {
  if(event.data == 'ready') {
    sendFrame();
  }

  if(anchor = event.data['setBlockId']) {
    window.location.href = '#' + anchor;
  }

  if(offset = event.data['offset']) {
    window.scrollTo(0, $('iframe').offset().top + offset);
  }
});

sendFrame = function(){
  hash = window.location.hash.substring(1)
  $('iframe')[0].contentWindow.postMessage({"findElement": hash}, '*');
}

$(window).on('hashchange', sendFrame);

После получение анкора в фрейме, вновь происходит отправка значения смещения страницы на родительскую страницу:

window.addEventListener('message', function(event) {
  if(anchor = event.data['findElement']) {
    data = $('.js-scroll-block');
    window.parent.postMessage({"offset": data.offset().top}, "*");
  }
});

Где потом происходит прокрутка до выбранного элемента:


window.addEventListener('message', function(event) {
  if(offset = event.data['offset']) {
    window.scrollTo(0, $('iframe').offset().top + offset);
  }
}

Вот полный пример:

Страница где расположен фрейм:

<!DOCTYPE html>
<html>
<head>
<title>Родительская страница</title>
</head>
<body>
<iframe src="frame.html"></iframe>

 
<script>
window.addEventListener('message', function(event) {
  if(event.data == 'ready') {
    sendFrame();
  }

  if(anchor = event.data['setBlockId']) {
    window.location.href = '#' + anchor;
  }

  if(offset = event.data['offset']) {
    window.scrollTo(0, $('iframe').offset().top + offset);
  }
});

sendFrame = function(){
  hash = window.location.hash.substring(1)
  $('iframe')[0].contentWindow.postMessage({"findElement": hash}, '*');
}

$(window).on('hashchange', sendFrame);
</script>
</body>
</html>

Страница фрейма:

<!DOCTYPE html>
<html>
<head>
<title>Страница с Iframe</title>
</head>
<body>

<a class="js-scroll-block" href="#block">Нажми на меня</a>
 
<script>
window.addEventListener('message', function(event) {
  if(anchor = event.data['findElement']) {
    data = $('.js-scroll-block');
    window.parent.postMessage({"offset": data.offset().top}, "*");
  }
});


$(document).ready(function(){
  window.parent.postMessage("ready", "*");

  $('.js-scroll-block').click(function(){
    event.preventDefault();
    blockId = $(this).attr('href').replace('#', '');
    window.parent.postMessage({"setBlockId": blockId}, "*");
  })
});

</script>
</body>
</html>

 

Понравился материал? Поделитесь с друзьями!

Автор

Автор сайта «Unetway», программист по образованию, работаю менеджером проектов, занимаюсь разработкой и развитием программного обеспечения.

Комментарии

Незарегистрированным пользователям запрещено комментировать.
Войдите или пройдите регистрацию