Question

I want to access and view public Youtube videos (simple read only) from any Youtube channel without resorting to Oauth, just with plain API key. I haven't found a decent layman example on how to go about with API v3 ;-(

I have this to juggle with which I cannot get to work. Basically, a Select menu contains options whose values are existing channel IDs. When an option containing a channel ID is selected, it should trigger requestUserUploadsPlaylistId(). Then, when NEXTbutton or PREVIOUSbutton are activated, function requestVideoPlaylist() would kick in. Is there a better way to do this? I get the following error messages in Firebug:

TypeError: response.result is undefined (When I choose an option from SELECTmenu). TypeError: response.result is undefined (After I click on buttons).

Here is what I am struggling with (am new to API v3 and kinda used to API v2 (sigh)):

<HTML is here>

script>
$('#NEXTbutton').prop('disabled', true).addClass('disabled');
</script>

<script type="text/javascript" src="https://apis.google.com
/js/client.js?onload=onJSClientLoad"></script>

<script>

var dd, playlistId, nextPageToken, prevPageToken;

function onJSClientLoad() {
gapi.client.setApiKey('YOUR-API-KEY');
gapi.client.load('youtube', 'v3', function(){
$('#NEXTbutton').prop('disabled', false).removeClass('disabled');
});
}

// Calling the following function via selected option value of select menu
// I am using "mine: false," since it's an unauthenticated request ?? 

function requestUserUploadsPlaylistId() {
var dd = $("#SELECTmenu option:selected").val();
var request = gapi.client.youtube.channels.list({
mine: false, // is this legit?
channelId: dd, // Variable is preset chosen value of SELECTmenu options
part: 'contentDetails,id'
});
request.execute(function(response) {
playlistId = response.result.items[0].contentDetails.relatedPlaylists.uploads;
channelId = response.result.items[0].id;
});
}

function requestVideoPlaylist(playlistId, pageToken) {
var requestOptions = {
playlistId: playlistId,
part: 'snippet,id',
maxResults: 5
};
if (pageToken) {
requestOptions.pageToken = pageToken;
}
var request = gapi.client.youtube.playlistItems.list(requestOptions);
request.execute(function(response) {

// Only show the page buttons if there's a next or previous page.
nextPageToken = response.result.nextPageToken;
var nextVis = nextPageToken ? 'visible' : 'hidden';
$('#NEXTbutton').css('visibility', nextVis);
prevPageToken = response.result.prevPageToken
var prevVis = prevPageToken ? 'visible' : 'hidden';
$('#PREVIOUSbutton').css('visibility', prevVis);

var playlistItems = response.result.items;
if (playlistItems) {

$.each(playlistItems, function(index, item) {
displayResult(item.snippet);
});

} else {
$('#CONTAINER').html('Sorry, no uploaded videos available');
}
});
}

function displayResult(videoSnippet) {

for(var i=0;i<response.items.length;i++) {
var channelTitle = response.items[i].snippet.channelTitle
var videoTitle = response.items[i].snippet.title;
var Thumbnail = response.items[i].snippet.thumbnails.medium.url;

var results = '<li><div class="video-result"><img src="'+Thumbnail+'" /></div>
<div class="chantitle">'+channelTitle+'</div>
<div class="vidtitle">'+videoTitle+'</div></li>';   

$('#CONTAINER').append(results);
}
}

function nextPage() {
requestVideoPlaylist(playlistId, nextPageToken);
}
function previousPage() {
requestVideoPlaylist(playlistId, prevPageToken);
}

$('#NEXTbutton').on('click', function() { // Display next 5 results
nextPage();
});
$('#PREVIOUSbutton').on('click', function() { // Display previous 5 results
previousPage();
});

$("#SELECTmenu").on("change", function() {
$('#CONTAINER').empty();
if ($("#SELECTmenu option:selected").val().length === 24) { //Channel ID length
requestUserUploadsPlaylistId();
} else {
return false;
}
});

I'm surely missing something here, any pointers will be greatly appreciated.

Was it helpful?

Solution

FINAL UPDATE

A few updates later and I've finally answered my question after playing with the awesome Google APIs Explorer tool. Here is a sample working code allowing access to Youtube channel video-related data from a Select menu for read-only without using OAUTH, just an API key. The Select menu, based on a selected option's value (which contains a channel id), posts a video thumbnail, the thumbnail's channel origin; and the video's title. Should be easy to make the thumbnail clickable so as to load video in iframe embed or redirect to Youtube page. Enjoy!

// Change values and titles accordingly
<select id="SELECTmenu">
<option value="selchan">Select channel ...</option>
<option value="-YOUR-24digit-ChannelID-">Put-channel-title-here</option>
<option value="-YOUR-24digit-ChannelID-">Put-channel-title-here</option>
</select>

<button id="NEXTbutton">NEXT</button>
<button id="PREVIOUSbutton">PREV</button>

<ol id="CONTAINER"></ol> // Loads video data response

<script type="text/javascript"
src="https://apis.google.com/js/client.js?onload=onJSClientLoad">
</script>

var playlistId, nextPageToken, prevPageToken;

function onJSClientLoad() {
  gapi.client.setApiKey('INSERT-YOUR-API-KEY'); // Insert your API key
  gapi.client.load('youtube', 'v3', function(){
    //Add function here if some action required immediately after the API loads
  });
}


function requestUserUploadsPlaylistId(pageToken) {
  // https://developers.google.com/youtube/v3/docs/channels/list
  var selchan = $("#SELECTmenu option:selected").val();
  var request = gapi.client.youtube.channels.list({
    id: selchan,
    part: 'snippet,contentDetails',
    filter: 'uploads'
  });
  request.execute(function(response) {
    playlistId = response.result.items[0].contentDetails.relatedPlaylists.uploads;
    channelId = response.result.items[0].id;
    requestVideoPlaylist(playlistId, pageToken);
  });
}

function requestVideoPlaylist(playlistId, pageToken) {
  $('#CONTAINER').empty();
  var requestOptions = {
    playlistId: playlistId,
    part: 'snippet,id',
    maxResults: 5 // can be changed
  };
  if (pageToken) {
    requestOptions.pageToken = pageToken;
  }
  var request = gapi.client.youtube.playlistItems.list(requestOptions);
  request.execute(function(response) {

    // Only show the page buttons if there's a next or previous page.
    nextPageToken = response.result.nextPageToken;
    var nextVis = nextPageToken ? 'visible' : 'hidden';
    $('#NEXTbutton').css('visibility', nextVis);
    prevPageToken = response.result.prevPageToken
    var prevVis = prevPageToken ? 'visible' : 'hidden';
    $('#PREVIOUSbutton').css('visibility', prevVis);

    var playlistItems = response.result.items;
    if (playlistItems) {
      displayResult(playlistItems);
    } else {
      $('#CONTAINER').html('Sorry, no uploaded videos.');
    }
  });
}

function displayResult(playlistItems) {
  for(var i=0;i<playlistItems.length;i++) {
    var channelTitle = playlistItems[i].snippet.channelTitle
    var videoTitle = playlistItems[i].snippet.title;
    var videoThumbnail = playlistItems[i].snippet.thumbnails.medium.url;

    var results = '<li>
    <div>'+channelTitle+'</div>
    <div><img src="'+videoThumbnail+'" /></div>
    <div>'+videoTitle+'</div>
    </li>'; 

    $('#CONTAINER').append(results);
  }
}

function nextPage() {
  $('#CONTAINER').empty(); // This needed here
  requestVideoPlaylist(playlistId, nextPageToken);
}

function previousPage() {
  $('#CONTAINER').empty(); // This needed here
  requestVideoPlaylist(playlistId, prevPageToken);
}

$('#NEXTbutton').on('click', function() { // Display next maxResults
  nextPage();
});

$('#PREVIOUSbutton').on('click', function() { // Display previous maxResults
  previousPage();
});

// Using as filtering example Select option values which contain channel
// ID length of 24 alphanumerics/symbols to trigger functions just in case
// there are other option values in the menu that do not refer to channel IDs.

$("#SELECTmenu").on("change", function() {
  $('#CONTAINER').empty();
  if ($("#SELECTmenu option:selected").val().length === 24) {
    requestUserUploadsPlaylistId();
    return false;
  } else {
    return false;
  }
});

NOTE:

Remember, code sample above is built based on what API v3 provided at the time of this posting.

TIP: It's better to make sure that the buttons be disabled during API call and re-enabled after API has posted the expected results. If you press those buttons while processing, you may get compounded and/or unexpected results. ~ Koolness

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top