YouTube Playlist Embed Script for Multiple Playlists on a Single Page (jQuery/CSS/HTML + CodePen)

Viewed 1990

I'm about half-way there. I am using a script which allows you to embed a YouTube playlist to any web page, using JQuery, CSS, and HTML.

The code works well, but the only issue is that I am unsure how to implement more than one playlist on a single web page at a time.

I have developed a codepen (below) which presents the main issue at hand.

There are currently three playlists, but only the first one displays, while the other two don't appear at all. Not sure if this has anything to do with YouTube's API, a script configuration, or otherwise.

Can anybody help me out?

Reference: https://codepen.io/anon/pen/NaygEm

(function() {

    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0]; //Find the first script tag in the html
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); //Put this script tag before the first one

    var player; //The Youtube API player
    var playlistID = $('#ytpl-player').data('pl');
    var $ul = $('#ytpl-thumbs');
    var nowPlaying = "ytpl-playing";
    var nowPlayingClass = "." + nowPlaying;

    function getPlaylistData() {

        var apiKey = 'AIzaSyDI4rWo_wVAxRZEIgF6_8sRZDj8OCOZZ38';
        var url = 'https://www.googleapis.com/youtube/v3/playlistItems?part=snippet';
        var data = {
            'playlistId': playlistID,
            'key': apiKey,
            'maxResults': 4
        }

        $.get(url, data, function(e) {
            buildHTML(e.items)
        })

    }

    function buildHTML(data) {

        var list_data = '';

        data.forEach(function(e, i) {
            var item = e.snippet;

            if (item.thumbnails) {
                list_data += '<li><button data-ytpl-index="'+ i +'" data-ytpl-title="' + item.title + '" data-ytpl-desc="' + item.description + '"><p>' + item.title + '</p><img alt="'+ item.title +'" src="'+ item.thumbnails.medium.url +'"/></button></li>';
            }

        })

        $ul.html(list_data);
        //
        // $('.ytpl-flexslider').flexslider({
        //  animation: "slide",
        //  startAt: 0,
        //  slideshow: false,
        //  touch: true,
        //  prevText: "",
        //  itemWidth: "25%",
        //  nextText: "",
        //  pausePlay: !0,
        //  pauseText: "Pause",
        //  playText: "Play",
        //  pauseOnHover: !0,
        //  useCSS: true
        // })

    }

    // generate playlist items once main player has loaded
    function onPlayerReady(event) {
        getPlaylistData();
    }

    window.onYouTubeIframeAPIReady = function() {

        var player = new YT.Player('ytpl-player', {
            height: '360',
            width: '640',
            playerVars: {
                listType:'playlist',
                list: playlistID
            },
            events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange
            }
        });

        function updateTitles($this) {

            $('#ytpl-title').text( $this.data('ytpl-title') )
            $('#ytpl-desc').text( $this.data('ytpl-desc') )

        }


        function onPlayerStateChange(e) {

            var $buttons = $ul.find('button');
            var currentIndex = player.getPlaylistIndex();

            // remove existing active class, add to currently playing
            if (e.data === YT.PlayerState.PLAYING) {
                $buttons.removeClass(nowPlaying);
                $buttons.eq(currentIndex).addClass(nowPlaying);
            }

            // if last video has finished playing
            if (e.data === YT.PlayerState.ENDED && currentIndex === $buttons.length - 1) {
                $buttons.removeClass(nowPlaying);
            }

            updateTitles($buttons.eq(currentIndex))
        }

        // handle playlist button click
        $(document).on('click', '[data-ytpl-index]:not(".ytpl-playing")',function(e) {
            e.preventDefault();

            var $this = $(this);

            var index = $this.data('ytpl-index');

            updateTitles($this);

            if (navigator.userAgent.match(/(iPad|iPhone|iPod)/g)) {

                player.cuePlaylist({
                    listType: 'playlist',
                    list: playlistID,
                    index: index,
                    suggestedQuality: 'hd720' //quality is required for cue to work, for now. https://code.google.com/p/gdata-issues/issues/detail?id=5411
                });

            } else {
                player.playVideoAt(index); //Play the new video, does not work for IOS 7
            }

        });
    };
})();
1 Answers

You're using the same id for multiple div. You can only specify a unique id. You can use class instead of id for ytpl-thumbs and use unique id for each players :

Check this fiddle

HTML

<div class="sidebar">
  <h1>Playlist (1): Birds</h1>
  <div class="container">
    <div class="ypt_wrapper">
      <div class="video embed-container">
        <div id="ytpl-player1" data-pl="PLBhKKjnUR0XB8DwQwXqBsChb48E8jzfr-">
        </div>
      </div>
      <div>
        <h2 class="ytpl-title"></h2>
        <div class="ytpl-desc"></div>
      </div>
      <div class="ytpl-flexslider">
        <ul class="ytpl--thumbs slides"></ul>
      </div>
    </div>
  </div>
</div>

<div class="sidebar">
  <h1>Playlist (2): Owls</h1>
  <div class="container">
    <div class="ypt_wrapper">
      <div class="video embed-container">
        <div id="ytpl-player2" data-pl="PLBhKKjnUR0XAM2Wvi7JY5gLRpFLzIE-An">
        </div>
      </div>
      <div>
        <h2 class="ytpl-title"></h2>
        <div class="ytpl-desc"></div>
      </div>
      <div class="ytpl-flexslider">
        <ul class="ytpl--thumbs slides"></ul>
      </div>
    </div>
  </div>
</div>

<div class="sidebar">
  <h1>Playlist (3): Misc. Animals</h1>
  <div class="container">
    <div class="ypt_wrapper">
      <div class="video embed-container">
        <div id="ytpl-player3" data-pl="PLBhKKjnUR0XCGuLxsESq7WMlIwZIH9tIi">
        </div>
      </div>
      <div>
        <h2 class="ytpl-title"></h2>
        <div class="ytpl-desc"></div>
      </div>
      <div class="ytpl-flexslider">
        <ul class="ytpl--thumbs slides"></ul>
      </div>
    </div>
  </div>
</div>

Javascript

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

var players = new Array();
var players_list = ["ytpl-player1", "ytpl-player2", "ytpl-player3"];

var nowPlaying = "ytpl-playing";
var nowPlayingClass = "." + nowPlaying;

function getPlaylistData(playerName) {
    var apiKey = 'AIzaSyDI4rWo_wVAxRZEIgF6_8sRZDj8OCOZZ38';
    var url = 'https://www.googleapis.com/youtube/v3/playlistItems?part=snippet';
    var data = {
        'playlistId': $('#' + playerName).data('pl'),
        'key': apiKey,
        'maxResults': 4
    };

    $.get(url, data, function(e) {
        buildHTML(playerName, e.items)
    })
}

function buildHTML(playerName, data) {
    var list_data = '';
    data.forEach(function(e, i) {
        var item = e.snippet;
        if (item.thumbnails) {
            list_data += '<li><button data-ytpl-index="' + i + '" data-ytpl-title="' + item.title + '" data-ytpl-desc="' + item.description + '"><p>' + item.title + '</p><img alt="' + item.title + '" src="' + item.thumbnails.medium.url + '"/></button></li>';
        }
    });
    $('#' + playerName).closest('.ypt_wrapper').find('.ytpl--thumbs').html(list_data);
}

// generate playlist items once main player has loaded
function onPlayerReady(event) {
    getPlaylistData(event.target.name);
}

function onYouTubeIframeAPIReady() {
    for (item in players_list) {
        players[players_list[item]] = new YT.Player(players_list[item], {
            height: '360',
            width: '640',
            playerVars: {
                listType: 'playlist',
                list: $('#' + players_list[item]).data('pl')
            },
            events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange
            }
        });
        players[players_list[item]].name = players_list[item];
    }
}

function updateTitles($this) {
    $('#ytpl-title').text($this.data('ytpl-title'))
    $('#ytpl-desc').text($this.data('ytpl-desc'))
}

function onPlayerStateChange(event) {
    var $buttons = $('#' + event.target.name).closest('.ypt_wrapper').find('.ytpl--thumbs').find('button');

    var currentIndex = event.target.getPlaylistIndex();

    // remove existing active class, add to currently playing
    if (event.data === YT.PlayerState.PLAYING) {
        $buttons.removeClass(nowPlaying);
        $buttons.eq(currentIndex).addClass(nowPlaying);
    }

    // if last video has finished playing
    if (event.data === YT.PlayerState.ENDED && currentIndex === $buttons.length - 1) {
        $buttons.removeClass(nowPlaying);
    }
    updateTitles($buttons.eq(currentIndex))
}

// handle playlist button click
$(document).on('click', '[data-ytpl-index]:not(".ytpl-playing")', function(e) {
    e.preventDefault();
    var $this = $(this);
    var index = $this.data('ytpl-index');
    var playerName = $(this).closest('.ypt_wrapper').find('iframe').attr('id');
    updateTitles($this);

    if (navigator.userAgent.match(/(iPad|iPhone|iPod)/g)) {
        players[playerName].cuePlaylist({
            listType: 'playlist',
            list: $('#' + players_list[playerName]).data('pl'),
            index: index,
            suggestedQuality: 'hd720'
        });
    } else {
        players[playerName].playVideoAt(index); //Play the new video, does not work for IOS 7
    }
});
Related