Drupal Bootstrap: Video Gallery for YouTube and Vimeo using a Custom Field Formatter and Video Embed Field module

I'm using the Video Embed Field Module and would like display this field as a gallery using the Bootstrap gallery at https://github.com/blueimp/Gallery, a touch-enabled, responsive and customizable image and video gallery.

Note the code here is an extenstion to the custom image formatter I created previously, therefore it also includes the formatter for an image gallery to work with the image field, though this post focuses on image gallery display. I will comment out the image related code.

In a module we need to use hook_field_formatter_info() to create our video formatter:

<?php
/**
 * Implements hook_field_formatter_info();
 */
function MODULENAME_field_formatter_info() {
  return array(
//    'MODULENAME_bootstrap_image_gallery' => array(
//      'label' => t('Bootstrap Image Gallery'),
//      'field types' => array('image'),
//    ),
   
'MODULENAME_bootstrap_video_gallery' => array(
     
'label' => t('Bootstrap Video Gallery'),
     
'field types' => array('video_embed_field'),
    ),
  );
}
?>

We then use hook_field_formatter_view() to build the output as a render array. This includes everything we need to display the Bootstrap video gallery:

<?php
/**
 * Implements hook_field_formatter_view();
 */
function MODULENAME_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
 
$type = $field['field_name'] == 'field_gallery' ? 'image' : 'video';
 
$element = array(
   
'#prefix' => '
      <div id="blueimp-gallery-'
. $type . '" class="blueimp-gallery blueimp-gallery-controls">
        <div class="slides"></div>
        <h3 class="title"></h3>
        <a class="prev">‹</a>
        <a class="next">›</a>
        <a class="close">×</a>
        <a class="play-pause"></a>
        <ol class="indicator"></ol>
        <div class="modal fade">
          <div class="modal-dialog">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" aria-hidden="true">&times;</button>
                <h4 class="modal-title"></h4>
              </div>
              <div class="modal-body next"></div>
              <div class="modal-footer">
                <button type="button" class="btn btn-default pull-left prev">
                  <i class="glyphicon glyphicon-chevron-left"></i>Previous
                </button>
                <button type="button" class="btn btn-primary next">Next
                  <i class="glyphicon glyphicon-chevron-right"></i>
                </button>
              </div>
            </div>
          </div>
        </div>
    </div>
    <div class="container-fluid"><div class="row">'
,
   
'#suffix' => '</div></div>',
   
'#attached' => array(
     
'css' => array(
       
'https://cdnjs.cloudflare.com/ajax/libs/blueimp-gallery/2.15.2/css/blueimp-gallery.min.css' => array(
         
'type' => 'external',
        ),
      ),
     
'js' => array(
       
'https://cdnjs.cloudflare.com/ajax/libs/blueimp-gallery/2.15.2/js/jquery.blueimp-gallery.min.js' => array(
         
'type' => 'external',
        ),
      ),
    ),
  );
  switch (
$field['field_name']) {
//    case 'field_gallery':
//      foreach ($items as $delta => $item) {
//        $thumb = array(
//          '#theme' => 'image_style',
//          '#style_name' => 'medium', // Insert your image style machine name here
//          '#path' => $item['uri'],
//          '#title' => $item['title'],
//          '#alt' => $item['title'],
//        );
//        $main = array(
//          '#theme' => 'image',
//          '#path' => $item['uri'],
//          '#title' => $item['title'],
//          '#alt' => $item['title'],
//        );
//        $element[$delta] = array(
//          '#markup' => '<a href="' . file_create_url($item['uri']) . '" title="' . $item['title'] . '" data-gallery="#blueimp-gallery-' . $type .'">' . render($thumb) . '</a>',
//        );
//      }
//      break;
   
case 'field_video':
      foreach (
$items as $delta => $item) {
       
$thumb = array(
         
'#theme' => 'image',
         
'#path' => image_style_url('video_thumb__400x280_', $item['thumbnail_path']), // Insert your image style machine name here
         
'#alt' => $item['description'],
         
'#title' => $item['description'],
         
'#attributes' => array(
           
'class' => array('img-responsive'),
          ),
         
'#width' => '400',
         
'#height' => '280',
        );
       
$id = '';
       
$vars = array();
       
parse_str(parse_url($item['video_url'], PHP_URL_QUERY ), $vars);
        if (isset(
$vars['v'])) {
         
$id = $vars['v'];
         
$poster = 'http://img.youtube.com/vi/' . $id . '/sddefault.jpg';
         
$data_id = 'data-youtube="' . $id . '" ';
        }
        else {
         
$id = (int) substr(parse_url($item['video_url'], PHP_URL_PATH), 1);
         
$data_id = 'data-vimeo="' . $id . '" ';
         
$hash = unserialize(file_get_contents('http://vimeo.com/api/v2/video/' . $id . '.php'));
         
$poster = $hash[0]['thumbnail_large'];
        }
       
$element[$delta] = array(
         
'#markup' => '<a href="' . $item['video_url'] . '" '
         
. 'title="' . $item['description'] . '" '
         
. 'type="text/html"  '
         
. $data_id
         
. 'data-poster="' . $poster . '" '
         
. 'data-gallery="#blueimp-gallery-' . $type .'">' . render($thumb) . '</a>',
        );
      }
      break;
  }
  return
$element;
}
?>

The style_name name in the code above can be changed to whatever image style you choose. Next we need to override the field template so we can change the wrapper div around each field output. To do this we need to copy the field.tpl.php file located at modules/field/theme and place it in our themes template folder. Rename the template file so it overrides fields for that specific image field, more information about overriding fields here: http://api.drupal.org/api/function/theme_field/7. Note the grid classes I've used, this can be altered according to your design.


<?php foreach ($items as $delta => $item): ?>
<div class="col-sm-6 col-md-4 col-lg-3"><?php print render($item); ?></div>
<?php endforeach; ?>

As always, remember to clear your cache. Now head over to admin/structure/types/manage/ and click Manage Display on your content type, go to your video field and you should now be able to choose the Bootstrap Video Gallery format for the video type.


bootstrap gallery



Below is the Bootstrap video gallery in action. Click one of the thumbnail images

In the Night Garden Horror Trailer - NOT SUITABLE FOR CHILDREN
I will see you again, at the Rainbow Bridge. RIP Daisy the dog.