samedi 25 juin 2016

Javascript Event Listener quits (?) from listening... Youtube API - No console error


EDIT - 2016-06-25
(I removed my june 16th update, since not relevant anymore.
   I left my OP below...)



I've passed another 4 hours on this today.
Here is the situation now:

My function WORKS for two links.
The video params are defined in an array.
The two other links aren't working.

I get a Uncaught TypeError: thisPlayer.loadVideoById is not a function for links #3 and #4.
BUT THE SAME function works good for links #1 and #2.

Seems like the youtube objects are not defined for these two.
WHY?

Please, have a close look to the console on this live link:
https://www.bessetteweb.com/?p=youtube-video-test
I inserted A LOT of console.logs to make it clear.

Here is my actual code:

// 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);    // SetTimeout de l'interval
        });
    }
}

// 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);



Here is a snapshot of my console log: Console-log



-----------------
Here is my original post - june 14th :

I spent 6 hours on this already.
(plus 1 editing this question!)

I'm kind of debugging the last 4 lines of it.

Problem is that I get NO console error as a hint.



Concept:
I want to link numerous Youtube videos to text links.
The wanted effect for the user is to be able to click on a citation link while reading a text... In order to be able to confirm the citation.
The video has NOT to play entirely.

The video shall start at a specific timecode AND end at a specific timecode.
Bonus complexity: All this is wanted to be shown in a modal view style.

My code WORKED quite fast for ONE video. See here.

I based my code on this tutorial and succedded real fast.

Then, having this working...
I had the need to build arrays to handle multiple videos.
For links ids, players ids, timecodes for start/end... AND LISTENERS!
Fun begins!

Like said, I spent most of my day on this. I always encountered bugs WITH console errors as clear (LOLLL) guides.

I am satisfied of my work... This is going in the right direction I think.
This is almost working...


But this time, no errors! See here. (check the console!)

WHATT!!! NO ERROR?!?
My arms are hacked off now.
In fact, the 1st shows but video doesn't start... And the second looks to be completely lost in the haze.

In console log messages, I see the 1st occurance of the onStateChange listener, wich is -1 (Unstarted). But then ??? It dies!
Arrgg!

I have to overstep my pride... And bring it as a question on StackOveflow.
;)



My full code (for multiple links):
This is a page called via ajax... So all external ressources like jQuery are already loaded.

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

Aucun commentaire:

Enregistrer un commentaire