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
function add_video_wmode_transparent($html, $url, $attr) {
	$pattern = &#39;/(\/)(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=";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=";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:

  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;);

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.

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

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;