[API][YouTube][最終章]YouTubeAPIを使用したチャンネル情報検索機能

##完成品##
完成品が見えた方が創作意欲も上がると思うので先にネタバレします。見た目はほぼ整えていないのでご了承ください。

[![Image from Gyazo](https://i.gyazo.com/a3aedc6fd1600d0a5dcc3a6a658f2a47.gif)](https://gyazo.com/a3aedc6fd1600d0a5dcc3a6a658f2a47)
検索ボックスにチャンネル名を入力すると、[チャンネル名][チャンネルID][登録者数][視聴回数][動画本数][チャンネル概要]などが取得可能です。

##JavaScript##
APIからチャンネルを取得する関数を記述していきます。

```youtube.js
function getChannel(channel){
 console.log(channel);
}

var defaultChannel = 'techguyweb';
getChannel(defaultChannel);
```
第2章で変数を定義した際の'techguyweb'というチャンネル名がコンソール上で出力されると思います。
getChannel関数の中身を記述していきます。

```youtube.js
  function getChannel(channel){
    gapi.client.youtube.channels
      .list({
        part: 'snippet,contentDetails,statistics',
        forUsername: channel
      })
      .then(response => {
        var channel = response.result.items[0];

        var output = `
          <ul class='collection'>
            <li class='collection-item'><span class="dan">Title:</span><span class="dan2">${channel.snippet.title}</span></li>
            <li class='collection-item'><span class="dan">ID:</span><span class="dan2">${channel.id}</span></li>
            <li class='collection-item'><span class="dan">Subscribers:</span><span class="dan2, marg">${numberWithCommas(channel.statistics.subscriberCount)}</span></li>
            <li class='collection-item'><span class="dan">Views:</span><span class="dan2">${
              numberWithCommas(channel.statistics.viewCount)
            }</span></li>
            <li class='collection-item'><span class="dan">Videos:</span><span class="dan2">${
              numberWithCommas(channel.statistics.videoCount)
            }</span></li>
          </ul>
          <p class='channel-description'>${channel.snippet.description}</p>
          <hr>
          <a class='btn grey darken-2' target='_blank' href="https://youtube.com/${channel.snippet.customUrl}">Visit Channel</a>
        `;
        showChannelData(output);

        var playlistId = channel.contentDetails.relatedPlaylists.uploads;
        requestVideoPlaylist(playlistId);
      })
  }
```
partを'snippet,contentDetails,statistics'で指定することで、下記のようなAjax構造がコンソール上で出力されます。
この関数では、'snippet,contentDetails,statistics'しか使わないので省略している構造があります。
partパラメータには、API レスポンスに含める1つまたは複数の channelリソースプロパティをカンマ区切りリストの形式で指定します。
※詳しくは[こちら](https://developers.google.com/youtube/v3/docs/videos?hl=ja)

```js:ajax
{
  "kind": "youtube#video",
  "etag": etag,
  "id": string,
  "snippet": {
    "publishedAt": datetime,
    "channelId": string,
    "title": string,
    "description": string,
    "thumbnails": {
      (key): {
        "url": string,
        "width": unsigned integer,
        "height": unsigned integer
      }
    },
    "channelTitle": string,
    "tags": [
      string
    ],
    "categoryId": string
  },
  "contentDetails": {
    "duration": string,
    "dimension": string,
    "definition": string,
    "caption": string,
    "licensedContent": boolean,
    "regionRestriction": {
      "allowed": [
        string
      ],
      "blocked": [
        string
      ]
    },
  },
  "statistics": {
    "viewCount": unsigned long,
    "likeCount": unsigned long,
    "dislikeCount": unsigned long,
    "favoriteCount": unsigned long,
    "commentCount": unsigned long
  }
}
```
例えばchannelの視聴回数を取得したいのなら、
**channel.statistics.viewCount**のように記述します。
是非色々試してみて確認してください。

先ほどのgetChannel関数内の関数達を解説していきます。
numberWithCommas(); showChannelData();がどこにあるのか確認して下さい。
numberWithCommas();はhtml内に記載してあります。

```youtube.js
function showChannelData(data){
   var channelData = document.getElementById('channel-data');
   channelData.innerHTML = data;
 }
```
channel-dataのidをもつDOMを取得して
getChannel関数で記述したチャンネルIDなどの情報を元にinnerHTML関数でhtml要素の中身を変更しています。

次にnumberWithCommas();関数を記述していきます。

```youtube.js
function numberWithCommas(x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
```

[javascript numbers with commas]と検索するとstackoverflowの記事が出てくるので、
そこから拝借しています...
この関数の引数のなか要素を入れると千の桁にコンマを打ってくれます。
それではFormの内容がSubmitされた際の動きを記述していきます。

getChannel関数内の以下の記述を確認してください。
requestVideoPlaylist関数は動画を表示する為の重要な関数です。
そして先ほどとAjaxの構造が変化しますので注意して下さい。

```youtube.js
var playlistId = channel.contentDetails.relatedPlaylists.uploads;
requestVideoPlaylist(playlistId);
```

```youtube.js
function requestVideoPlaylist(playlistId) {
    var requestOptions = {
      playlistId: playlistId,
      part: 'snippet',
      maxResults: 8
    };

    var request = gapi.client.youtube.playlistItems.list(requestOptions);

    request.execute(function(response){
      
      var playListItems = response.result.items;
      if(playListItems){
      var output = '<h4 class="align-center">Latest Videos</h4>';

      
      playListItems.forEach(item => {
        var videoId = item.snippet.resourceId.videoId;

        output += `
          <div class="col s3">
          <iframe  height="auto" src="https://www.youtube.com/embed/${videoId}" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
          </div>
        `;
      });

      //動画一覧の出力
      videoContainer.innerHTML = output;

      } else {
        videoContainer.innerHTML = 'No Uploaded Videos';
      }
    });
  }
```

requestOptions変数に代入されているmaxResultsは表示する動画の最大件数です。

var request = gapi.client.youtube.playlistItems.list(requestOptions);
この行でplaylistItems.listメソッドをgapi.client.youtubeに対して呼び、IDを取得したrequestOptionsを引数に入れることでリスト内の動画を検索します。
※詳しくは[こちら](https://developers.google.com/youtube/v3/code_samples/javascript?hl=ja)

requestが実行された時このようなAjax構造がかえってきます。
配列のlengthがちゃんと8になっている事が確認出来ます。
このajax構造を元に
var videoId = item.snippet.resourceId.videoId;
この値を取得します。
取得の仕方は先ほどと同じなので確認してください。


そしてiframeタグ内のソースにvideoIdを組み込めば動画情報を取得できます。


<img width="1242" alt="スクリーンショット 2020-03-08 18.19.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565275/4dc7abb4-d440-ac05-b8f8-121b12a98206.png">



##後は一撃##

```youtube.js
document.addEventListener("DOMContentLoaded", function(){
  channelForm.addEventListener('submit', function(e){
    e.preventDefault();

    var channel = channelInput.value;

    getChannel(channel);
  });
}, false);
```
変数channelはchannelInputに入力された値が代入されています。
その値をもとにgetChannel関数が走ります。
私の場合'submit'イベントがエラーを起こしていたので、DOMContentLoadedイベントでDOMツリーの構築の読み込みをしています。

##総括##
いかがだったでしょうか。
大変長くなりましたが、お付き合い頂きありがとうございました。
良かったと思われた方は、是非LGTM宜しくお願い致します。