2016-06-14 77 views
6

编辑 - 2016年6月25日
(我打消了我6月16日更新,因为不再相关
 。     我离开了我下面的OP ...)JavaScript事件监听器退出从听... YouTube的API(?) - 无控制台错误



我花了4小时今日上。
现在情况如下:

我的功能作品两个链接。
视频参数在数组中定义。
其他两个链接不起作用。

对于链接#3和#4,我得到一个Uncaught TypeError: thisPlayer.loadVideoById is not a function
但是,相同的功能适用于链接#1和#2。

看起来像youtube对象只是定义了两个第一。
为什么?

请,有一个近距离观察到控制台这个活链接:
https://www.bessetteweb.com/?p=youtube-video-test
我插入的console.log messagess的很多讲清楚。

这里是我的实际代码:

// Global variable for the player 
var player = []; 
var statePlaying=false; 

playerArr = [{ 
      linkID:"link0", 
      divID:"player1", 
      ytID:"5V_wKuw2mvI", // Heavy metal playlist 
      start:20, 
      end:30 
      }, 
      { 
      linkID:"link1", 
      divID:"player2", 
      ytID:"u9Dg-g7t2l4", // Disturbed 
      start:10, 
      end:20 
      }, 
      { 
      linkID:"link2", 
      divID:"player3", 
      ytID:"39b5v3-d6ZA", // Maiden 
      start:30, 
      end:40 
      }, 
      { 
      linkID:"link3", 
      divID:"player4", 
      ytID:"z8ZqFlw6hYg", // Slayer 
      start:120, 
      end:136 
      }]; 

// This function gets called when API is ready to use 
function onYouTubePlayerAPIReady() { 

    // Binding events loop 
    console.log("playerArr.length: "+playerArr.length); 
    for(i=0;i<playerArr.length;i++){ 
     console.log(""); 
     console.log("onPlayerReady for loop ->i: "+i); 

     var playButton = document.getElementById(playerArr[i].linkID); 
     console.log("playButton.id: "+playButton.id); 

     var thisArr = playerArr[i]; 
     console.log("playerArr[i] object (below): "); 
     console.log(thisArr); 

     playButton.addEventListener("click", function() { 
      thisLinkID = $(this).attr("id").replace("link",""); 

      console.log(""); 
      console.log("------------------"); 
      console.log("Link #"+(parseInt(thisLinkID)+1)+" clicked."); 
      console.log("------------------"); 

      var ytID = playerArr[thisLinkID].ytID; 
      var start = playerArr[thisLinkID].start; 
      var end = playerArr[thisLinkID].end; 

      var thisPlayer = new YT.Player(playerArr[thisLinkID].divID); 

      console.log("ytID: "+ytID); 
      console.log("start: "+start); 
      console.log("end: "+end); 
      console.log(""); 

      console.log("Below are the google ads, blocked by AdBlocker."); 

      $("#ytplayerModal").css({"display":"block"}); 
      $("#ytplayerModal").animate({"opacity":"0.7"},1000,function(){ 

       console.log(""); 
       console.log("player show()"); 
       $(".ytplayer").show(); 

       console.log("Youtube player object:"); 
       console.log(thisPlayer); 
       console.log(""); 
       console.log('loadVideoById() parameters --\> videoId:'+ytID+', startSeconds:'+start+', endSeconds:'+end); 

       thisPlayer.loadVideoById({'videoId':ytID, 'startSeconds':start, 'endSeconds':end}); 
       console.log(""); 
      }); 

      // Bugfix - Set Interval instead of listener 
      setTimeout(function(){ 
       var IntervalCounter=0; 
       listenerInterval = setInterval(function() { 

        var state = thisPlayer.getPlayerState(); //player[thisLinkID].getPlayerState(); 
        var stateMsg; 

        switch (state){ 
         case -1: stateMsg="unstarted"; thisPlayer.playVideo(); console.log("player["+thisLinkID+"]"); break; 
         case 0: stateMsg="ended"; break; 
         case 1: stateMsg="playing"; break; 
         case 2: stateMsg="paused"; break; 
         case 3: stateMsg="buffering"; break; 
         case 5: stateMsg="video cued"; break; 
         default: stateMsg="Undefined player state..."; 
        } 
        console.log(state+" : "+stateMsg); 

        if(state==1){ 
         statePlaying=true; 
        } 

        // Closes the modal 
        if((statePlaying) && (state==0)){ 
        //if((statePlaying) && (stateObj.data==0)){ 
         setTimeout(function(){ 
          console.log("Closing Modal"); 
          $(".ytplayer").css({"display":"none"}); 
          $("#ytplayerModal").animate({"opacity":"0"},1000,function(){ 
           $("#ytplayerModal").css({"display":"none"}); 
          }); 
          statePlaying=false; 
         },500); 
         clearInterval(listenerInterval); 
         console.log("Interval loop stopped on video end.") 
        } 

        // Stop the interval at 1000... Endless instead! 
        IntervalCounter++; 
        if((IntervalCounter>999)&&(state!=1)&&(state!=2)&&(state!=0)){ 
         clearInterval(listenerInterval); 
         console.log("Interval loop willingly stopped. Endless otherwise.") 
        } 
       }, 10); 
      },1100); // Interval setTimeout 
     }); 
    } 
} 

// Inject YouTube API script 
var tag = document.createElement('script'); 
tag.src = "//www.youtube.com/player_api"; 
var firstScriptTag = document.getElementsByTagName('script')[0]; 
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 



这里是我的控制台日志的快照: Console-log



--------- --------
他重新是我的原始后 - 6月14日:

我已经花了6个小时了。
(加1编辑这个问题!)

我有种调试的最后4行吧。

问题是我得到NO控制台错误作为提示。



理念:
我要链接众多YouTube视频到文本链接。
用户想要的效果是能够在阅读文本时点击引文链接...为了能够确认引文。
视频不能完全播放。

视频应以特定的时间码开始并以特定的时间码结束。
奖励复杂度:所有这些都希望以模态视图样式显示。

我的代码WORKED相当快为ONE视频。 See here

我基于我的代码this tutorial,并迅速成功。

然后,将具有这方面的工作...
我有必要建立阵列来处理多个视频。
对于链接ID,玩家ID,开始/结束的时间码...和听众!
有趣的开始!

就像这样说,我在这一天度过了大半天。 我总是遇到错误作为明确(LOLLL)指南的控制台错误。

我对我的工作感到满意......这是我认为正确的方向。
这几乎是工作...


但是这一次,没有任何错误! See here(检查控制台!)

热点问题研究!没有错误?!?
我的手臂现在被砍掉。
事实上,第一场表演,但视频没有开始......第二个看起来完全迷失在阴霾中。

在控制台日志消息中,我看到第一个发生的onStateChange侦听器,它是-1(未启动)。但是之后 ???它死了!
Arrgg!

我不得不超越我的骄傲......并把它作为一个问题在StackOveflow。
;)



我的全代码(多链路):
这是一个通过AJAX ......因此,所有外部ressources如jQuery已经载入称为页。

<style> 
.ytplayer{ 
    position:fixed; 
    z-index:2; 
    width:60%; 
    height:40%; 
    top:30%; 
    left:20%; 
    display:none; 
} 
#ytplayerModal{ 
    display:none; 
    background-color:#000; 
    opacity:0; 
    position:fixed; 
    z-index:1; 
    top:0; 
    left:0; 
    width:100%; 
    height:100%; 
} 
.ytTriggerPlay{ 
    text-decoration:underline; 
    color:dodgerblue; 
    cursor:pointer; 
} 
</style> 



<h1>Youtube modal trigger link test</h1> 
<br> 
<br> 
<div id="text"> 
    Lorem ipsum dolor sit amet, consectetur <a id="0" class="ytTriggerPlay">adipiscing elit</a>. Quisque feugiat lectus ut est vestibulum ornare. Vivamus felis nulla, facilisis id cursus non, pharetra non diam. Sed pellentesque turpis vel sem tincidunt consectetur. Aenean ut lorem erat. Donec ut tellus sed leo ultrices cursus. <a id="1" class="ytTriggerPlay">Cras varius libero</a> ut purus suscipit ultrices. Vivamus eget efficitur turpis. Aenean suscipit, dui nec luctus fringilla, neque tellus fringilla risus, et porta enim justo et turpis. Sed risus orci, vehicula sed eleifend eget, tincidunt ut turpis. Vestibulum in sapien non lacus tristique mattis id eget tortor.<br> 
    <br> 
    Proin est purus, maximus id nunc vel, consectetur tristique urna. Mauris cursus ipsum a varius luctus. Nunc interdum condimentum massa vitae rutrum. Morbi volutpat nec lorem eleifend malesuada. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis fringilla metus vel nunc elementum efficitur. Duis sed dolor diam. In eu ultrices libero, eget lobortis mi. Sed pretium orci non augue vehicula, eget placerat leo lacinia. Sed sed gravida dui. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In bibendum, erat eget venenatis elementum, nulla enim posuere lacus, quis efficitur dolor ex quis ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Phasellus volutpat finibus odio id venenatis. Fusce at leo libero. Cras eget velit sed justo egestas vehicula efficitur sit amet ex.<br> 
</div> 

<!--iframe id="ytplayer" type="text/html" width="720" height="405" src="https://www.youtube.com/embed/5V_wKuw2mvI?end=60&start=20" frameborder="0" allowfullscreen--> 

<div id="ytplayerModal"></div> 
<div id="player1" class="ytplayer"></div> 
<div id="player2" class="ytplayer"></div> 

<script> 
// https://developers.google.com/youtube/iframe_api_reference 
// https://css-tricks.com/play-button-youtube-and-vimeo-api/ 

// Global variable for the player 
var player = []; 
var statePlaying=false; 

playerArr = [{ 
      linkID:"0", 
      divID:"player1", 
      ytID:"5V_wKuw2mvI", // Heavy metal playlist 
      start:20, 
      end:40, 
      }, 
      { 
      linkID:"1", 
      divID:"player2", 
      ytID:"39b5v3-d6ZA", // Maiden 
      start:30, 
      end:60, 
      }]; 

// This function gets called when API is ready to use 

function onYouTubePlayerAPIReady() { 
    for(i=0;i<playerArr.length;i++){ 
     // Create the global player from the specific iframe (#video) 
     thisPlayer = new YT.Player(playerArr[i].divID, { 
      height: '352', 
      width: '640', 
      videoId: '5V_wKuw2mvI', 
      startSeconds:20, 
      endSeconds:40, 
      events: { 
       // Call this function when player is ready to use 
       // 'onReady': onPlayerReady   // Commented out willingly. 
      } 
     }); 
     player[i] = thisPlayer; 

    } 
    onPlayerReady(); 
} 

function onPlayerReady(event) { 

    // Binding events loop 
    console.log("playerArr.length: "+playerArr.length); 
    for(i=0;i<playerArr.length;i++){ 
     console.log(""); 
     console.log("onPlayerReady for loop ->i: "+i); 

     var playButton = document.getElementById(playerArr[i].linkID); 
     console.log("playButton.id: "+playButton.id); 

     var thisArr = playerArr[i]; 
     console.log("playerArr[i] object (below): "); 
     console.log(thisArr); 

     var thissPlayer = player[i]; 

     playButton.addEventListener("click", function() { 
      thisLinkID = parseInt($(this).attr("id")); 
      console.log("thisLinkID: "+thisLinkID); 

      var ytID = playerArr[thisLinkID].ytID; 
      var start = playerArr[thisLinkID].start; 
      var end = playerArr[thisLinkID].end; 

      console.log("ytID: "+ytID); 
      console.log("start: "+start); 
      console.log("end: "+end); 
      console.log("thissPlayer object (below): "); 
      console.log(thissPlayer); 

      $("#ytplayerModal").css({"display":"block"}); 
      $("#ytplayerModal").animate({"opacity":"0.7"},1000,function(thissPlayer,ytID,start,end){ 
       $(".ytplayer").show(); 

       player[thisLinkID].loadVideoById({videoId:ytID, startSeconds:start, endSeconds:end}); 
       setTimeout(function(){ 
        player[thisLinkID].playVideo(); 
       },500); 
      }); 
     }); 



     thissPlayer.addEventListener("onStateChange", function(stateObj){ 
      console.log("Player State: "+stateObj.data); 
      console.log("Again, thissPlayer object in the onStateChange listener (below)."); 
      console.log(thissPlayer); 
      // State sequence : -1, 3, 1, 2, 0, which is: Unstarted, Buffering, Playing, Paused, Ended. 

      if(stateObj.data==1){ 
       statePlaying=true; 
      } 
      console.log("Player State bolean memory: "+statePlaying); 

      // Closes the modal 
      if((statePlaying) && (stateObj.data==0)){ 
       setTimeout(function(){ 
        console.log("Closing Modal"); 
        $(".ytplayer").css({"display":"none"}); 
        $("#ytplayerModal").animate({"opacity":"0"},1000,function(){ 
         $("#ytplayerModal").css({"display":"none"}); 
        }); 
        statePlaying=false; 
       },500); 
      } 
     }); 
    } 
} 

// Inject YouTube API script 
var tag = document.createElement('script'); 
tag.src = "//www.youtube.com/player_api"; 
var firstScriptTag = document.getElementsByTagName('script')[0]; 
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 
</script> 

回答

7

有使用iframe Player API的暂时性问题,你可以读到这里:https://code.google.com/p/gdata-issues/issues/detail?id=4706

作为一个临时的解决办法,你只需要在onReady事件中添加事件侦听器:

function onReady() { 
player.addEventListener('onStateChange', function(e) { 
console.log('State is:', e.data); 
}); 
} 

此外,正如Google代码问题主题中提到的人,您设置一个时间间隔并轮询播放器的当前状态,而不是侦听onStateChange事件。以下是一个示例代码片段:

setInterval(function() { 
var state = player.getPlayerState(); 
if (playerState !== state) { 
onPlayerStateChange({ 
data: state 
}); 
} 
}, 10); 
+0

看起来像是找到我的修复程序的正确线索。我必须先尝试才能接受。但是,由于它看起来很严肃,我赞成它。我有一个30分钟开始的晚间会议......所以我会认真检查一下。谢谢! –

+0

不用担心队友! –

+0

我尝试了这个间隔的想法...我现在得到一些新的东西。但我仍然在树林里。现在我得到playerState = 5(视频提示)1秒。然后3(缓冲)80毫秒。在此之后,时间间隔不断计算,玩家状态在-1(未启动)上被阻塞。请参阅我的[正在进行中的工作链接](https://www.bessetteweb.com/?p=youtube-video-test)上的控制台我将编辑该问题以显示我的修改后的代码。 –