Jump to content

(Javascript) sending in videoID whenever user click on the corresponding video. (youtube API)

mrchow19910319
Spoiler

123.thumb.jpeg.b15d0cd2403c8c4e9ab52b6bd0e94149.jpeg

My goal is really easy, in the UI below, whenever a user click on the thumbnail of one video, its videoID will be submitted into the main video's videoID. 

So that user can watch the video in the bigger player above it.

 

Here is my code, I am stuck at the last step, I dont know how to get the videoID of the clicked event.

I know that I need to use addEventListener then use click, but I dont know how to write the callback function.

 

/* 
TODO list

1. need a fetch function to handle HTTP request
2. renderMainVideo() 
3. renderPlaylist()
4. call back function for the click event
*/


/*
Global variables and constants
*/


const key = 'myapikey';
const playlistId = 'UUuSrv3qgQA7SSi6R9bWag5A';
var URL = 'https://www.googleapis.com/youtube/v3/playlistItems';

const options = {
  playlistId: playlistId,
  maxResults: 20,
  key: key,
  part: 'snippet'
};

var mainVideoID;
var new_data;

/* 
HTTP request
*/
URL += '?' + Object.keys(options).map((k) => k + '=' + encodeURIComponent(options[k])).join('&');

fetch(URL)
  .then(res => res.json())
  .then(function (data) {
    new_data = data;
    mainVideoID = data.items[0].snippet.resourceId.videoId;
    console.log(data);
    renderPlaylist(data);
  })


/*
Render main video
 */
setTimeout(function renderMainVideo() {
  document.getElementById('youtube_feed').innerHTML = `
      <iframe width="1280" height="720" src="https://www.youtube.com/embed/${mainVideoID}" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`
}, 1000)

/*
Render Playlist
*/
function renderPlaylist(data) {
  console.log(data.items.length); //this gives you 20 which is correct

  //let's try loop through the array using for loop
  for (let i = 1; i < data.items.length; i++) {
    var thumbnail = data.items[i].snippet.thumbnails.medium.url;
    var title = data.items[i].snippet.title.substring(0, 50);
    var videoID = data.items[i].snippet.resourceId.videoId;


    document.getElementById('youtube_playlist').innerHTML += `
      <div class="individual_list_item" data-key = "${videoID}">
      <img src="${thumbnail}" alt="video_thumbnail_placeholder" class="thumbnails">
        <p class="playlist_titles">${title}</p>
    </div>
      `;
  }
}

/*
Call back function for the click event
*/

/* every time you click the video, you want to get the videoID of that specific video */

// setTimeout(function () {
//   console.log("main video ID is:" + mainVideoID);
// }, 1000);

// function setID() {
//   mainVideoID =
// }

 

If it is not broken, let's fix till it is. 

Link to comment
Share on other sites

Link to post
Share on other sites

i can't help you but let me know when you are finished. I would like to check out the website you made. It looks pretty cool. 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

3 minutes ago, wasab said:

i can't help you but let me know when you are finished. I would like to check out the website you made. It looks pretty cool. 

thanks for the support, already bought a domain for it. this is the last step I need to finish. 

If it is not broken, let's fix till it is. 

Link to comment
Share on other sites

Link to post
Share on other sites

$('#youtube_playlist').on('click','.individual_list_item',function(e){
    e.preventDefault();
    $element = $(e.currentTarget);
    console.log($element.data('key'));
});

Should do it ;) 

Edited by leodaniel
changed id name

Business Management Student @ University St. Gallen (Switzerland)

HomeServer: i7 4930k - GTX 1070ti - ASUS Rampage IV Gene - 32Gb Ram

Laptop: MacBook Pro Retina 15" 2018

Operating Systems (Virtualised using VMware): Windows Pro 10, Cent OS 7

Occupation: Software Engineer

Link to comment
Share on other sites

Link to post
Share on other sites

7 hours ago, mrchow19910319 said:

setTimeout(function renderMainVideo() { document.getElementById('youtube_feed').innerHTML = ` <iframe width="1280" height="720" src="https://www.youtube.com/embed/${mainVideoID}" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>` }, 1000)

And by the way, the mainVideoID could be undefined if the request takes more than 1s... why don't you just call that function in the promise?
 

Business Management Student @ University St. Gallen (Switzerland)

HomeServer: i7 4930k - GTX 1070ti - ASUS Rampage IV Gene - 32Gb Ram

Laptop: MacBook Pro Retina 15" 2018

Operating Systems (Virtualised using VMware): Windows Pro 10, Cent OS 7

Occupation: Software Engineer

Link to comment
Share on other sites

Link to post
Share on other sites

3 hours ago, leodaniel said:

And by the way, the mainVideoID could be undefined if the request takes more than 1s... why don't you just call that function in the promise?
 

I am fairly new to javascript. Is there any way that I can avoid dealing with promises?

Like I just want to GET the data from the API, store it into an object, then later iterate through that object and do things to it.

If I go that route and completely avoid using fetch, which method should I use when it comes to making a HTTP request?

 

https://medium.freecodecamp.org/here-is-the-most-popular-ways-to-make-an-http-request-in-javascript-954ce8c95aaa

 

 

@duncannah 

If it is not broken, let's fix till it is. 

Link to comment
Share on other sites

Link to post
Share on other sites

23 minutes ago, mrchow19910319 said:

I am fairly new to javascript. Is there any way that I can avoid dealing with promises?

Like I just want to GET the data from the API, store it into an object, then later iterate through that object and do things to it.

HTTP requests have to be asynchronous. What you could do is to create an empty variable outside of the fetch function, and change it when the fetch succeeds. When you want to go through it, you could check if the variable is an object (typeof variable === "object"), then only interact with it if so

 

Here's code that adds an click handler to each video div and gets the key:

document.querySelectorAll(".individual_list_item").each((el) => {
    el.addEventListener("click", (e) => {
        let id = e.originalTarget.dataset.key;
        
        // do whatever with id
    });
});

Run it after you insert the divs.

🙂

Link to comment
Share on other sites

Link to post
Share on other sites

26 minutes ago, duncannah said:

HTTP requests have to be asynchronous

Completely agree with that. 

 

Just pass the data in the promise to the function. So you don't even need global variables

fetch(url).then( response => {
	renderVideos(response.data)
})

function renderVideos(data){
	...
    // Register Click handler after insertion here
    // My example used jquery as i thought you used it before
}

 

Business Management Student @ University St. Gallen (Switzerland)

HomeServer: i7 4930k - GTX 1070ti - ASUS Rampage IV Gene - 32Gb Ram

Laptop: MacBook Pro Retina 15" 2018

Operating Systems (Virtualised using VMware): Windows Pro 10, Cent OS 7

Occupation: Software Engineer

Link to comment
Share on other sites

Link to post
Share on other sites

I created two local variables for sending videoID into the DOM, one for the playlist, one for the main video.

/* 
TODO list

1. need a fetch function to handle HTTP request
2. renderMainVideo() 
3. renderPlaylist()
4. call back function for the click event
*/


/*
Global variables and constants
*/


const key = 'AIzaAWvl6IdE';
const playlistId = 'UUuSrv3qgQA7SSi6R9bWag5A';
var URL = 'https://www.googleapis.com/youtube/v3/playlistItems';

const options = {
  playlistId: playlistId,
  maxResults: 20,
  key: key,
  part: 'snippet'
};


/* 
HTTP request
*/
URL += '?' + Object.keys(options).map((k) => k + '=' + encodeURIComponent(options[k])).join('&');

fetch(URL)
  .then(res => res.json())
  .then(function (data) {
    let mainVideoID;
    mainVideoID = data.items[0].snippet.resourceId.videoId;
    renderPlaylist(data);
    renderMainVideo(mainVideoID);
  });

/*
Render main video
 */
function renderMainVideo(mainVideoID) {
  document.getElementById('youtube_feed').innerHTML = `
        <iframe width="1280" height="720" src="https://www.youtube.com/embed/${mainVideoID}" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`
}




/*
Render Playlist
*/
function renderPlaylist(data) {
  console.log(data.items.length); //this gives you 20 which is correct

  //let's try loop through the array using for loop
  for (let i = 1; i < data.items.length; i++) {
    var thumbnail = data.items[i].snippet.thumbnails.medium.url;
    var title = data.items[i].snippet.title.substring(0, 50);
    var videoID = data.items[i].snippet.resourceId.videoId;


    document.getElementById('youtube_playlist').innerHTML += `
      <div class="individual_list_item" data-key = "${videoID}">
      <img src="${thumbnail}" alt="video_thumbnail_placeholder" class="thumbnails">
        <p class="playlist_titles">${title}</p>
    </div>
      `;
  }
}

/*
Call back function for the click event
*/

/* every time you click the video, you want to get the videoID of that specific video */

document.getElementById('youtube_playlist')
  .addEventListener('click', function (event) {
    const target = event.target;

    let mainVideoID_forclick;
    if (event.target.dataset.key) {
      mainVideoID_forclick = event.target.dataset.key;
      renderMainVideo(mainVideoID_forclick);
    } else {
      mainVideoID_forclick = event.target.parentElement.dataset.key;
      renderMainVideo(mainVideoID_forclick);
    }
  })

 

If it is not broken, let's fix till it is. 

Link to comment
Share on other sites

Link to post
Share on other sites

@leodaniel @duncannah 

 

I have another question for you guys. I have read some of the twitch.tv API documents as well as youtube API documents.

BOTH of those code bases, use: 

var options = {
 //something either ralated to twitch VOD/stream OR youtube playlist/video
}

for example, in twitch we have:

  var options = {
    width: <width>,
    height: <height>,
    channel: "<channel ID>",
    video: "<video ID>",
    collection: "<collection ID>",
  };

and in youtube we have:

const options = {
  playlistId: playlistId,
  maxResults: 50,
  key: key,
  part: 'snippet'
};

If I want to use these 2 APIs in one site, how am I gonna do it? In JS file I can only set one options right? Or I need to set one as a local variable, set another one as another local variable?

If it is not broken, let's fix till it is. 

Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, mrchow19910319 said:

If I want to use these 2 APIs in one site, how am I gonna do it? In JS file I can only set one options right? Or I need to set one as a local variable, set another one as another local variable?

Just use a different name, they don't have to be called options

🙂

Link to comment
Share on other sites

Link to post
Share on other sites

On 1/2/2019 at 12:08 PM, wasab said:

i can't help you but let me know when you are finished. I would like to check out the website you made. It looks pretty cool. 

https://trick2gsite.netlify.com/ 

 

version 1 is online.

If it is not broken, let's fix till it is. 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×