2015-04-17 25 views
17

Mam problem z następującym kodem, ale nie jestem pewien, gdzie jest problem.Ładowanie wielu filmów z YouTube iFrame API

Na mojej stronie wzorcowej, w javascript, mam tablicę zdefiniowaną do przechowywania listy utworzonych obiektów YouTubePlayer. Również ładuję interfejs YouTube API tutaj.

Posiadam również (czasami kilka) kontrolki użytkownika YouTube, które zawierają element div YouTube w modcie początkowym. Zawiera również JavaScript do przesuwania nowego obiektu YouTubePlayer do tablicy w stronie głównej js. Na koniec, na sterowaniu użytkownika, definiuję metody automatycznego uruchamiania i zatrzymywania wideo w "pokazanych" i "ukrytych" zdarzeniach modemu ładowania początkowego.

Na koniec, aby (miejmy nadzieję) rozwiązać warunek wyścigu między ładowanym dokumentem i ładowanym API YouTube, ustawiam dwie zmienne bool (jedną dla dokumentu, jedną dla API) i sprawdzam prawdziwe dla wszystkich przed wywołaniem initVideos funkcja, która iteruje przez tablicę obiektów YouTubePlayer i inicjuje je, ustawiając obiekt w oknie. Częścią problemu, jak sądzę, jest to, że nie mogę statycznie ustawić window.player1 itp., Ponieważ nigdy nie wiem, ile elementów sterujących YouTube zostanie załadowanych.

Problem jest, gdy ogień bootstrap modalne imprezy, obiekt YT.Player odzyskać z okna nie zawiera metody playVideo() i pauseVideo().

Na mojej stronie wzorcowej:

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

A w sprawie kontroli użytkownika:

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

To może być brak wiedzy js, ale jestem całkowicie zatrzymany. Każda pomoc będzie bardzo ceniona. Ponadto, dla odniesienia, wyjątek mogę to

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

Czy celowe jest uruchamianie 'initVideos()' dwukrotnie w funkcji 'onYouTubeIframeAPIReady()'? –

+0

możliwy duplikat [.playVideo() - nie funkcja?] (Http://stackoverflow.com/questions/2217543/cant-control-youtube-embed-even-with-document-getelementbyidxyz-playvideo) lub [playVideo doesn 't work] (http://stackoverflow.com/questions/9287170/youtube-player-iframe-api-playvideo-doesnt-work-on-firefox-9-0-1) –

+0

Czy możesz wkleić część wygenerowanego HTML Proszę ? Ułatwi mi to odtworzenie problemu. –

Odpowiedz

8

Więc problem jest, że film staje się jedynie, że playVideo() metoda gdy API YouTube zakończeniu ładowania elementu wideo. Ten element wideo jest ładowany asynchronicznie, więc wykonanie kodu będzie kontynuowane z kodem jQuery $(document).ready(function() {, gdzie spróbuje dołączyć funkcje playVideo(), które w tym momencie - jeszcze nie istnieją.

Mam powielana tego błędu w danej strony 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> 

To daje mi ten sam błąd opisania. Aby przetestować moją teorię (i upewnić się, że nie było innych błędów skryptu), zrobiłem to:

setTimeout(function() { 
     window.ctl100_phContent_ctl100player.playVideo() 
}, 1000); 

To zadziałało. Tak naprawdę to wydaje się problem. Jednakże - nie wiemy na pewno, że 1000ms wystarczy, aby zagwarantować, że odtwarzacz zostanie zainicjowany.Więc co można zrobić - jeśli chcesz nie byłaby zbyt dużo - to zacząć słuchać na onready wydarzeń zawodnik:

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

który zakłada użyłeś codegeneration stworzyć funkcje, takie jak:

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

To nie jest rozwiązanie problemu z kopiowaniem i wklejaniem, ale powinno dać ci wgląd w to, dlaczego kod nie działa. Prawdopodobnie istnieją bardziej eleganckie sposoby osiągnięcia tego, co próbujesz zrobić, ale na razie trzymajmy prostą łatę.

Daj mi znać, jeśli zadziała, lub jeśli masz inne pytania.

+0

Okno nie działa na eksploratorze –

Powiązane problemy