Firefox, Vimeo and Froogaloop Have a Little Problem

On one of our latest projects we're integrating with Vimeo. They provide a great Video player API that makes it pretty simple to interact with videos. Vimeo even provides the Froogaloop library that wraps up all the communication between the iframe where the video lives and your page.

What We Need

The requirement was to show other content once the video finished playing. That seems easy enough and really it is:


var VimeoStuff = {

init: function(){ $.each($('iframe.vimeo'), function(i, iframe){ this.setupEvents(iframe) }.bind(this)); }

setupEvents: function(iframe){ var player = $f(iframe);

player.addEvent('ready', function(player_id){
  player.addEvent('finish', onFinish);
});

function onFinish(id){
  // Show other content
}

}

};

$(document).ready(function(){ VimeoStuff.init(); });

The Problem

We do most of our development using Chrome and so everything worked great until someone tried to use the application with Firefox. I know, most people will tell you that Internet Explorer is pure evil and a total piece of junk. I hate to say it but Firefox has its rough spots as well. For some reason in Firefox the events from the Vimeo player iframe never fired. After some digging we found this semi-related bug indicating if an iframe isn't visible then window.getComputedStyle() would return null. It turns out that if an iframe isn't visible when a page loads and you attempt to use the Froogaloop library to monitor events coming from that window you are out of luck - the 'ready' event will never fire and you won't be able to monitor any other events coming from the iframe.

The solution was something we needed anyway. Orginally, we were loading iframes for a bunch of videos on the page. That's a bad idea anyway since loading 20 or 30 hidden videos on a page isn't especially performant.

A Fix

The fix was pretty simple. Instead of setting the 'src' tag on every iframe and loading the video at startup we set a 'data-src' on every iframe and left the src tag empty. We have a helper that looks like this:


def video_embed(video)
  %Q{}
end

Then in our javascript we only set the iframe src when we display the modal. After that we watch for the 'ready' event from Froogaloop and everything works like magic again:


var VimeoStuff = {

init: function(){

$.each($('.modal'), function(i, modal){
  modal = $(modal);

  modal.on('show.bs.modal', function(){
    var iframe = $('iframe.vimeo', modal);
    iframe.attr('src', iframe.data('src'));
    this.setupEvents(iframe[0]);
  }.bind(this));

}.bind(this));

},

setupEvents: function(iframe){ var player = $f(iframe);

player.addEvent('ready', function(player_id){
  player.addEvent('finish', onFinish);
});

function onFinish(id){
  // Show other content
}

}

};

$(document).ready(function(){ PikkitUserAds.init(); });