Getting control of YouTube via Javascript

Recently I was trying to write a WordPress slideshow plugin that would include YouTube videos. The challenge was that when I play the video I want to pause the slide. On regular picture slides I just needed to add a click() event listener to the slide object and attach a call to pause jQueryCycle. YouTube, though, refused to take the click() listener seriously. The solution came to me by reading up on the Youtube player api. I must say I'm a bit surprised that WordPress doesn't turn this on by default in its [embed] tag but here is my solution in the hopes that I can save someone else the trouble of finding this out again.

Step 1: Opt in to Use the API

Wordpress oembed doesn't turn add enablejsapi=1 to the embedded url when you use the embed shortcode

<code>//add ENABLEjsAPI to youtube videos
 
//With mad props to mehigh http://mehigh.biz/wordpress/adding-wmode-transparent-to-wordpress-3-media-embeds.html
 
function add_video_wmode_transparent($html, $url, $attr) {
 
 
 
	$pattern = &#39;/(youtube.com\/)(v\/\w+\?version=\d+)/i&#39;;
 
	$add = &#39;&amp;enablejsapi=1&#39;;
 
	$new_pattern = &quot;$1$2$add$3&quot;;
 
	$html = preg_replace($pattern, $new_pattern, $html);
 
 
 
   if (strpos($html, &quot;<embed src=" ) !== false) {     	$html = str_replace('&amp;lt;/param&amp;gt;&amp;lt;embed', '&amp;lt;/param&amp;gt;&amp;lt;param name=" value="1"></embed><param name="wmode" value="transparent" /><embed wmode="transparent"></embed></code>

What you end up with is the following:

 

<object height="330" width="440"><param name="movie" value="http://www.youtube.com/v/fxQWbMenYCc?version=3&amp;enablejsapi=1" /><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="enablejsapi" value="1" /><param name="wmode" value="transparent" /><embed allowfullscreen="true" allowscriptaccess="always" height="330" src="http://www.youtube.com/v/fxQWbMenYCc?version=3&amp;enablejsapi=1" type="application/x-shockwave-flash" width="440" wmode="transparent"></embed></object>

This code is doing a couple of things with a really basic hack that rewrites the oembed html as it's passing through to being printed.

  1. Tack on '&enablejsapi=1' to the embedded url
  2. add &lt;param&gt; tags to the &amp;lt;object&amp;gt; tag: We're adding enablejsapi=1 and wmode =transparent. wmode is a parameter that will allow Youtube videos to exist underneath our dropdown menus.

In the end these two steps were a little hack-y so if anyone knows a better way to override the [embed] shortcode functionality I'm all ears.

Step 2: Capture the youtube clicks

Now that we have access to the YouTube API we need to capture the clicks that come into it:

<code>
 
/*****************************************************
 
 
 
  Capture Youtube clicks so we can pause our slideshow
 
  when video plays.
 
 
 
*****************************************************/
 
 
 
function onYouTubePlayerReady(){
 
  var players = jQuery(&#39;#basic_slideshow embed&#39;).each(function(){
 
    if (this.addEventListener) {
 
      this.addEventListener(&#39;onStateChange&#39;, &#39;handlePlayerStateChange&#39;);
 
    }
 
    else {
 
      this.attachEvent(&#39;onStateChange&#39;, &#39;handlePlayerStateChange&#39;);
 
    }
 
  });
 
 
 
}
 
</code>

Ok. Now we've got the listeners in place to spy on YouTube for us. It's time to write one more little function to give instructions when things change.

<code>
 
function handlePlayerStateChange (state) {
 
  var slideshow = jQuery(&#39;#basic_slideshow div.list&#39;);
 
  switch (state) {
 
    case 1:
 
    case 3:
 
      // Video has begun playing/buffering
 
      slideshow.cycle(&#39;pause&#39;);
 
      break;
 
    case 2:
 
    case 0:
 
      // Video has been paused/ended
 
      slideshow.cycle(&#39;resume&#39;);
 
      break;
 
  }
 
}
 
</code>

I'll have to find some way to do it for Vimeo at some point but that uses iframes so it's a little different. Also, YouTube videos seem to be smart enough to pause themselves when jQueryCycle changes the slide and Vimeo videos just keep playing in the background. &nbsp;