2015-04-17 221 views
17

我遇到以下代碼問題,但我不確定問題出在哪裏。加載多個YouTube視頻iFrame API

在我的母版頁上,在javascript中,我定義了一個數組來定義我創建的YouTubePlayer對象的列表。我也在這裏加載YouTube API。

我也有(有時是幾個)YouTube用戶控件包含YouTube div的引導模式。它還包含一個JavaScript,用於將新的YouTubePlayer對象推送到主頁面js中的數組。最後,在用戶控件上,我定義了用於在引導模式的「顯示」和「隱藏」事件上自動啓動和停止視頻的方法。

最後,爲了(希望)解決正在加載的文檔和正在加載的YouTube API之間的競爭狀態,我設置了兩個bool變量(一個用於文檔,一個用於API),並在調用init之前檢查兩個變量是否爲true。函數,它遍歷YouTubePlayer對象數組並初始化它們,在窗口中設置YT.Player對象。我認爲問題的一部分是我無法靜態設置window.player1等,因爲我不知道將會加載多少YouTube用戶控件。

的問題是每當引導模式的事件發生火災,YT.Player對象我從窗口檢索不包含playVideo()pauseVideo()方法。

在我的母版頁:

$(document).ready(function() { 
    window.docReady = true; 

    if (window.apiReady) 
     initVideos(); 
}); 

function onYouTubeIframeAPIReady() { 
    window.apiReady = true; 

    if (window.docReady) 
     initVideos(); 

    initVideos(); 
} 

function initVideos() { 

    if (typeof ytPlayerList === 'undefined') 
     return; 

    for (var i = 0; i < ytPlayerList.length; i++) { 
     var player = ytPlayerList[i]; 
     var pl = new YT.Player(player.DivId, { 
      playerVars: { 
       'autoplay': '0', 
       'controls': '1', 
       'autohide': '2', 
       'modestbranding': '1', 
       'playsinline': '1', 
       'rel': '0', 
       'wmode': 'opaque' 
      }, 
      videoId: player.VideoId, 
      events: { 
       'onStateChange': player.StateChangeHandler 
      } 
     }); 

     window[player.Id] = pl; 
    } 
} 

而且用戶控件:

window.ytPlayerList.push({ 
    Id: "<%=ClientID%>player", 
    DivId: "<%=ClientID%>player", 
    VideoId: "<%=VideoId%>", 
    StateChangeHandler: hide<%=ClientID%>Player 
}); 

function hide<%=ClientID %>Player(state) { 
    if (state.data == '0') { 
     hide<%=ClientID %>Video(); 
    } 
} 

function show<%=ClientID %>Video() { 
    $('#<%=ClientID %>video-modal').modal('show'); 
} 

function hide<%=ClientID %>Video() { 
    $('#<%=ClientID %>video-modal').modal('hide'); 
} 

$(document).ready(function() { 
    $("#<%=ClientID%>Video").click(function() { 
     show<%=ClientID%>Video(); 
    }); 

    $("#<%=ClientID %>video-modal").on('shown', function() { 
     window["<%=ClientID%>player"].playVideo(); 
    }); 

    $("#<%=ClientID %>video-modal").on('hide', function() { 
     window["<%=ClientID%>player"].pauseVideo(); 
    }); 
}); 

這可能是缺乏專業知識的js,但我絕對堅持。任何幫助將不勝感激。此外,作爲參考,我得到的例外是

Uncaught TypeError: window.ctl100_phContent_ctl100player.playVideo is not a function 
+0

是否故意在'onYouTubeIframeAPIReady()'函數中激發'initVideos()'兩次? –

+0

可能重複[.playVideo() - 不是一個函數?](http://stackoverflow.com/questions/2217543/cant-control-youtube-embed-even-with-document-getelementbyidxyz-playvideo)或[playVideo doesn 't work](http://stackoverflow.com/questions/9287170/youtube-player-iframe-api-playvideo-doesnt-work-on-firefox-9-0-1) –

+0

你可以粘貼一些生成的HTML請 ?這會讓我更容易重現這個問題。 –

回答

8

所以問題是,視頻僅獲得,當YouTube的API已經完成加載視頻元素playVideo()方法。這個視頻元素是異步加載的,因此代碼執行將繼續執行$(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> 

這給了我你所描述的同樣的錯誤。所以爲了測試我的理論(並確保沒有其他腳本錯誤),我這樣做了:

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; 
     } 
    } 

即假設你使用codegeneration創建類似的功能:

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(); 
    } 

所以這不是針對你的問題的複製粘貼解決方案,但應該讓你瞭解代碼不工作的原因。有可能更優雅的方式來實現你想要做的事情,但讓我們現在就保持簡單。

讓我知道它是否有效,或者如果您有任何其他問題。

+0

窗口在瀏覽器上不起作用 –