Created
December 20, 2011 12:18
-
-
Save pbuyle/1501391 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Implements hook_field_info(). | |
*/ | |
function MODULE_field_info() { | |
return array( | |
'video_thumbnail_settings' => array( | |
'label' => t('Video Thumbnail Settings'), | |
'description' => t('Configure Video Thumbnail display.'), | |
'settings' => array(), | |
'instance_settings' => array(), | |
'default_widget' => 'video_thumbnail_settings_widget', | |
'default_formatter' => 'video_thumbnail_settings_formatter', | |
'no_ui' => FALSE // TODO: Set to TRUE and automatically create a field instance when needed | |
), | |
); | |
} | |
/** | |
* Implements hook_field_widget_info(). | |
*/ | |
function MODULE_field_widget_info() { | |
return array( | |
'video_thumbnail_settings_widget' => array( | |
'label' => t('Default'), | |
'field types' => array('video_thumbnail_settings'), | |
), | |
); | |
} | |
/** | |
* Implements hook_field_widget_form(). | |
*/ | |
function MODULE_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { | |
$file =& $form_state['file']; | |
if (!empty($file->uri)) { | |
$scheme = file_uri_scheme($file->uri); | |
$local_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL); | |
if (isset($local_wrappers[$scheme]) && ($movie = MODULE_ffmpeg_movie($file)) && $movie->hasVideo()) { | |
if (isset($form_state['values'])) { | |
$path = array_merge($element['#field_parents'], array($field['field_name'], $langcode)); | |
$path_exists = FALSE; | |
$values = drupal_array_get_nested_value($form_state['values'], $path, $path_exists); | |
if ($path_exists) { | |
$items = $values; | |
drupal_array_set_nested_value($form_state['values'], $path, NULL); | |
} | |
} | |
else { | |
foreach ($items as &$item) { | |
switch ($item['mode']) { | |
case 'select': | |
$item['thumbnail']['framenumber'] = $item['value']; | |
break; | |
case 'media': | |
$item['thumbnail']['fid'] = $item['value']; | |
break; | |
} | |
} | |
} | |
$item = !empty($items[$delta]) ? $items[$delta] : array(); | |
$mode = !empty($item['mode']) ? $item['mode'] : 'random'; | |
$element += array( | |
'#type' => 'fieldset', | |
'#title' => 'Thumbnail', | |
'#collapsible' => TRUE, | |
'#collapsed' => TRUE, | |
'#element_validate' => array('MODULE_field_widget_validate'), | |
'mode' => array( | |
'#type' => 'select', | |
'#default_value' => $mode, | |
'#options' => array( | |
'random' => t('Extract random thumbnail'), | |
'select' => t('Select extracted thumbnail'), | |
'media' => t('Select image as thumbnail') | |
), | |
'#return_value' => 1, | |
'#ajax' => array( | |
'callback' => 'MODULE_field_widget_form_thumbnail_callback', | |
'wrapper' => 'thumbnail-wrapper', | |
) | |
), | |
'thumbnail' => array( | |
'#prefix' => '<div id="thumbnail-wrapper">', | |
'#suffix' => '</div>', | |
) | |
); | |
switch ($mode) { | |
case 'random': | |
$element['thumbnail'] += array( | |
'#type' => 'container', | |
); | |
break; | |
case 'select': | |
$framerate = $movie->getFrameRate(); | |
$framecount = $movie->getFrameCount(); | |
$interval = 10; | |
$options = array(); | |
$framenumbers = array(); | |
$framenumber = 1; | |
while ($framenumber < $framecount) { | |
$framenumbers[] = (int)$framenumber; | |
$framenumber += $interval * $framerate; | |
} | |
$framenumbers[] = (int)($framecount - ($framerate * 0.25)); | |
foreach(MODULE_video_extract_frames($file, $framenumbers) as $framenumber => $path) { | |
$options[$framenumber] = theme('image_style', array( | |
'style_name' => 'thumbnail', | |
'path' => $path, | |
'title' => format_interval($framenumber / $framerate) | |
)); | |
} | |
$element['thumbnail'] += array( | |
'#type' => 'container', | |
); | |
$element['thumbnail']['framenumber'] = array( | |
'#type' => 'radios', | |
'#options' => $options, | |
'#default_value' => $item['thumbnail']['framenumber'], | |
'#required' => FALSE, | |
); | |
break; | |
case 'media': | |
$element['thumbnail'] += array( | |
'#type' => 'media', | |
'#mutliple' => FALSE, | |
'#title' => FALSE, | |
'#default_value' => array('fid' => $item['thumbnail']['fid']), | |
'#description' => t('Select an existing image or upload a new one to be used as thumbnail for this video.'), | |
'#media_options' => array( | |
'global' => array( | |
'types' => array('image'), | |
) | |
) | |
); | |
break; | |
} | |
} | |
} | |
$element['#attached']['css'][] = drupal_get_path('module', 'MODULE') . '/css/MODULE.theme.css'; | |
$element['#attached']['js'][] = drupal_get_path('module', 'MODULE') . '/js/MODULE.widget.js'; | |
return $element; | |
} | |
/** | |
* Implements hook_field_widget_validate(). | |
*/ | |
function MODULE_field_widget_validate($element, &$form_state) { | |
$item = array('mode' => $element['mode']['#value']); | |
switch($item['mode']) { | |
case 'random': | |
$item['value'] = 0; | |
break; | |
case 'select': | |
$item['value'] = !empty($element['thumbnail']['framenumber']) ? $element['thumbnail']['framenumber']['#value'] : 0; | |
break; | |
case 'media': | |
$item['value'] = !empty($element['thumbnail']['fid']) ? $element['thumbnail']['fid']['#value'] : 0; | |
break; | |
} | |
form_set_value($element, $item, $form_state); | |
} | |
/** | |
* Ajax callback to update the 'thumbnail' element. | |
* | |
* @see MODULE_field_widget_form(). | |
*/ | |
function MODULE_field_widget_form_thumbnail_callback($form, $form_state) { | |
$triggering_element = $form_state['triggering_element']; | |
$form_state['triggering_element']['#array_parents']; | |
if ($triggering_element['#type'] == 'select') { | |
$parents = array_slice($triggering_element['#array_parents'], 0, -1); | |
} | |
else { | |
$parents = array_slice($triggering_element['#array_parents'], 0, -2); | |
} | |
$parents[] = 'thumbnail'; | |
return drupal_array_get_nested_value($form, $parents); | |
} | |
/** | |
* Implements hook_field_formatter_info(). | |
*/ | |
function MODULE_field_formatter_info() { | |
return array( | |
'video_thumbnail_settings_formatter' => array( | |
'label' => t('Default'), | |
'field types' => array('video_thumbnail_settings'), | |
), | |
); | |
} | |
/** | |
* Formatter for the video_thumbnail_settings_formatter. | |
*/ | |
function MODULE_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { | |
//Don't do anything for video_thumbnail_settings_formatter | |
} | |
/** | |
* Implements hook_field_formatter_settings_form(). | |
*/ | |
function MODULE_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) { | |
$display = $instance['display'][$view_mode]; | |
$settings = $display['settings']; | |
$element = array(); | |
//Don't do anything for video_thumbnail_settings_formatter | |
return $element; | |
} | |
/** | |
* Implements hook_field_is_empty(). | |
*/ | |
function MODULE_field_is_empty($item, $field) { | |
if (!empty($item['mode'])) { | |
switch ($item['mode']) { | |
case 'random': | |
return FALSE; | |
break; | |
case 'select': | |
case 'media': | |
return empty($item['value']); | |
break; | |
} | |
} | |
else { | |
return TRUE; | |
} | |
} | |
/** | |
* Implements hook_field_validate(). | |
*/ | |
function MODULE_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) { | |
$function = __FUNCTION__ . '_' . $field['type']; | |
if (function_exists($function)) { | |
return $function($entity_type, $entity, $field, $instance, $langcode, $items, $errors); | |
} | |
} | |
/** | |
* Implements hook_field_validate() for the video_thumbnail_settings filed type. | |
*/ | |
function MODULE_field_validate_video_thumbnail_settings($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) { | |
if ($entity_type == 'file') { | |
foreach ($items as $delta => $item) { | |
switch ($item['mode']) { | |
case 'random': | |
break; | |
case 'select': | |
$file = file_load($entity->fid); | |
$scheme = file_uri_scheme($file->uri); | |
$local_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL); | |
if (isset($local_wrappers[$scheme]) && ($movie = MODULE_ffmpeg_movie($file)) && $movie->hasVideo()) { | |
$framecount = $movie->getFrameCount(); | |
if ($item['value'] < 1 || $item['value'] >= $framecount) { | |
$errors[$field['field_name']][$langcode][$delta][] = array( | |
'error' => 'video_thumbnail_settings_framenumber', | |
'message' => t('Invalid thumbnail frame number.'), | |
); | |
} | |
} | |
break; | |
case 'media': | |
$thumbnail = file_load($item['value']); | |
if (!$thumbnail || $thumbnail->type !== 'image') { | |
$errors[$field['field_name']][$langcode][$delta][] = array( | |
'error' => 'video_thumbnail_settings_media', | |
'message' => t('Invalid thumbnail media.'), | |
); | |
} | |
break; | |
default: | |
$errors[$field['field_name']][$langcode][$delta][] = array( | |
'error' => 'video_thumbnail_settings_mode', | |
'message' => t('Invalid thumbnail mode.'), | |
); | |
break; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// @todo Remove when http://drupal.org/node/977052 is fixed. | |
require_once dirname(__FILE__) . '/MODULE.field.inc'; | |
/** | |
* Implement hook_file_formatter_info(). | |
*/ | |
function MODULE_file_formatter_info() { | |
$formatters = array(); | |
if (extension_loaded('ffmpeg')) { | |
$formatters['video_thumbnail'] = array( | |
'label' => t('Video Thumbnail'), | |
'default settings' => array( | |
'image_style' => '', | |
'field' => '', | |
), | |
'view callback' => 'MODULE_file_formatter_video_thumbnail_view', | |
'settings callback' => 'MODULE_file_formatter_video_thumbnail_settings', | |
); | |
} | |
return $formatters; | |
} | |
/** | |
* Helper function to retrieve the path to an extracted video frame as a JPG | |
* file. | |
* | |
* @param string $uri | |
* The URI of the video file. | |
* @param int $framenumber | |
* The extracted frame number. | |
* | |
* @return | |
* The path for an extracted video frame as a JPG file. The actual file may not | |
* exist. | |
*/ | |
function MODULE_video_frame_path($uri, $framenumber = 0) { | |
$scheme = file_uri_scheme($uri); | |
if ($scheme) { | |
$path = file_uri_target($uri); | |
} | |
else { | |
$path = $uri; | |
$scheme = file_default_scheme(); | |
} | |
return $scheme . '://video_frames/' . $scheme . '/' . preg_replace('/\.[^.]+$/', "-$framenumber.jpg", $path); | |
} | |
/** | |
* Build the poster frame for an video file. | |
* | |
* @param object $file | |
* The (fully loaded) file entity for which to build a poster frame. | |
* @param array $settings | |
* The build settings, the following properties are supported | |
* - 'mode': one of 'select', 'random' and 'media'. | |
* - 'value': if 'mode' is 'media', the fid of (image) file entity to use as | |
* poster frame. If 'mode' is 'select', the frame number of the | |
* frame to extract as poster frame. Not used if 'mode' is 'random' | |
* | |
* @return | |
* The path to an image file to use as poster frame. Or NULL if no poster frame | |
* could be build (invalid file or settings). | |
*/ | |
function MODULE_build_video_poster_frame($file, $settings) { | |
if (is_object($file) && !empty($file->type) && $file->type === 'video') { | |
switch ($settings['mode']) { | |
case 'media': | |
$thumbnail_file = file_load($settings['value']); | |
if ($thumbnail_file && ($thumbnail_file->type == 'image')) { | |
$path = $thumbnail_file->uri; | |
} | |
break; | |
case 'random': | |
$settings['value'] = 0; | |
case 'select': | |
$path = MODULE_video_extract_frame($file, $settings['value']); | |
break; | |
} | |
if (!empty($path) && file_exists($path)) { | |
return $path; | |
} | |
} | |
return NULL; | |
} | |
/** | |
* Helper function to extract a single frame from a video file. The extracted | |
* frame file name is build by appending the frame number to the video file | |
* name. If the given frame bnumber is 0 (or not a number), then a random frame | |
* is extracted but 0 is used as suffix when building the frame file name. | |
* | |
* @param object $file | |
* A file entity. | |
* @param int $framenumber | |
* (optional) The frame from the movie to extract. | |
* | |
* @return | |
* The path to the extracted frame as a unmanaged JPG file. Or NULL if no frame | |
* could be extracted. | |
* | |
*/ | |
function MODULE_video_extract_frame($file, $framenumber = 0) { | |
if (!is_numeric($framenumber)) { | |
$framenumber = 0; | |
} | |
$paths = MODULE_video_extract_frames($file, array($framenumber)); | |
if (empty($paths)) { | |
return NULL; | |
} | |
else { | |
return reset($paths); | |
} | |
} | |
/** | |
* Helper function to extract multiples frame sfrom a video file. The extracted | |
* frames file names are build by appending the frame numbers to the video file | |
* name. If a given frame number is 0 (or not a number), then a random frame is | |
* extracted but 0 is used as suffix when building the frame file name. | |
* | |
* If for some reason a frame couldn't get extracted (ie. it frame number is | |
* lower than the frame count but ffmpeg_movie::getFrame() returns null). Then | |
* the first found frame before the requested one is used. | |
* | |
* @param object $file | |
* A file entity. | |
* @param int $framenumbers | |
* (optional) The frames from the movie to extract. | |
* | |
* @return | |
* An array of paths for the extracted frame as a unmanaged JPG files, indexed | |
* by the (requested) frame number. | |
* | |
*/ | |
function MODULE_video_extract_frames($file, $framenumbers, $suffix = TRUE) { | |
set_time_limit(0); | |
$scheme = file_uri_scheme($file->uri); | |
$local_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL); | |
$paths = array(); | |
if (isset($local_wrappers[$scheme])) { | |
$suffix = $suffix || (count($framenumbers) > 1); | |
if (($movie = MODULE_ffmpeg_movie($file)) && $movie->hasVideo()) { | |
sort($framenumbers); | |
$framecount = $movie->getFrameCount(); | |
$framerate = $movie->getFrameRate(); | |
foreach ($framenumbers as $framenumber) { | |
$path = MODULE_video_frame_path($file->uri, $framenumber); | |
if (!file_exists($path)) { | |
$requested_framenumber = $framenumber; | |
if ($framenumber < 1 || !is_numeric($framenumber)) { | |
$framenumber = rand(1, $framecount - 1); | |
} | |
$frame = NULL; | |
// Loop until we get a frame. | |
while (!$frame && $framenumber > 0) { | |
$frame = $movie->getFrame($framenumber--); | |
} | |
if ($frame) { | |
$resource = $frame->toGDImage(); | |
file_prepare_directory(drupal_dirname($path), FILE_CREATE_DIRECTORY); | |
if (imagejpeg($resource, drupal_realpath($path))) { | |
$paths[$requested_framenumber] = $path; | |
} | |
imagedestroy($resource); | |
} | |
} | |
else { | |
$paths[$framenumber] = $path; | |
} | |
} | |
} | |
} | |
return $paths; | |
} | |
/** | |
* Return a ffmpeg_movie object for a file. ffmpeg_movie objects are statically | |
* cached. | |
* | |
* @param object $file | |
* A file object. | |
* | |
* @return | |
* A ffmpeg_movie instance. Or null if $file is not a local file or if an | |
* instance could not be created. | |
* | |
* @see ffmpeg_movie::__construct(). | |
*/ | |
function MODULE_ffmpeg_movie($file) { | |
$cache =& drupal_static(__FUNCTION__, array()); | |
$scheme = file_uri_scheme($file->uri); | |
$local_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL); | |
if (isset($local_wrappers[$scheme])) { | |
if (!isset($cache[$file->uri])) { | |
return $cache[$file->uri] = @(new ffmpeg_movie(drupal_realpath($file->uri))); | |
} | |
else { | |
return $cache[$file->uri]; | |
} | |
} | |
return NULL; | |
} | |
/** | |
* View callback for the Video Thumbnail file formatter. | |
*/ | |
function MODULE_file_formatter_video_thumbnail_view($file, $display, $langcode) { | |
$settings = !empty($display['settings']['field']) ? field_get_items('file', $file, $display['settings']['field']) : FALSE; | |
if ($settings === FALSE) { | |
$settings = array('mode' => 'random', 'value' => 0); | |
} | |
else { | |
$settings = reset($settings); | |
} | |
$path = MODULE_build_video_poster_frame($file, $settings); | |
if (!empty($path)) { | |
if (!empty($display['settings']['image_style'])) { | |
$element = array( | |
'#theme' => 'image_style', | |
'#style_name' => $display['settings']['image_style'], | |
'#path' => $path, | |
); | |
} | |
else { | |
$element = array( | |
'#theme' => 'image', | |
'#path' => $path, | |
); | |
} | |
return $element; | |
} | |
} | |
/** | |
* Settings callback for the Video Thumbnail file formatter. | |
*/ | |
function MODULE_file_formatter_video_thumbnail_settings($form, &$form_state, $settings) { | |
$element = array(); | |
$element['image_style'] = array( | |
'#title' => t('Image style'), | |
'#type' => 'select', | |
'#options' => image_style_options(FALSE), | |
'#default_value' => $settings['image_style'], | |
'#empty_option' => t('None (original image)'), | |
); | |
// TODO: Remove this setting and use a single automatically create field instance | |
$fields = array(); | |
foreach (field_info_instances('file', $form['#file_type']) as $instance) { | |
$field = field_info_field_by_id($instance['field_id']); | |
if ($field['type'] == 'video_thumbnail_settings') { | |
$fields[$field['field_name']] = $instance['label']; | |
} | |
} | |
if (!empty($fields)) { | |
$element['field'] = array( | |
'#title' => t('Thumbnail frame from field:'), | |
'#type' => 'select', | |
'#options' => $fields, | |
'#default_value' => $settings['field'], | |
'#empty_option' => t('None (random frame)'), | |
); | |
} | |
return $element; | |
} | |
/** | |
* Implements hook_file_formatter_info_alter(). | |
*/ | |
function MODULE_file_formatter_info_alter(&$info) { | |
// Orverride the MediaElement File Field formatter wrapped by File entity to | |
// use our own callbacks and extend the available settings. | |
$info['file_field_mediaelement_video']['view callback'] = 'MODULE_file_formatter_mediaelement_view'; | |
$info['file_field_mediaelement_video']['settings callback'] = 'MODULE_file_formatter_mediaelement_settings'; | |
$info['file_field_mediaelement_video']['default settings']['poster'] = ''; | |
$info['file_field_mediaelement_video']['default settings']['detect_size'] = FALSE; | |
} | |
/** | |
* Settings form callback for the mediaelement video file formatter (not file | |
* field). | |
* | |
* @see file_entity_file_formatter_file_field_settings() | |
*/ | |
function MODULE_file_formatter_mediaelement_settings($form, &$form_state, $settings, $formatter_type, $file_type, $view_mode) { | |
// Get the settign form as provided by the File Entity module. | |
$form = file_entity_file_formatter_file_field_settings($form, $form_state, $settings, $formatter_type, $file_type, $view_mode); | |
// Additional settings | |
$poster_options = array( | |
NULL => t('None'), | |
'random' => t('Select a random frame'), | |
); | |
$fields = array(); | |
foreach (field_info_instances('file', $file_type) as $instance) { | |
$field = field_info_field_by_id($instance['field_id']); | |
if ($field['type'] == 'video_thumbnail_settings') { | |
$poster_options['field_' . $field['field_name']] = $instance['label']; | |
} | |
if (in_array($field['type'], array('file', 'link_field', 'media'))) { | |
$tracks_options[$field['field_name']] = $instance['label']; | |
} | |
} | |
$form['detect_size'] = array( | |
'#type' => 'checkbox', | |
'#title' => t('Detect video size'), | |
'#description' => t('If checked, the height and width of the video will be detected and the Height and Witdh settings will be used as maximum values.'), | |
'#default_value' => $settings['detect_size'] | |
); | |
$form['poster'] = array( | |
'#type' => 'select', | |
'#title' => t('Poster frame'), | |
'#options' => $poster_options, | |
'#default_value' => $settings['poster'], | |
); | |
if (!empty($tracks_options)) { | |
$form['tracks'] = array( | |
'#type' => 'fieldset', | |
'#title' => t('Text tracks'), | |
'#description' => t('Select the fields used to provide <a href="@url">Text tracks</a> for the video element.', array( | |
'@url' => 'http://www.w3.org/TR/html5/video.html#text-track', | |
)), | |
'#collapsible' => TRUE, | |
'#collapsed' => FALSE, | |
'#tree' => TRUE, | |
); | |
$kinds = array( | |
'' => t("Don't use as tracks"), | |
'subtitles' => t('Subtitles'), | |
'captions' => t('Caption'), | |
'descriptions' => t('Descriptions'), | |
'chapters' => t('Chapters'), | |
'metadata' => t('Metadata'), | |
); | |
foreach($tracks_options as $field_name => $title) { | |
$form['tracks'][$field_name] = array( | |
'#type' => 'select', | |
'#title' => $title, | |
'#options' => $kinds, | |
'#default_value' => !empty($settings['tracks'][$field_name]) ? $settings['tracks'][$field_name] : NULL, | |
); | |
} | |
} | |
return $form; | |
} | |
/** | |
* View callback for the mediaelement video file formatter (not file field). | |
* | |
* @see file_entity_file_formatter_file_field_view(); | |
*/ | |
function MODULE_file_formatter_mediaelement_view($file, $display, $langcode) { | |
$element = file_entity_file_formatter_file_field_view($file, $display, $langcode); | |
if ($element) { | |
// Apply poster frame settings | |
if (!empty($display['settings']['poster'])) { | |
$poster_settings = ($display['settings']['poster'] !== 'random') ? field_get_items('file', $file, substr($display['settings']['poster'], 6)) : FALSE; | |
if ($poster_settings === FALSE) { | |
$poster_settings = array('mode' => 'random', 'value' => 0); | |
} | |
else { | |
$poster_settings = reset($poster_settings); | |
} | |
$path = MODULE_build_video_poster_frame($file, $poster_settings); | |
if (!empty($path)) { | |
$element['#attributes']['poster'] = file_create_url($path); | |
$element['#attributes']['poster'] = file_create_url($path); | |
} | |
} | |
// Apply size detection settings | |
if (!empty($display['settings']['detect_size']) && $movie = MODULE_ffmpeg_movie($file)) { | |
$height = $movie->getFrameHeight(); | |
$width = $movie->getFrameWidth(); | |
$ratio = $width / $height; | |
if ($display['settings']['width'] > 0 && $width > $display['settings']['width']) { | |
$height = $display['settings']['width'] / $ratio; | |
$width = $display['settings']['width']; | |
} | |
if ($display['settings']['height'] > 0 && $height > $display['settings']['height']) { | |
$width = $ratio * $height; | |
$height = $display['settings']['height']; | |
} | |
$element['#settings']['height'] = $element['#attributes']['height'] = $height; | |
$element['#attached']['js'][0]['data']['mediaelement']['.' . $element['#attributes']['class']]['opts']['videoHeight'] = $height; | |
$element['#settings']['width'] = $element['#attributes']['width'] = $width; | |
$element['#attached']['js'][0]['data']['mediaelement']['.' . $element['#attributes']['class']]['opts']['videoWidth'] = $width; | |
} | |
// Apply tracks settings | |
if (!empty($display['settings']['tracks'])) { | |
foreach (array_filter($display['settings']['tracks']) as $field_name => $kind) { | |
foreach(field_available_languages('file', $field_name) as $langcode) { | |
if ($values = field_get_items('file', $file, $field_name, $langcode)) { | |
$field = field_info_field($field_name); | |
foreach($values as $value) { | |
$track = array(); | |
switch($field['type']) { | |
case 'file': | |
$value = (object)$value; | |
$track += array( | |
'src' => file_create_url($value->uri), | |
'label' => entity_label('file', $value), | |
); | |
break; | |
case 'media': | |
$value = $value['file']; | |
$track += array( | |
'src' => file_create_url($value->uri), | |
'label' => entity_label('file', $value), | |
); | |
break; | |
case 'link_field': | |
// FIXME Does it work ? | |
$track += array( | |
'src' => $value['url'], | |
'label' => check_plain($value['title']), | |
); | |
break; | |
} | |
if ($track) { | |
$track += array( | |
'srclang' => $langcode, | |
'kind' => $kind, | |
); | |
$element['#tracks'][] = $track; | |
} | |
} | |
} | |
} | |
} | |
} | |
return $element; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#thumbnail-wrapper .form-radios .form-type-radio { | |
float: left; | |
} | |
#thumbnail-wrapper .form-radios .form-type-radio input { | |
display: none; | |
} | |
#thumbnail-wrapper .form-radios .form-type-radio label { | |
display: block; | |
overflow: hidden; | |
/*border: 1px solid transparent;*/ | |
} | |
#thumbnail-wrapper .form-radios .form-type-radio label img { | |
border: 2px dashed transparent; | |
padding: 1px; | |
} | |
#thumbnail-wrapper .form-radios .form-type-radio.selected label img { | |
border-color: #0074BD; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($){ | |
Drupal.behaviors.videoThumbnailSettingsField = { | |
attach: function(context, setting) { | |
jQuery('#thumbnail-wrapper .form-radios', context) | |
.once('video-thumbnail-settings-field') | |
.delegate('input:radio', 'change', function(e){ | |
jQuery(this) | |
.parents('.form-radios') | |
.find('.form-type-radio') | |
.removeClass('selected') | |
.end() | |
.end() | |
.parents('.form-type-radio') | |
.addClass('selected') | |
.end() | |
}) | |
.find('input:checked') | |
.parents('.form-type-radio') | |
.addClass('selected'); | |
} | |
}; | |
}(jQuery)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment