Skip to content

Instantly share code, notes, and snippets.

@haziqAhmed7
Last active October 10, 2015 23:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haziqAhmed7/772ca9e70706b2229ff5 to your computer and use it in GitHub Desktop.
Save haziqAhmed7/772ca9e70706b2229ff5 to your computer and use it in GitHub Desktop.
Play multiple videos without playlist in Youtube Iframe Api v3
/**
* The Functionality would be to Fetch the Playlist from the registered user
* then wrap the data into the Youtube Player and bind the event so that
* it can play the playlist according to the videos offset which are essential for this
* application
* Created by Haziq on 9/27/2015.
*/
//Variables to remember states
var data;
var playlist_name, date, count, tracks, start, end = [];
playlist_name = []; date = []; count = []; tracks = []; start = []; end = [];
//Youtube player array
var Player = [];
/**
* Getters and Setters for the global data containing server response
*/
function getData()
{
return data;
}
function setData(response)
{
data = response;
}
/**
* As the scripts function is dependent on the Api which will be fetched by the Youtube Server
* So we need a function that will authenticate that the script is downloaded and ready to use in
* order to fire our methods
* This function will basically wait for the script to download for this purpose recursive methods
* will be used for watitng along with the timeout functionality
* once the script has loaded the control will be headed towards the other core functions
*/
function authenticateScriptDownload()
{
//First initiate function to retrieve the script from the google
identify_library();
//wait until the script is fetched
setTimeout(function()
{
//check whether the script is loaded by checking the length of script tag and class object
if($.isFunction(YT.Player)) //if( typeof(YT.Player) != 'undefined' )
{
//our script is loaded and ready to use
console.log("Script is loaded");
//once the script is loaded call other script functions but first consider the response is loaded
if(getData().length > 0)
{
// use the setters to retrieve the script global property
refine(getData());
split_organize();
console.log(getData());
}
else
{
console.log("No response is provided against playlist tasks");
}
}
else
{
//Since the script is still loading we can wait
console.log("Script still loading");
authenticateScriptDownload();
}
}, 600);
}
/**
The Purpose of this function is to refine the ajax response , separate each field and save them into an
individual array.
Further more this function is also responsible for changing the DOM elements which are described as follow.
This function will create the child div for every playlist iteration in the main "Playlist" div.
the child div will contain heading (playlist name) and another div which will then be forwarded to the Youtube Api
for its processing
The id for the div which will be used by the youtube will start from 'p' followed by the playlist name.
*/
function refine(data)
{
//fetch every playlist in iteration
for(var i=0; i<data.length; i++)
{
//get Playlist Name, Date, count of songs in a playlist
console.log(data[i]['Name']);
playlist_name[i] = data[i]['Name'];
date[i] = data[i]['Date'];
count[i] = data[i]['Count'];
//initialize the variables to get the video offsets, codes from the individual playlist
var Start,End,Tracks = "";
//Get Playlist tracks
for(var j=0; j < parseInt(count[i]); j++)
{
//Get the video offsets, codes from the response
Start = data[i]['Tracks'][j]['StartTime'] + ',';
End = data[i]['Tracks'][j]['EndTime'] + ',';
Tracks = data[i]['Tracks'][j]['SongID'] + ',';
}
//Remove the last separators ',' from the data and save them in to the array for safe keeping
start[i] = Start.replace(/,\s*$/, "");
end[i] = End.replace(/,\s*$/, "");
tracks[i]= Tracks.replace(/,\s*$/, "");
//Create a new DOM element <div>, <p> tag and add it in the playlist <div>
var element = '<div id="'+playlist_name[i] + '" > <p > '+ playlist_name[i] + '<p/> <div id="v'+playlist_name[i]+
'" <div/> <div/>';
$("#Playlist").append(element);
}
}
/**
* The purpose of this function is to split the whole array into individual playlist so it the each player
* can have its own responsibility.
* The array which would be split will contain the songs ID, video offsets in an individual data structures
*/
function split_organize()
{
//Iterate through every index of playlist array and split this according to the total count of the array
//Actually as we created above the DOM elements so we would iterate the DOM elements instead of using the formal loop
//Initialize the indexer variable to iterate the values in the array
var counter = 0;
//Using the map function to iterate the inner child divs of the Playlist div
setTimeout(function()
{
//check whether the script is loaded by checking the length of script tag and class object
if($.isFunction(YT.Player) )
{
//our script is loaded and ready to use
$("#Playlist > div").map(function()
{
//Get the ID of every inner child
var id = this.id;
console.log("ID "+id);
var videoID = 'v' +id;
//Splitting of the array code starts here
var playlist_songs, video_start, video_end;
playlist_songs = tracks[counter];
video_start = start[counter];
video_end = end[counter];
//Instantiate player here and bind on the created div
console.log("Initializing objects");
$("#"+videoID).on( Create_Player(playlist_songs, video_start, video_end, counter, videoID) );
//increment the indexer value
counter++;
});
}
else
{
//Since the script is still loading we can wait
console.log("Script still loading and passed 1st iteration");
split_organize();
}
}, 300);
}
/**
The purpose of this function is to Instantiate the Youtube Player object in the inner child of the Playlist <div>
The object instantiated will be provided four arguments
1) list of video ID's
2) Each videos starting offset
3) Each videos ending offset
4) Current index of the playlist
5) ID of the DOM element in which the player object will reside
After passing the arguments in the object creation the next step would be to bind that object in an event
The binding will be against the onPlayerStateChange(event) event
*/
function Create_Player(songs, start, end, counter, element_id)
{
//create a property to iterate through next videos
var indexer = 0;
//create the property to record the previous index
var previous;
//remove the impurity and store them in an array
songs = songs.split(',');
start = start.split(',');
end = end.split(',');
//First check whether the library is available for creating Youtube object
identify_library();
//create the Youtube Player here specify height of the player and provide event function names
Player[counter] = new YT.Player(element_id,
{
height: '320',
width: '480',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
}); console.log('# '+ counter + Player[counter]);
//---event function-- When the player is ready fire this one
function onPlayerReady(event)
{
//load video by the Youtube api provided function accepted arguments are VideoID, Video offsets
Player[counter].loadVideoById( { 'videoId': songs[indexer],
'startSeconds':start[indexer],
'endSeconds': end[indexer]
});
//once all the arguments are supplied fire the method to start video
event.target.playVideo(); console.log("video is playing");
Player[counter].playVideo();
//record the indexer value
previous = indexer;
//Increment the indexer property so to play the next video.
indexer += 1;
}
//---event function-- When the player change state fire this one
function onPlayerStateChange(event)
{
//get current time of the playing video
var currentTime = Player[counter].getCurrentTime();
//check if the current time exceeds the video offset if so then load next video and update fields also check
//that if the indexer property exceeds the total length of the songs array if so then stop the player
if( (currentTime > end[indexer] || currentTime == end[indexer]) && indexer < songs.length )
{
//load next video and update the properties
Player[counter].stopVideo();
Player[counter].loadVideoById({
'VideoId':songs[indexer],
'startSeconds':start[indexer],
'endSeconds': end[indexer]
});
Player[counter].playVideo();
previous = indexer;
indexer += 1;
}
else if(indexer >= songs.length)
{
Player[counter].stopVideo();
}
}
}
/**
* The purpose of this function is to identify the availability of script tag from Youtube api
* if the tag exists then return false else create the tag and import the youtube api iframe library
*/
function identify_library()
{
//check the library existence
if($("#script").length)
{
console.log("Library exists");
//library exist
return false;
}
else
{
//library doesn't exist fetch the code from the Youtube
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
console.log("Library Fetched");
setTimeout(function(){}, 200);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment