Не удалось выполнить 'postMessage' на 'DOMWindow': несоответствие цели / источника http vs https
Я заранее приношу свои извинения, так как я очень запутался в своей проблеме. Я действительно в затруднительном положении, потому что это вызывает проблемы на моем производственном участке.
У меня есть javascript-плеер на моем сайте, который воспроизводит списки песен, которые могут быть размещены на youtube, soundcloud или vimeo. Вчера я заметил эту ошибку, которая обычно возникает всякий раз, когда вы пытаетесь загрузить новую песню через "пропуск" с помощью кнопок проигрывателя. Эта ошибка только началась в последние день или два. Я не вижу в этом ничего нового. YouTube api release notes и эта ошибка возникает при использовании Chrome, Firefox и Safari, поэтому она, скорее всего, не связана с изменением браузера. Что-то, что я использую, изменилось, хотя, поскольку я не нажимал новый код в течение 18 дней.
Пример плейлиста здесь: http://www.muusical.com/playlists/programming-music
Я думаю, что выделил способ воспроизвести ошибку, вот шаги:
- воспроизведение песни, размещенной на youtube.
- перейти к любому другому песня в списке (либо нажатием кнопки пропустить, либо прямым нажатием кнопки воспроизвести в строке песни).
*Обратите внимание, что если первая песня в плейлисте является песней youtube, то простой переход к другой песне даже без воспроизведения изначально загруженной песни youtube приведет к ошибке.
По сути, ошибка возникает, как только вы загрузили и / или воспроизвели песню youtube и попытались перейти к другой песне.
Дайте мне знать, если вы найдете исключение для такое поведение.
Я вижу эту ошибку в консоли:
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://www.muusical.com') does not match the recipient window's origin ('http://www.muusical.com').
Я загружаю плеер с помощью API YouTube javascript:
new YT.Player('playlist-player', {
playerVars: { 'autoplay': 1, 'fs': 0 },
videoId: "gJ6APKIjFQY",
events: {
'onReady': @initPlayerControls,
'onStateChange': @onPlayerStateChange
}
})
Который производит этот iframe:
<iframe id="playlist-player" frameborder="0" allowfullscreen="1" title="YouTube video player" width="640" height="360" src="https://www.youtube.com/embed/gJ6APKIjFQY?autoplay=1&enablejsapi=1&origin=http%3A%2F%2Fwww.muusical.com"></iframe>
После нажатия пропустить из вышеупомянутой песни youtube, это то, что я вижу загруженным в iframe:
<iframe id="playlist-player" frameborder="0" allowfullscreen="1" title="YouTube video player" width="640" height="360" src=""></iframe>
Я поддерживаю youtube, soundcloud и песни vimeo. Похоже, как только загружается песня youtube, "origin" меняется с http на https. Я не думаю, что нужно включать встраивание эта ошибка возникает даже в том случае, если весь плейлист-это только youtube, и она не возникает в плейлисте, который состоит только из песен из soundcloud и vimeo.
Кроме того, вот как я загружаю javascript youtube:
// Load the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
Пожалуйста, дайте мне знать, если вам нужно, чтобы я что-нибудь прояснил, и заранее спасибо, что взглянули.4 ответа:
Я немного читал об этом, некоторые так посты здесь и там, и эта ссылка тоже: https://code.google.com/p/gdata-issues/issues/detail?id=5788
Я собирался добавить комментарий к вашему вопросу, сказав, что схожу с ума от этого ... но когда я начал описывать свою установку,я нашел способ избежать этой проблемы.Я начинаю с пустого элемента
div
и использую API Youtube Iframe, чтобы превратить его вiframe
со всеми необходимыми опциями.У меня есть несколько дивы, подобные этому, обычно используют одну и ту же переменную JS для хранения всех этих игроков, но по одному (один заменяет другого и т. д... - могло быть и лучше, я знаю).
Чтобы исправить проблему, у меня была идея уничтожить игрока с
youtubePlayer.destroy();
, прежде чем построить новый из другого элемента. Больше никаких ошибок JS, кровоточащих в моей консоли Chrome:).Надеюсь, это поможет, вся литература, которую я мог прочитать о http и https, не применима к моему случаю, потому что я не устанавливаю iframe URL сам, и мой сайт, оказывается, не https ...
Я восстановил асинхронный вызов вместо статического тега
script
в моем HTML, но я не думаю, что это было необходимо.EDIT : это сообщение об ошибке довольно вводит в заблуждение на самом деле, это только смутно означает : вы не используете API youtube должным образом :)
Ответ@sodawillow частично верен, но я хотел бы подробно рассказать о решении и о том, что заставило мой код перестать вызывать метод
На моем сайте есть плеер, который меняет местами песни с различных сайтов, одним из которых является Youtube. Существуют различные способы удаления игрока в зависимости от его типа. Мой код проверяет наличие проигрывателя youtube, и если он проходит проверку, то он использует метод.destroy()
для удаления проигрывателя youtube..destroy()
, который только проигрыватель YouTube имеет. Проблема в том, что YouTube изменил имена некоторых статических переменных в своем объекте player. Например, если я создал игрока через:var player = new YT.Player('playlist-player', { playerVars: { 'autoplay': 1, 'fs': 0 }, videoId: "gJ6APKIjFQY", events: { } })
Тогда была бы переменная
player.L
, которая содержала бы строку"player"
. Поэтому, чтобы проверить, является ли текущий плеер YouTube-плеером и удалить его, я сделал следующее:if (player.L == "player") { player.destroy(); } else { //handle the removal of the Soundcloud or Vimeo player. }
Недавно Youtube изменил расположение строки
"player"
, чтобы теперь она находилась вplayer.M
. Я мог бы изменить приведенный выше код, чтобы проверитьplayer.M
вместоplayer.L
и это сработало бы, но чтобы попытаться избежать этой проблемы в будущем, я вместо этого реализовал:if (player.destroy) { player.destroy(); } else { //handle the removal of the Soundcloud or Vimeo player. }
До тех пор, пока Youtube не удалит метод
Таким образом, в общем, проблема заключалась в том, что, как догадался @sodawillow, я не использовал метод.destroy()
без предупреждения, это не вызовет никаких проблем..destroy()
для удаления проигрывателя Youtube. Причина заключалась в том, что Youtube внес некоторые необъявленные изменения в свой api, изменив расположение некоторых статических переменных.
Эта ошибка относится к API Google Youtube.
Внутри "https://www.youtube.com/iframe_api":
if (!window['YT']) { var YT = {loading: 0, loaded: 0}; } if (!window['YTConfig']) { var YTConfig = {'host': 'http://www.youtube.com'}; }
Они используют http вместо https.
Нам нужно переопределить опцию 'host' и 'widget_referrer' так же, как и'origin'.
player = new YT.Player('player', { host: 'https://www.youtube.com', height: '390', width: '640', videoId: 'M7lc1UVf-VE' ... origin: "https://www.enziin.com", widget_referrer: "https://www.enziin.com" }
Гудлак.
Мое решение состоит в том , чтобы записать всю логику плеера Youtube на отдельной странице (такой же пустой, как и possible), и на эту страницу ссылаться в теге
IFRAME
.<iframe src="/youtube_frame/?data=SOME_DATA -%>" height="400px" width="100%" frameborder="0" border="0" scrolling="no"></iframe>
Тогда ваш
youtube_frame.html
будет примерно таким:<!DOCTYPE html> <html> <body> <!-- 1. The <iframe> (and video player) will replace this <div> tag. --> <div id="player"></div> <script> // 2. This code loads the IFrame Player API code asynchronously. var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); // 3. This function creates an <iframe> (and YouTube player) // after the API code downloads. var player; function onYouTubeIframeAPIReady() { player = new YT.Player('player', { height: '390', width: '640', videoId: 'M7lc1UVf-VE', events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange } }); } // 4. The API will call this function when the video player is ready. function onPlayerReady(event) { // event.target.playVideo(); } // 5. The API calls this function when the player's state changes. // The function indicates that when playing a video (state=1), // the player should play for six seconds and then stop. var done = false; function onPlayerStateChange(event) { console.log("OnplayerStateChange"); if (event.data == YT.PlayerState.PLAYING && !done) { console.log("OnplayerStateChange - If statement"); setTimeout(stopVideo, 6000); done = true; } } function stopVideo() { player.stopVideo(); } </script> </body> </html>
(как Примечание На полях: мой контекст-это прототип.js вмешивается в событие OnStateChange, и мы не можем удалить эту зависимость. Использование jsfiddle не было бы полезно для воспроизведения проблемы, так как оно имеет мало зависимостей. Мое приложение здесь встроено в Rails, и с помощью этого плагин для показа плейлиста Видео: https://github.com/Giorgio003/Youtube-TV/)