Aug 21, 2013

Triggering a Youtube Video from Clicking a Button Image and Replacing when Ended

This post will discuss how to solve the problem of playing a Youtube video from a press from an initial starting image, and then replacing the image when the video has ended playing.

Over the last two years on a few different web projects, I have had occasion to need to trigger a Youtube video to play from a Jquery click event on a PNG image button or HTML5 element. When implementing frontend development For example, a JPG rollover has CSS3 styles simulating button presses, which loads the Youtube Player Javascript API and fires the OnPlayerReady callback.

Recently, it was needed to replace the Jpeg clicked button or Div element when the video finished playing. In this case, it is necessary to detect the Youtube player state and call the player.destroy() method, along with reseting any other DOM elements that may have been effected during the instantiation of the player object. This all needs to be reliable for browser versions at least as old as IE8, as well as, mobile devices, iPhones, iPads, and Android tablets and phones.

Skip to full code
Working JSfiddle

How it works

Basically, this works by downloading the Youtube player API asynchronously, then instantiating a new player object and assigning the appropriate event listeners

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

In this example, I have added a few other pieces that were useful in my particular case, namely a rollover image for a button which is attached as the background-image of a div that holds the player div.

    $("#container").mouseenter(function(){
$(this).addClass('hover-state');
}).mouseleave(function(){
$(this).removeClass('hover-state');
});

For the purposes of simplicity I am simply using some image urls that have been converted to data uris

    .inactive-state {
background-repeat: no-repeat;
background-size: 100%;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFUAAAAwCAIAAADvrqHkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAVxJREFUeNpivD5DnmEEAyaGkQ1G/T/q/1H/j/p/1P+j/h/1/6j/RxpgoZ3RGmn3qWXUjVmKo/E/1OKfKlFHxUQ0iOKfU8xgRJd/0m4zOUR0R67/WbjEZDxmD4YgGLDyj4VLHBQEonojt/4HBYE7MAh0R6j/oRnBbRaHiM7Ibf+xcEuAUsEAlQWDov0DDIKBqhEGS/uPlUdSxn0W/YNgELV/QRnBYzafSsDI7f8BawReJc9h1f4nCXy4vvzt+Skj1P8fb615ebTu/78/IzH9f7y56sWhCjp7frDE/4drS16eaP3/7+9IrP+Aef7Vifb/f34MTIk7wMn+9nr65/nB4n9ggff8YDnD/38DWeMOYJ5/daJtYD0/YPkflOdPdf37833AS5+B8f+bsxP//fo8KFqctLaA1gO4w6r9T3/AOLr+iWHU/6P+H/X/qP9H/T/q/1H/j/p/1P8jBwAEGAAZsV2KaXSD7AAAAABJRU5ErkJggg==');
}
.hover-state {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFUAAAAwCAIAAADvrqHkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAU1JREFUeNrsmV1qwkAUhVOJ9b8PUZ+UFp+MW+iLuo8uzAW4FhFEBREsWsVSQZO2oM/WGYdB360k3jH33AVM8p0758yd5GHSerEYV8ziXeAHP/jBD37wgx/83MoOb2n39S2opd47bfT/3vofSOsC3EQG9T+VK7DOv1K1nsw6fPntx1TZbZogAVn+nSXI8z3/tQQNWgmIzz8tQT2ZcZjyawnS5VqDKguMmH+UBKUqjQSmzH/xRFpngcOU/2QEt/lUrPC9/6k4zOWfIzX//6u23ux3NWbKv/Pn3qInpeDIr+A3866UMmr334u2/WbqLfu3hzci/5Tn/c+BFAeaxCXe9t+L23veFH7l+fVH17Ik4TvYhJ73lwNaeDL/a88PhfgjTx8a/p+vkTjsjZg4w35A2B9wIzX/R6r/4f20Qf/BD37wgx/84Ac/+MF/ZR0FGAAHJFtR2l1ELgAAAABJRU5ErkJggg==');
}

I have also added an example of some additional embellishment that can be added to the event handler functions, clicking the element and then the onStateChange.

  $("#container.click-to-play-video").click(function(){
$('#head').css({"background-color":"black"});

and

$("#container.click-to-play-video").click(function(){
$('#head').css({"background-color":"black"});function onPlayerStateChange(event) {
if(event.data == YT.PlayerState.ENDED) {
player.destroy();
$('#head').css({"background-color":"#aaa"});
}
}

I found that this code will work in a wide range of browsers, tested backward to IE8, as well as mobile devices and phones. As always, testing the code in every platform that your project supports is paramount to success.

The Full Code

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Triggering a Youtube Video from Clicking a Button Image and Replacing when Ended</title>
</head>
<body>
<style type="text/css">
#head {
background-color: #aaa;
width:100%;
}
#container {
cursor:pointer;
width:320px;
height:180px;

margin:auto;
position:relative;
}

.inactive-state {
background-repeat: no-repeat;
background-size: 100%;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFUAAAAwCAIAAADvrqHkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAVxJREFUeNpivD5DnmEEAyaGkQ1G/T/q/1H/j/p/1P+j/h/1/6j/RxpgoZ3RGmn3qWXUjVmKo/E/1OKfKlFHxUQ0iOKfU8xgRJd/0m4zOUR0R67/WbjEZDxmD4YgGLDyj4VLHBQEonojt/4HBYE7MAh0R6j/oRnBbRaHiM7Ibf+xcEuAUsEAlQWDov0DDIKBqhEGS/uPlUdSxn0W/YNgELV/QRnBYzafSsDI7f8BawReJc9h1f4nCXy4vvzt+Skj1P8fb615ebTu/78/IzH9f7y56sWhCjp7frDE/4drS16eaP3/7+9IrP+Aef7Vifb/f34MTIk7wMn+9nr65/nB4n9ggff8YDnD/38DWeMOYJ5/daJtYD0/YPkflOdPdf37833AS5+B8f+bsxP//fo8KFqctLaA1gO4w6r9T3/AOLr+iWHU/6P+H/X/qP9H/T/q/1H/j/p/1P8jBwAEGAAZsV2KaXSD7AAAAABJRU5ErkJggg==');
}
.hover-state {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFUAAAAwCAIAAADvrqHkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAU1JREFUeNrsmV1qwkAUhVOJ9b8PUZ+UFp+MW+iLuo8uzAW4FhFEBREsWsVSQZO2oM/WGYdB360k3jH33AVM8p0758yd5GHSerEYV8ziXeAHP/jBD37wgx/83MoOb2n39S2opd47bfT/3vofSOsC3EQG9T+VK7DOv1K1nsw6fPntx1TZbZogAVn+nSXI8z3/tQQNWgmIzz8tQT2ZcZjyawnS5VqDKguMmH+UBKUqjQSmzH/xRFpngcOU/2QEt/lUrPC9/6k4zOWfIzX//6u23ux3NWbKv/Pn3qInpeDIr+A3866UMmr334u2/WbqLfu3hzci/5Tn/c+BFAeaxCXe9t+L23veFH7l+fVH17Ik4TvYhJ73lwNaeDL/a88PhfgjTx8a/p+vkTjsjZg4w35A2B9wIzX/R6r/4f20Qf/BD37wgx/84Ac/+MF/ZR0FGAAHJFtR2l1ELgAAAABJRU5ErkJggg==');
}
</style>
<section id="head">
<div id="container" class="click-to-play-video inactive-state">
<div id="player" class="home-player"></div>
</div>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script type="text/javascript">
$("#container").mouseenter(function(){
$(this).addClass('hover-state');
}).mouseleave(function(){
$(this).removeClass('hover-state');
});

$("#container.click-to-play-video").click(function(){
$('#head').css({"background-color":"black"});

player = new YT.Player('player', {
width : '320',
height : '180',
videoId : 'qlEUrEVqDbo',
playerVars: { 'autoplay': 1 },
events : {
'onReady' : onPlayerReady,
'onStateChange' : onPlayerStateChange
}
});
});

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 player;
function onPlayerReady(event) {
//event.target.playVideo();
}
function onPlayerStateChange(event) {
if(event.data == YT.PlayerState.ENDED) {
player.destroy();
$('#head').css({"background-color":"#aaa"});
}
}
</script>
</body>
</html>

Was this content useful? Follow Nate Flink on Twitter!

About the Author

Object Partners profile.

One thought on “Triggering a Youtube Video from Clicking a Button Image and Replacing when Ended

  1. JP says:

    Have you had any luck getting this to work on the iphone?

  2. TW says:

    This was a great help to me.

  3. Silviu says:

    Good article, of course, but why didn’t you separate your jQuery in the fiddle example?

    That would make things so much easier to understand.

  4. zezen says:

    http://jsfiddle.net/eLt4aybd/1/

    🙂

    and in angularjs in a ng-repeat grid ?? how would you do ?

    so that the container clicked fills with a random video and empties the player that ended before …

  5. Larry says:

    How would you do this with 2 instances on the page?

  6. Sadik Sheikh says:

    Thank for this
    one issue in this code on click play video not working in the mobile
    pls check

Leave a Reply to Larry Cancel reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
An Exploration in Rust: Musings From a Java/C++ Developer
Why Rust? It’s fast (runtime performance) It’s small (binary size) It’s safe (no memory leaks) It’s modern (build system, language features, etc) When Is It Worth It? Embedded systems (where it is implied that interpreted […]
Getting Started with CSS Container Queries
For as long as I’ve been working full-time on the front-end, I’ve heard about the promise of container queries and their potential to solve the majority of our responsive web design needs. And, for as […]
Simple improvements to making decisions in teams
Software development teams need to make a lot of decisions. Functional requirements, non-functional requirements, user experience, API contracts, tech stack, architecture, database schemas, cloud providers, deployment strategy, test strategy, security, and the list goes on. […]
JavaScript Bundle Optimization – Polyfills
If you are lucky enough to only support a small subset of browsers (for example, you are targeting a controlled set of users), feel free to move along. However, if your website is open to […]