Javascript事件监听器从监听中退出(?)… Youtube API – 没有控制台错误

编辑 – 2016-06-25
(我删除了我的6月16日更新,因为不再相关。
我把OP留在了……)

我今天又花了4个小时。
现在情况如下:

我的函数适用于两个链接。
video参数在数组中定义。
另外两个链接不起作用。

我得到一个Uncaught TypeError: thisPlayer.loadVideoById is not a function链接#3和#4 Uncaught TypeError: thisPlayer.loadVideoById is not a function
但是相同function对链路#1和#2有效。

似乎youtube对象仅为两个第一个定义。
为什么?

请仔细查看此实时链接上的控制台:
https://www.bessetteweb.com/?p=youtube-video-test
我插入了很多console.log消息来说清楚。

这是我的实际代码:

 // 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;ii: "+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); 

这是我的控制台日志的快照: 控制台日志

—————–
这是我原来的post – 6月14日:

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

我有点调试它的最后4行。

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

概念:
我想将许多Youtubevideo链接到文本链接。
用户想要的效果是能够在阅读文本时点击引文链接…以便能够确认引文。
该video无法完全播放。

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

对于一个video, 我的代码工作得非常快。 看到这里

我将我的代码基于本教程 ,并且快速成功。

然后,这个工作……
我需要构建数组来处理多个video。
对于链接ID,玩家ID,开始/结束的时间码……和听众!
好玩开始了!

就像说的那样,我大部分时间都花在这上面。 我总是遇到错误控制台错误作为清除(LOLLL)指南。

我对自己的工作感到满意……我认为这是正确的方向。
这几乎正​​在……

但这一次,没有错误! 看到这里 。 (检查控制台!)

热点问题研究! 没有错误?!?
我的arm现在被砍掉了。
事实上,第一个节目但是video没有开始…而第二个看起来完全迷失在阴霾中。

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

我必须超越自己的骄傲……并将其作为StackOveflow上的一个问题。
;)

我的完整代码(适用于多个链接):
这是一个通过ajax调用的页面…所以所有外部资源如jQuery都已经加载了。

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

Youtube modal trigger link test



Lorem ipsum dolor sit amet, consectetur adipiscing elit. 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. Cras varius libero 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.

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.
// 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;ii: "+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);

您可以在此处阅读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 Code Issue Thread中提到的那样,您设置一个间隔并轮询播放器的当前状态,而不是监听onStateChange事件。 以下是执行此操作的示例代码段:

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