Categories:

Creating a simple Youtube Lightbox

By combining everything we've learned in the last 2 sections- making our Youtube iframe responsive and centered, plus loading and manipulating it through the Youtube Player API- we're ready to create a simple lightbox that pops up to show our desired Youtube video when launched.

Demo: Click on one of the sample links below to launch a Youtube video inside lightbox: Video 1 | Video 2 | Video 3

You can also view the demo on a separate page.

Lets go through how the script is created now, step by step.

The lightbox Interface

To create the lightbox interface, we'll use the same technique and setup discussed in the first section to display an iframe that's both responsive and centered in the middle of the page:

<head>
<link rel="stylesheet" href="youtubelightbox.css" />
</head>

<body>
<!-- Add this to bottom of page -->
<div id="youtubelightbox" class="parent">
	<div class="centeredchild">
		<div class="videowrapper">
			<div id="playerdiv"></div>
		</div>
	</div>
</div>
</body>

If you look inside youtubelightbox.css, everything should look familiar to you based on what you've read in the previous section. We hide the interface initially by setting the top level container to "display: none". Also, notice that instead of actually embedding a youtube iframe in the heart of the lightbox, we insert a temporary DIV '<div id="player"></div>'. This DIV will be dynamically replaced with a Youtube iframe using the Youtube Player API later.

Defining the links that will trigger the lightbox

Before getting to our actual lightbox script, we also need to decide how it should be triggered. A simple yet versatile set up is to attach the lightbox to any link on the page that points to a Youtube video and carries a CSS class of "lightbox"- whenever the user clicks on one of those links, we want the lightbox to be shown and the Youtube video played. Here are some example links that we want the lightbox to be triggered for when clicked on:

<p>
Click on one of the sample links below to launch a Youtube video inside lightbox: 
<a href="https://www.youtube.com/watch?v=Pe0jFDPHkzo" class="lightbox">Video 1</a> | <a href="https://youtu.be/oIlIVFBBbNw" class="lightbox">Video 2</a> | <a href="https://www.youtube.com/watch?v=fzrfrXhE-w4" class="lightbox">Video 3</a>
</p>

We'll design the script to recognize a Youtube link by way of its "lightbox" class name, and then to extract the Youtube video ID portion of the link to feed into Youtube Player API the video to play. Youtube links come in a variety of forms, and we'll use a robust regular expression to get to the video ID portion of the link regardless.

Creating the lightbox script

We've defined the interface for the lightbox and how it should be activated- only thing left to do is to create the script! We'll use plain JavaScript here (no jQuery). Here it is, followed by an explanation:

<!-- Add this to bottom of page after the lightbox markup-->
<script>

// load Youtube API code asynchronously
var tag = document.createElement('script')

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

var isiOS = navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)/i) != null //boolean check for iOS devices

var youtubelightbox = document.getElementById('youtubelightbox')
var player // variable to hold new YT.Player() instance

// Hide lightbox when clicked on
youtubelightbox.addEventListener('click', function(){
	this.style.display = 'none'
	player.stopVideo()
}, false)

// Exclude youtube iframe from above action
youtubelightbox.querySelector('.centeredchild').addEventListener('click', function(e){
	e.stopPropagation()
}, false)


// define onYouTubeIframeAPIReady() function and initialize lightbox when API is ready
function onYouTubeIframeAPIReady() {
	createlightbox()
}

// Extracts the Youtube video ID from a well formed Youtube URL
function getyoutubeid(link){
	// Assumed Youtube URL formats
	// https://www.youtube.com/watch?v=Pe0jFDPHkzo
	// https://youtu.be/Pe0jFDPHkzo
	// https://www.youtube.com/v/Pe0jFDPHkzo
	// and more
	
	//See http://stackoverflow.com/a/6904504/4360074
	var youtubeidreg = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i;
	return youtubeidreg.exec(link)[1] // return Youtube video ID portion of link
}

// Creates a new YT.Player() instance
function createyoutubeplayer(videourl){
	player = new YT.Player('playerdiv', {
		videoId: videourl,
		playerVars: {autoplay:1}
	})
}

// Main Youtube lightbox function
function createlightbox(){
	var targetlinks = document.querySelectorAll('.lightbox')
	for (var i=0; i<targetlinks.length; i++){
		var link = targetlinks[i]
		link._videoid = getyoutubeid(link) // store youtube video ID portion of link inside _videoid property
		targetlinks[i].addEventListener('click', function(e){
			youtubelightbox.style.display = 'block'
			if (typeof player == 'undefined'){ // if video player hasn't been created yet
				createyoutubeplayer(this._videoid)
			}
			else{
				if (isiOS){ // iOS devices can only use the "cue" related methods
					player.cueVideoById(this._videoid)
				}
				else{
					player.loadVideoById(this._videoid)
				}
			}
			e.preventDefault()
		}, false)
	}
}

</script>

After loading the Youtube Player API asynchronously, the first thing we do is assign "click" behaviour to the main "#youtubelightbox" container, so clicking on it dismisses the lightbox and stops playing the video. However, we want users to be able to interact with the Youtube iframe inside it without it disappearing, so we make an exception for clicks occurring inside the iframe container (".centeredchild").

Moving on, we define the onYouTubeIframeAPIReady() that Youtube API automatically calls when the API is loaded, and instead of initializing a Youtube player at this point, we simply initialize the Lightbox. We'll wait until the user actually clicks on a Youtube link before initializing the Youtube player:

function onYouTubeIframeAPIReady() {
	createlightbox()
}

Following the above, function getyoutubeid(link) gets the ID portion of a Youtube link to feed into Youtube API to play a specific video. The regular expressions used is discussed here. Function createyoutubeplayer(videourl) takes a Youtube video ID and creates a Youtube player using it, by creating an instance of new YT.Player(). We'll only be creating the Youtube player once, the first time the user clicks on a Youtube link. Subsequent clicks will simply cause the existing player to play the desired video.

Last but not least, we arrive at function createlightbox(), which ties everything together. Firstly, it gathers up all links on the page with class ".lightbox", then iterates through each of them to assign a "click" event handler to them. When the user clicks on these links, the script displays the lightbox interface while either creating a Youtube player or simply plays the target video depending on whether the player is already present.

As mentioned in the previous section on Mobile Devices Playback, in iOS devices such as iPhone and iPad, Youtube API's "play" related functions not only do not play the requested video, but puts the player in "perpetual" buffering mode, essentially disabling the player altogether. To overcome this nasty bug, inside our lightbox script, we detect iOS devices, and when a link is clicked on, simply "cue" the corresponding video instead of play it in those devices:

if (isiOS){ // iOS devices can only use the "cue" related methods
	player.cueVideoById(this._videoid)
}
else{
	player.loadVideoById(this._videoid)
}

This loads up the video in the lightbox for iOS users but doesn't attempt to play it (and triggering the bug), leaving it up to the user to click "play".

End of tutorial