YouTube API: Authentication and search

  1. Authentication and initialization
  2. Search
  3. Playback
  4. The HTML

In part one, we'll access public content. We'll also set up user authentication for future use.

Authentication and initialization

/* To get your own keys, create a project at https://console.developers.google.com
and navigate to APIs & auth > Credentials */
var OAUTH2_CLIENT_ID = "_YOUR_CLIENT_ID_",
		OAUTH2_SCOPES = ["https://www.googleapis.com/auth/youtube"];

function googleApiClientReady() {
	"use strict";

	var el;

	// Your public API key
	gapi.client.setApiKey("_YOUR_API_KEY_");

	gapi.client.load("youtube", "v3", function() {
		el = document.getElementById("searchForm");
		el.querySelector("input[type=submit]").removeAttribute("disabled");
		el.addEventListener("submit", search, false);

		document.getElementById("results").addEventListener("click", resultControls, false);
	});

	gapi.auth.init(function() {
		window.setTimeout(checkAuth, 1);
	});
}

function checkAuth(immediate) {
	"use strict";

	gapi.auth.authorize({
		client_id: OAUTH2_CLIENT_ID,
		scope: OAUTH2_SCOPES,
		immediate: (immediate !== false ? true : false),
	}, handleAuthResult);
}

function handleAuthResult(authResult) {
	"use strict";

	if (authResult && !authResult.error) {
		document.getElementById("loginButton").setAttribute("disabled", "disabled");
		/*
		here you can set up things that require authorization, such as list your own videos
		*/
	}
	else {
		document.getElementById("loginButton").onclick = function() {
			checkAuth(false);
		};
	}
}

Search

function search(e, params) {
	"use strict";

	var container = document.getElementById("results"),
			items,
			item,
			i,
			obj;

	e.preventDefault();

	params = params || {
		part: "snippet",
		q: e.target.querySelector("input").value,
		type: e.target.querySelector("select").value
	};

	if (params.q === "") {
		return;
	}

	container.innerHTML = "";

	gapi.client.youtube.search.list(params).execute(function(response) {
		if (response.error) {
			alert("Error: " + response.error.message);
		}
		else if (response.pageInfo.totalResults === 0) {
			container.appendChild(document.createTextNode("No results."));
		}
		else if (response.items) {
			container.appendChild(document.importNode(document.getElementById("items").content, true));
			items = container.querySelector(".items");

			if (response.nextPageToken) {
				params.pageToken = response.nextPageToken;
				container.querySelector(".more").removeAttribute("disabled");
				container.querySelector(".more").addEventListener("click", function click(e) {
					e.target.removeEventListener("click", click, false);
					search(e, params);
				}, false);
			}

			for (i = 0; i < response.items.length; i += 1) {
				obj = response.items[i];
				item = document.importNode(document.getElementById(obj.id.kind.replace("youtube#", "")).content, true);
				item.querySelector(".item").setAttribute("data-id", (obj.id.videoId || obj.id.playlistId || obj.id.channelId));
				item.querySelector("img").setAttribute("src", obj.snippet.thumbnails["default"].url);
				item.querySelector(".title").appendChild(document.createTextNode(obj.snippet.title));
				items.appendChild(item);
			}
		}
	});
}

Playback

This function was bound to the search result list after the client library had initialized.

function resultControls(e) {
	"use strict";

	var el;

	// unnecessary at this point, but because we have fake buttons, we'll restrict the action to them
	if (e.target.nodeName !== "BUTTON") {
		return;
	}

	el = e.target;

	while (el && el.id !== "results" && !el.getAttribute("data-id")) {
		el = el.parentNode;
	}

	switch (el.getAttribute("data-kind")) {
		case "video":
			document.getElementById("videoPlayer").setAttribute("src", "http://www.youtube.com/embed/" + el.getAttribute("data-id") + "?autoplay=1&html5=1");
			break;

		case "playlist":
			document.getElementById("videoPlayer").setAttribute("src", "http://www.youtube.com/embed/?autoplay=1&html5=1&listType=playlist&list=" + el.getAttribute("data-id"));
			break;

		case "channel":
			alert("For now, let's pretend you subscribed.");
			break;
	}
}

The HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>YouTube API Demo</title>
<style>
	hidden {display:none}
	hr {margin:1em 0; border-width:1px 0px 0px 0px; border-style:dashed; border-color:black}
	iframe {display:block; background-color:#ddd; border:none}
	img {max-width:150px}
</style>
<script src="youtube-search.js"></script>
<script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
</head>
<body>

<button id="loginButton" type="button">Sign in</button>

<hr>

<form id="searchForm" action="" method="post" accept-charset="utf-8">
	<input type="search" placeholder="Search terms" aria-label="Search terms">
	<select name="type" aria-label="Type">
		<option value="">All</option>
		<option value="video">Videos</option>
		<option value="playlist">Playlists</option>
		<option value="channel">Channels</option>
	</select>
	<input type="submit" value="Search" disabled>
</form>

<hr>

<div id="results"></div>

<hr>

<iframe id="videoPlayer" width="640" height="390"></iframe>

<template id="items" hidden>
	<ul class="items"></ul>
	<button class="more" type="button" disabled>More results</button>
</template>

<template id="video" hidden>
	<li class="item" data-kind="video">
		<img>
		<span class="title"></span>
		<button type="button">Play</button>
	</li>
</template>

<template id="playlist" hidden>
	<li data-kind="playlist">
		<img>
		<span class="title"></span>
		<button type="button">Play</button>
	</li>
</template>

<template id="channel" hidden>
	<li data-kind="channel">
		<img>
		<span class="title"></span>
		<button type="button">Subscribe</button>
	</li>
</template>

</body>
</html>
Using
  • YouTube Data API v3
  • Javascript client library

Comments