Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

If I embed a YouTube video into a post, how do I put a play button over the featured image so that the video can be played without having to open the whole post?

I.e Flipboard the iOS app has a function which allows you to watch videos from the featured image stage.

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

It happens that I answered a similar Question.
And adapting it a little bit, some serious magic can happen ;)

Notes:

  • the CSS is being printed inline. It should go with the theme's style.css and be adapted accordingly.

  • each Featured Image is encapsulated in a div with id="videocontainer-' . $post_id . '".

  • and a Javascript variable in printed together with each FI containing
    var embedCode_' . $post_id .' = \'' . $iframe .'\';.

  • then, the FI is replaced with the YouTube iframe via Javascript using innerHTML.

  • other notes and credits in the comments.

<?php
/**
 * Plugin Name: Featured Image to YouTube Player
 * Plugin URI: http://wordpress.stackexchange.com/q/78140/12615
 * Description: Swaps the Featured Image by a YouTube player (click to load/play). 
   Needs a custom field with a YouTube video ID 'youtube' 
 * Version: 1.0
 * Author: brasofilo
 * Author URI: http://wordpress.stackexchange.com/users/12615/brasofilo
 * Licence: GPLv2 or later
 * Notes: 
   Plugin skeleton from Plugin Class Demo (https://gist.github.com/3804204), by toscho. 
   CSS Overlay images (http://stackoverflow.com/q/403478), by Tim K. 
   Extracting image attributes from Html (http://stackoverflow.com/a/10131137), by hackre.
 */

add_action(
    'plugins_loaded',
    array ( BL_Featured_Youtube_Thumb::get_instance(), 'plugin_setup' )
);

class BL_Featured_Youtube_Thumb
{
    /**
     * Plugin instance.
     *
     * @see get_instance()
     * @type object
     */
    protected static $instance = NULL;

    /**
     * URL to this plugin's directory.
     *
     * @type string
     */
    public $plugin_url = '';

    /**
     * Path to this plugin's directory.
     *
     * @type string
     */
    public $plugin_path = '';

    /**
     * Access this plugin’s working instance
     *
     * @wp-hook plugins_loaded
     * @since   2012.09.13
     * @return  object of this class
     */
    public static function get_instance()
    {
        NULL === self::$instance and self::$instance = new self;

        return self::$instance;
    }

    /**
     * Used for regular plugin work.
     *
     * @wp-hook plugins_loaded
     * @since   2012.09.10
     * @return  void
     */
    public function plugin_setup()
    {
        $this->plugin_url    = plugins_url( '/', __FILE__ );
        $this->plugin_path   = plugin_dir_path( __FILE__ );

        add_filter( 
            'post_thumbnail_html', 
            array( $this, 'thumbnail_to_youtube' ) , 
            10, 5 
        );
        add_action( 
            'wp_head', 
            array( $this, 'print_click_to_play_css' ) 
        );
    }

    /**
     * Constructor. Intentionally left empty and public.
     *
     * @see plugin_setup()
     * @since 2012.09.12
     */
    public function __construct() {}

    /**
     * Filters post_thumbnail_html
     * If the post contains a Custom Field ('youtube') with a video ID, replacement is done
     */
    public function thumbnail_to_youtube( $html, $post_id, $post_thumbnail_id, $size, $attr )
    {   
        $yt = get_post_meta( $post_id, 'youtube', true );

        // Post without YT ID, exit earlier
        if( !$yt )
            return $html;

        // Extract info from the html source
        $atts = $this->get_html_img_attributes( $html );

        // Overlay for Featured Image
        // $click_to_play = $this->plugin_url . 'click-to-play.png';
        // $click_to_play = get_stylesheet_directory_uri() . '/click-to-play.png';
        $click_to_play = 'http://upload.wikimedia.org/wikipedia/commons/thumb/archive/4/47/20051015080301%21PNG_transparency_demonstration_1.png/120px-PNG_transparency_demonstration_1.png';

        // Render final output
        $output = $this->get_featured_yt_thumbnail( $html, $click_to_play, $atts, $post_id, $yt );

        return $output;
    }

    /**
     * Print inline CSS in frontend <head>
     * - just for demonstrations purposes, include this in your theme style.css!
     */
    public function print_click_to_play_css()
    {
        ?>
        <style>
        a.gallerypic{
          width:inherit;
          text-decoration:none;
          position:relative;
          display:block;
          float:left;
        }

        a.gallerypic span.zoom-icon{
          visibility:hidden;
          position:absolute;
          left:35%;
          top:35%;
        }

        a.gallerypic:hover span.zoom-icon{
          visibility:visible;
        }
        </style>
        <?php
    }

    /**
     * Generate the Html for the Featured Image thumbnail.
     * Prints one javascript line per thumbnail (not sure if the best method)
     */
    private function get_featured_yt_thumbnail( $html, $img, $atts, $post_id, $yt )
    {
        $iframe = '<iframe title="" class="youtube-player" type="text/html" width="' 
                    . $atts['width'] 
                    . '" height="' 
                    . $atts['height'] 
                    . '" src="http://www.youtube.com/embed/' 
                    . $yt 
                    . '?autoplay=1" frameborder="0" allowFullScreen></iframe>';


        $return = '
            <div id="videocontainer-' . $post_id . '">
                <a href="javascript:void(0)" onclick="document.getElementById(\'videocontainer-' . $post_id
         . '\').innerHTML = embedCode_'.$post_id.';" class="gallerypic" title="">
                    <img src="' . $atts['src'] . '" height="' . $atts['height'] . '" width="' . $atts['width'] . '" alt="' . $atts['alt'] . '" class="pic" />
                    <span class="zoom-icon">
                        <img src="' . $img . '" width="160" height="120" alt="Zoom">
                    </span>
                </a>
            </div>
            <script type="text/javascript">var embedCode_' 
                    . $post_id 
                    . '  = \''
                    . $iframe 
                    . '\';</script>';

        return $return;
    }

    /**
     * Extract image attributes from Html
     * @author hackre
     * @url    http://stackoverflow.com/a/10131137/1287812
     */
    private function get_html_img_attributes( $html )
    {
        $xpath = new DOMXPath( @DOMDocument::loadHTML( $html ) );
        $src = $xpath->evaluate( "string(//img/@src)" );
        $alt = $xpath->evaluate( "string(//img/@alt)" );
        $width = $xpath->evaluate( "string(//img/@width)" );
        $height = $xpath->evaluate( "string(//img/@height)" );
        return array( 
                'src' => $src
            ,   'alt' => $alt
            ,   'width' => $width
            ,   'height' => $height
        );
    }
}
share|improve this answer
2  
I like your code style. :D –  toscho Jan 4 '13 at 21:03
    
@toscho, you won't believe how it looked a year ago, I've learned like one Yotaton of great style since being here :o) –  brasofilo Jan 4 '13 at 21:13
    
Do I just insert this into the wordpress Loop? –  Andrew John Jan 9 '13 at 20:57
add comment

You can't just put a play button over an image and expect it to play a video without some serious magic.

What you can do easily is change the video oembed size depending on what the viewer is looking at, for example for the front loop you can have a very tiny (thumbnail size) video that plays, and if they click through to the post they get larger size.

You can add a content filter like the following.

add_filter( 'the_content', 'wpse_78140_Embed' );

function wpse_78140_Embed( $content ) {

    if ( is_front_page() ) {

        //return small video, youtube has a cap here so play with it
        $embed_code = wp_oembed_get( 
                                   'http://www.youtube.com/watch?v=M8yBcry1RHU',  
                                    array( 'width'=>200, 'height'=>200 ) );

        $content = $content . $embed_code;

        return $content;

    } elseif ( is_single() )

        //just return the regular size video
        $embed_code = wp_oembed_get( 'http://www.youtube.com/watch?v=M8yBcry1RHU' );

        $content = $content . $embed_code;

        return $content;
}

In this example the video is hard-coded, so it is advised you add it using a get_post_meta or parse the content.

ps. I tried several oembed filters and could not get it to change anything so maybe there is a better solution.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.