One of the requests I've had for a website I'm currently working
on is to provide a placeholder image for an embedded Youtube
Video. Essentially, the client wants to display the image
until someone clicks on it, then replace it with the video.
So here's how I did it with the new uTube package for Umbraco, but
the same technique can be used for any web page...
With this method, I'm not trying to play the video in a separate
window, or resize anything, I'm just wanting to have the video take
the place of the image on the website. This makes things a
little easier, as I can render both the video and the image in
separate div's and use CSS to lay one on top of the other using
z-index and position elements. In addition, I can use some
fairly straight forward jquery javascript to hide one element and
show the other.
Rendering a Flash Video player with an Image overlay
Here's a sample of the HTML including embedded javascript:
<div id="mainFeature">
<div id="mediaVideo" style="visibility: hidden">
<div class="youTubePlayer" style="height: 433px; width: 680px;">
<div id="ytPlayerAPI-rldN0jSBbZQ">
<p>
You need Flash version 8 and JS enabled to view the video</p>
</div>
<script type="text/javascript">
//SWF Embedd
var flashVars = { video_id: "rldN0jSBbZQ", playerapiid: "ytPlayerAPI-rldN0jSBbZQ", allowFullScreen: "true" }
var params = { allowScriptAccess: "always", wmode: "transparent", allowFullScreen: "true" };
var atts = { id: "ytPlayerAPI-rldN0jSBbZQ" };
swfobject.embedSWF("http://www.youtube.com/v/rldN0jSBbZQ?fs=1&rel=0&enablejsapi=1&version=3&playerapiid=ytPlayerAPI-rldN0jSBbZQ", "ytPlayerAPI-rldN0jSBbZQ", "680", "433", "8", null, flashVars, params, atts);
</script>
</div>
</div>
<div id="mediaImage">
<a href="/recipes/crispy-chinese-chicken-with-sichuan-salt-pepper" title="Crispy Chinese Chicken with Sichuan Salt & Pepper">
<img src="/media/2245/crispy_chinese_chicken_01.jpg" title="Crispy Chinese Chicken with Sichuan Salt & Pepper"
alt="Crispy Chinese Chicken with Sichuan Salt & Pepper" /></a></div>
<script type="text/javascript">
$(document).ready(function () {
$('div#mediaImage a').click(function () {
$('div#mediaVideo').css('visibility', 'visible');
$('div#mediaImage').fadeOut(1000);
return false;
});
});
</script>
</div>
And the corresponding CSS to initially lay out the elements:
#mediaVideo, #mediaImage {
position: absolute;
left: 0;
top: 0;
}
#mediaImage {
z-index: 10;
}
Notice that in this example I'm using the SWFObject library to
render the flash player. For some reason I haven't fully explored
yet, if you render the flash object using object tags, the flash
player is rendered on top of the mediaImage instead of obeying the
CSS rules and rendering the image div on top as it should.
The result? When the user clicks on the image, it fades out and
is replaced by the flash object.
Displaying embedded Youtube Videos on an iPhone/iPad
The thing about iPhone and iPad is it doesn't yet support
Flash. However, if you use the object tags approach, the
device is smart enough to recognise the Youtube player and use the
built-in YouTube app in it's place. This is a pretty cool
feature, but doesn't appear to work if you use the SWFObject
library approach above. Only problem is, although iPhones etc
support javascript, and will honour the code above, all you see is
the following message:
Rendering a Youtube
embedded video with the SWFObject on iPhone...
And using the <object> tag approach:
Rendering a Youtube embedded video
with object tags on iPhone...
Clicking on the video launches the
Youtube App. The iPad plays the video in place in the website
using the Youtube app, which is pretty cool, only launching a
separate window if you view it in fullscreen mode.
The code for rendering the Youtube
with object tags is as follows:
<div class="youTubePlayer" style="height: 433px; width: 680px;">
<object width="680" height="433">
<param name="movie" value="http://www.youtube.com/v/rldN0jSBbZQ?fs=1&rel=0" />
<param name="allowFullScreen" value="true" />
<param name="allowscriptaccess" value="always" />
<embed src="http://www.youtube.com/v/rldN0jSBbZQ?fs=1&rel=0" type="application/x-shockwave-flash"
allowscriptaccess="always" allowfullscreen="true" width="680" height="433" /></object></div>
The best of both worlds: Supporting iPhone and rendering
placeholder Images...
It's a compromise, but since we can't
get both apple devices and standard browsers to render the same
thing, we need to use the HTTP_USER_AGENT string to conditionally
render the different approaches.
Umbraco
and the uTube plugin...
For those
of us utilising the excellent new uTube plugin with Umbraco, the
following XSLT code should do the trick - note that you'll have to
render the Chrome player if you want Full screen mode, as the
chromeless player doesn't support it. See my earlier post
about this: Enabling
Alternate Media with the uTube Umbraco Package
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon"
xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes"
xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath"
xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions"
xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings"
xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:yt="http://gdata.youtube.com/schemas/2007"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns:uTube.XSLT="urn:uTube.XSLT"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath
Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets atom yt media uTube.XSLT">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<xsl:template match="/">
<!-- YouTube URL or VideoID -->
<xsl:variable name="uTubeVideo" select="/macro/uTubeVideo" />
<xsl:variable name="allowFullScreen" select="/macro/allowFullScreen" />
<xsl:variable name="allowRelatedVideos" select="/macro/allowRelatedVideos" />
<xsl:variable name="jsPlayerApiId" select="/macro/jsPlayerApiId" />
<!-- Don't do anything unless we have a value in uTubeVideo -->
<xsl:if test="/macro/uTubeVideo">
<xsl:variable name="uTubeVideoID" select="uTube.XSLT:GetVideoId($uTubeVideo)" />
<xsl:variable name="uTubeXML" select="uTube.XSLT:GetVideoData($uTubeVideoID, 60)"/>
<xsl:variable name="uTubeRatio" select="uTube.XSLT:GetAspectRatio($uTubeVideoID)"/>
<!-- Video Width -->
<xsl:variable name="uTubeWidth">
<xsl:choose>
<!-- If the Width is not set, then check if Height is available -->
<xsl:when test="not(/macro/uTubeWidth) and /macro/uTubeHeight">
<!-- Use the Height to get the Width -->
<xsl:value-of select="uTube.XSLT:GetVideoWidth(/macro/uTubeHeight, $uTubeRatio)" />
</xsl:when>
<!-- If the Width is set, use it! -->
<xsl:when test="/macro/uTubeWidth">
<xsl:value-of select="/macro/uTubeWidth" />
</xsl:when>
<!-- Otherwise fall back on a default value -->
<xsl:otherwise>
<xsl:value-of select="number(480)" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Video Height -->
<xsl:variable name="uTubeHeight">
<xsl:choose>
<!-- If the Height is not set -->
<xsl:when test="not(/macro/uTubeHeight)">
<!-- Then use the Width to get the Height -->
<xsl:value-of select="uTube.XSLT:GetVideoHeight($uTubeWidth, $uTubeRatio)" />
</xsl:when>
<xsl:otherwise>
<!-- Otherwise use the user-defined value -->
<xsl:value-of select="/macro/uTubeHeight" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="allowFullScreenText">
<xsl:choose>
<xsl:when test="$allowFullScreen = 1">true</xsl:when>
<xsl:otherwise>false</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="uTubeRel">
<xsl:choose>
<xsl:when test="$allowRelatedVideos = 1">&rel=1</xsl:when>
<xsl:otherwise>&rel=0</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="enableJSApi">
<xsl:if test="$jsPlayerApiId != ''">&enablejsapi=1&playerapiid=<xsl:value-of select="$jsPlayerApiId" /></xsl:if>
</xsl:variable>
<div class="youTubePlayer" style="height:{$uTubeHeight}px; width:{$uTubeWidth}px;">
<xsl:choose>
<xsl:when test="uTube.XSLT:AllowEmbed($uTubeVideoID) = true()">
<xsl:choose>
<xsl:when test="contains(umbraco.library:RequestServerVariables('HTTP_USER_AGENT'), 'iPad') or
contains(umbraco.library:RequestServerVariables('HTTP_USER_AGENT'), 'iPhone')">
<object width="{$uTubeWidth}" height="{$uTubeHeight}">
<param name="movie"
value="http://www.youtube.com/v/{$uTubeVideoID}?fs={$allowFullScreen}{$uTubeRel}{$enableJSApi}"></param>
<param name="allowFullScreen" value="{$allowFullScreenText}"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/{$uTubeVideoID}?fs={$allowFullScreen}{$uTubeRel}{$enableJSApi}"
type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="{$allowFullScreenText}"
width="{$uTubeWidth}" height="{$uTubeHeight}"></embed>
</object>
</xsl:when>
<xsl:otherwise>
<!-- Video is allowed to be embedded -->
<div id="{concat('ytPlayerAPI-',$uTubeVideoID)}">
<p>You need Flash version 8 and JS enabled to view the video</p>
</div>
<!-- SWFObject call to Embed Chromless player -->
<script type="text/javascript">
//SWF Embedd
var flashVars = {video_id : "<xsl:value-of select="$uTubeVideoID"/>",
playerapiid: "<xsl:value-of select="concat('ytPlayerAPI-',$uTubeVideoID)" />",
allowFullScreen: "<xsl:value-of select="$allowFullScreenText"/>" }
var params = {allowScriptAccess: "always", wmode: "transparent",
allowFullScreen: "<xsl:value-of select="$allowFullScreenText"/>" };
var atts = { id: "<xsl:value-of select="concat('ytPlayerAPI-',$uTubeVideoID)" />" };
swfobject.embedSWF("http://www.youtube.com/v/<xsl:value-of
select="$uTubeVideoID" />?fs=<xsl:value-of
select="$allowFullScreen" /><xsl:value-of
select="$uTubeRel" />&enablejsapi=1&version=3&playerapiid=<xsl:value-of
select="concat('ytPlayerAPI-',$uTubeVideoID)" />","<xsl:value-of
select="concat('ytPlayerAPI-',$uTubeVideoID)" />", "<xsl:value-of
select="$uTubeWidth" />", "<xsl:value-of
select="$uTubeHeight"/>", "8", null, flashVars, params, atts);
</script>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<!-- Video Not Allowed to be embedded -->
<p>This video does not allow it to be embedded.</p>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Any questions, comments or
suggestions, feel free to leave a comment...
Enjoy!