Propeople Blog

A regular dose of fresh news, events, products, Drupal development resources and more.

June 12, 2013

How to create slideshows with embedded YouTube videos in Drupal 7

One of the popular functionalities we build at Propeople Drupal Agency are slideshows. Thanks to views_slideshow module it’s a very easy task to implement. Sometimes slideshows contain embedded YouTube videos. And thanks to the great Media module, it is not a very hard task to do either.

The only problem we face is when the user clicks play – the slideshow still switches to the next slide. This article addresses this problem.

We have found a nice example of reacting on YouTube player play / pause.

In order to use this example we will need to override media-youtube-video template as we will need to change the output.

In order to accomplish this we can create our own template and add it to suggestions in case this field is displayed in a view with slideshow.

<?php
/**
* Implements hook_theme().
*/
function mymodule_theme() {
return array(
'mymodule_media_youtube_video' => array(
'variables' => array('uri' => NULL, 'options' => array()),
'template' => 'mymodule-media-youtube-video',
),
);
}

/**
* Preprocess function for template media-youtube-video.tpl.php
*/
function mymodule_preprocess_media_youtube_video(&$variables) {
if (!_mymodule_search_backtrace('template_preprocess_views_view_field')) {
return;
}

$views_id = drupal_static('mymodule_preprocess_views_view_field');
if (empty($views_id)) {
return;
}

drupal_add_js('http://www.youtube.com/player_api');
drupal_add_js(drupal_get_path('module', 'mymodule') . '/mymodule.js');

$variables['theme_hook_suggestions'] = array('mymodule_media_youtube_video');

$variables['iframe_id'] = 'media-youtube-' . $variables['id'];
$variables['views_id'] = $views_id;
}
?>

The mymodule_preprocess_media_youtube_video() function does some tricks:

1. It checks whether rendering of media file is done inside the view. For this we check the backtrace for template_preprocess_views_view_field function. This is pretty hacky but I haven't found a nicer way to check. It is needed so we do not modify output if for example media file displayed in the node.

2. It loads $views_id from static variable. This is another pretty ugly hack, but it is needed for passing a variable to javascript (so we know what slideshow to pause / start). Also when we prepare that variable we check if a view actually uses slideshow style.

I would love to hear if you know a better workaround for these two hacks. Write in the comment form below or on our social profiles: Twitter, Facebook.

The function where we prepare the view id:

<?php
/**
* Preprocess function for views-view-field.tpl.php.
*
* Statically cache view information to pass to mymodule.js so we know what slideshow to pause.
*/
function mymodule_preprocess_views_view_field(&$variables) {
$views_slideshow_id = &drupal_static(__FUNCTION__);
$views_slideshow_id = '';

$view = $variables['view'];
if ($view->style_plugin->plugin_name == 'slideshow') {
$views_slideshow_id = $view->name . '-' . $view->current_display;
}
}
?>

Now the template file:

<div class="<?php print $classes; ?> media-youtube-<?php print $id; ?>">
<iframe id="<?php print $iframe_id; ?>"
class="media-youtube-player media-youtube-mymodule" <?php print $api_id_attribute; ?>
width="<?php print $width; ?>"
height="<?php print $height; ?>"
title="<?php print $title; ?>"
src="<?php print $url; ?>"
frameborder="0"
allowfullscreen
data-iframe_id='<?php print $iframe_id; ?>'
data-video_id='<?php print $video_id; ?>'
data-views_id='<?php print $views_id; ?>'
>
<?php print $alternative_content; ?></iframe>
</div>

As you can see, we are passing iframe_id, video_id and views_id as attributes of the iframe so javascript can use them.

And the last piece is the javascript itself:

<javascript>
(function ($) {
Drupal.behaviors.mymodule = {
attach: function (context) {
$('.media-youtube-mymodule').once('mymodule').load(function() {
iframe_id = $(this).data('iframe_id');
video_id = $(this).data('video_id');
views_id = $(this).data('views_id');

// Example of interacting with YouTube API's
//@link http://jsfiddle.net/masiha/4mEDR/
var mymodule_player = new YT.Player(iframe_id, {
videoId: video_id,
events: {
'onStateChange': function (event) {
if (event.data == YT.PlayerState.PLAYING) {
Drupal.viewsSlideshow.action({
"action": 'pause',
"slideshowID": views_id,
"force": true
});
}
else if (event.data == YT.PlayerState.PAUSED) {
Drupal.viewsSlideshow.action({
"action": 'play',
"slideshowID": views_id,
"force": true
});
}
}
}
});
});
}
};
})(jQuery);
</javascript>

The full code of this drupal module can be downloaded here.

Now, after enabling this module, if you build a slideshow with media youtube files it should apply this functionality automatically.

Enjoy.

1 Response to this post

This is definitely the right way to do it. The pause on click option is the quick hack of a way that will also work.

Communicate!