Ответ 1
Таким образом, проблема заключается в том, что видео только получает этот метод playVideo()
, когда YouTube API завершил загрузку видеоэлемента. Этот видеоэлемент загружается async, поэтому выполнение кода будет продолжено с кодом $(document).ready(function() {
jQuery, где он попытается присоединить функции playVideo()
, которые в этот момент времени еще не существуют.
Я воспроизвел эту ошибку на этой странице HTML/JS:
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title></title>
</head>
<body>
<div id="ctl100_phContent_ctl100player" style="border:1px solid red;"></div>
<div id="ctl100_phContent_ctl101player" style="border:1px solid red;"></div>
<div id="ctl100_phContent_ctl102player" style="border:1px solid red;"></div>
<script src="https://www.youtube.com/iframe_api"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.6.2.min.js"><\/script>')</script>
<script>
window.ytPlayerList = [];
window.players = [];
window.ytPlayerList.push({ Id: 'ctl100_phContent_ctl100player', DivId: 'ctl100_phContent_ctl100player', VideoId: 'IaHxPi9dM7o', StateChangeHandler: 'hide_player_1' });
window.ytPlayerList.push({ Id: 'ctl100_phContent_ctl101player', DivId: 'ctl100_phContent_ctl101player', VideoId: 'IaHxPi9dM7o', StateChangeHandler: 'hide_player_2' });
window.ytPlayerList.push({ Id: 'ctl100_phContent_ctl102player', DivId: 'ctl100_phContent_ctl102player', VideoId: 'IaHxPi9dM7o', StateChangeHandler: 'hide_player_3' });
function onYouTubeIframeAPIReady() {
initVideos();
}
function initVideos() {
for (var i = 0; i < ytPlayerList.length; i++) {
var player = ytPlayerList[i];
var pl = new YT.Player(player.DivId, {
height: '390',
width: '640',
videoId: player.VideoId,
});
window[player.Id] = pl;
}
}
window.ctl100_phContent_ctl100player.playVideo();
</script>
</body>
</html>
Это дает мне ту же ошибку, которую вы описываете. Поэтому, чтобы проверить мою теорию (и убедиться, что не было других ошибок script), я сделал это:
setTimeout(function() {
window.ctl100_phContent_ctl100player.playVideo()
}, 1000);
Это сработало. Так и в самом деле это проблема. Однако - мы не знаем точно, что 1000 мс достаточно, чтобы гарантировать, что игрок будет инициализирован. Итак, что вы могли бы сделать - если вы хотите не рефакторировать слишком много - начинает прослушивать события onready
игрока:
function initVideos() {
for (var i = 0; i < ytPlayerList.length; i++) {
var player = ytPlayerList[i];
var pl = new YT.Player(player.DivId, {
height: '390',
width: '640',
videoId: player.VideoId,
events: {
'onReady': window[player.Id + '_ready']
}
});
window[player.Id] = pl;
}
}
Предполагается, что вы использовали когенерацию для создания таких функций, как:
function ctl100_phContent_ctl100player_ready() {
// Hook up the hide() / onShow() and other behaviors here
// ... to prove that playVideo() is a function here, I'm calling it
window.ctl100_phContent_ctl100player.playVideo();
}
function ctl100_phContent_ctl101player_ready() {
window.ctl100_phContent_ctl101player.playVideo();
}
function ctl100_phContent_ctl102player_ready() {
window.ctl100_phContent_ctl102player.playVideo();
}
Итак, это не решение для копирования-вставки для вас, но должно дать вам представление о том, почему код не работает. Есть, вероятно, более элегантные способы достижения того, что вы пытаетесь сделать, но давайте просто сохранить исправление на данный момент.
Сообщите мне, если это сработало, или если у вас есть другие вопросы.