Encapsulate the Youtube Iframe API with RequireJS

After not finding a nice encapsulated javascript module. My attemt to use the Youtube Iframe API inside a module definded with RequireJS.

The Basics

If you are using require.js as your AMD module loader. The youtubePlayer module will allow you to focus on functionality instead of forcing the YouTube JavaScript Player API into your infrastructure. Your favorite publish and Subscribe implementation can be used requiring only small change to the module. This pattern is used to expose player api functionality and events.

Source code of the module can be found in the broekema41 / youtubePlayer Gist.

Basic Implementation

<div id="playerExsample1">

</div>
<script>
    require(['myweb/youtubePlayer'], function (player) {
        player.init(document.getElementById('playerExsample1'),{
            videoId : 'M7lc1UVf-VE'
        });
    });
</script>

Eventing and Controls

I decided to use jQuery Custom Events as pubsub in this example because most developers are familiar with them. Inside the module there is a "_createPubsubFunctions" code block where custom events can be added to perform/send playerAPI changes.

Outside youtubePlayer module

$('#btn-play').on('click', function () {
    $(elm).trigger('play');
});

$('#btn-stop').on('click', function () {
    $(elm).trigger('stop');
});

Inside youtubePlayer module

var _createPubsubFunctions = function(id) {

    JElm = $('#'+id);

    JElm.on('play', function () {
        playerAPI.playVideo();
    });

    JElm.on('stop', function () {
        playerAPI.stopVideo();
    });

}

Add Responsive Characteristics

The current web is full of responsive and fluid layouts. Fortunately there are several techniques to make video elements responsive. The technique shown below wraps the video in another element. The padding bottom on this element ensures a fixed aspect ratio. If your video has a different aspect ratio play around with the padding-bottom until the black bars are no longer there.

<div class="video-wrapper">
   <div id="playerExsample">
   </div>
</div>
<style>
    /**
     * youtube player styles
     */
     .video-wrapper {
        position: relative;
        max-width: 640px;
        padding-bottom:  56.25%;
        padding-top: 0;
        height: 0;
        overflow: hidden;
    }

    .video-wrapper iframe,
    .video-wrapper object,
    .video-wrapper embed {
        position: absolute;
        max-width: 640px;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
    }

    @media screen and (min-width: 705px) {
        .video-wrapper {
           padding-bottom:  360px;
        }
    }

</style>

Example

Event log and Controls

Example code

<div class="video-wrapper">
    <div id="playerExsample2">
    </div>
</div>

<pre><code class="player-log"></code></pre>

<div>
    <button id="btn-play" class="btn btn-large btn-primary"><span>Play</span></button>
    <button id="btn-stop" class="btn btn-large btn-primary"><span>Stop</span></button>
    <button id="btn-reset" class="btn btn-large btn-primary"><span>Reset</span></button>
</div>

<script>

    require(['myweb/youtubePlayer','myweb/jquery'], function (player, $) {

        var elm = document.getElementById('playerExsample2');

        player.init(elm,{
            videoId : 'M7lc1UVf-VE'
        });

        $('#btn-play').on('click', function () {
            $(elm).trigger('play');
        });

        $('#btn-stop').on('click', function () {
            $(elm).trigger('stop');
        });

        $('#btn-reset').on('click', function () {
            $(elm).trigger('reset');
        });

        $(elm).on('ready', function () {
            $('.player-log').append('<div>log: player ready event received.</div>')
        });

        $(elm).on('StateChange', function (event, obj) {
            $('.player-log').append('<div>log: player StateChange event '+obj.state+'</div>')
        });

    });

</script>