Our approach with WordPress has always been to make it run on common server configurations. We want users to have flexibility when choosing a host for their precious content. Because of this strategy, WordPress runs pretty much anywhere. Web hosting platforms, however, change over time, and we occasionally are able to reevaluate some of the requirements for running WordPress. Now is one of those times. You probably guessed it from the title — we’re finally ready to announce the end of support for PHP 4 and MySQL 4!
First up, the announcement that developers really care about. WordPress 3.1, due in late 2010, will be the last version of WordPress to support PHP 4.
For WordPress 3.2, due in the first half of 2011, we will be raising the minimum required PHP version to 5.2. Why 5.2? Because that’s what the vast majority of WordPress users are using, and it offers substantial improvements over earlier PHP 5 releases. It is also the minimum PHP version that the Drupal and Joomla projects will be supporting in their next versions, both due out this year.
The numbers are now, finally, strongly in favor of this move. Only around 11 percent of WordPress installs are running on a PHP version below 5.2. Many of them are on hosts who support PHP 5.2 — users merely need to change a setting in their hosting control panel to activate it. We believe that percentage will only go down over the rest of the year as hosting providers realize that to support the newest versions of WordPress (or Drupal, or Joomla), they’re going to have to pull the trigger.
In less exciting news, we are also going to be dropping support for MySQL 4 after WordPress 3.1. Fewer than 6 percent of WordPress users are running MySQL 4. The new required MySQL version for WordPress 3.2 will be 5.0.15.
WordPress users will not be able to upgrade to WordPress 3.2 if their hosting environment does not meet these requirements (the built-in updater will prevent it). In order to determine which versions your host provides, we’ve created the Health Check plugin. You can download it manually, or use this handy plugin installation tool I whipped up. Right now, Health Check will only tell you if you’re ready for WordPress 3.2. In a future release it will provide all sorts of useful information about your server and your WordPress install, so hang on to it!
In summary: WordPress 3.1, due in late 2010, will be the last version of WordPress to support PHP 4 and MySQL 4. WordPress 3.2, due in the first half of 2011, will require PHP 5.2 or higher, and MySQL 5.0.15 or higher. Install the Health Check plugin to see if you’re ready!
Video presentations are a great addition to any product page. With a presentation you can showcase your product’s features without making the visitor read through long paragraphs of text. But apart from producing the video, you still need to manually convert it and find (or code) some sort of flash player that will display it on your site.
The other possible path is that you upload it to a video sharing site such as youtube, but you are going to have a rough time trying to incorporate the player into your design.
Luckily for us, YouTube does provide a solution to this problem – their chromeless player (a stripped down version of the regular embeddable player), which allow you to build and style your own custom controls. This way you have both a quick and secure way to include videos in your pages, and the freedom to customize any way you might want to.
The Idea
Today we are going to make a jQuery plugin which uses YouTube’s chromeless player, and creates our own set of minimalistic controls, which allows for perfect integration with your designs. The supported controls include a Play/Pause/Replay button, and a clickable progress bar.
The plugin is going to use YouTube’s gdata api to determine whether embedding has been allowed for the video, and fetch extensive information about it, such as title, description, tags, screenshots & more, which you can use to improve the plugin.
Using the plugin to embed videos is extremely easy:
// Embed a video into the #player div:
$('#player').youTubeEmbed('http://www.youtube.com/watch?v=u1zgFlCw8Aw');
// Chaining is also supported:
$('#player').youTubeEmbed('http://www.youtube.com/watch?v=u1zgFlCw8Aw');
.youTubeEmbed('http://www.youtube.com/watch?v=AsdfFdwlzdAw');
You can also specify a width for the embedded video (the height will be calculated automatically depending on the aspect ratio), and choose to disable the progress bar:
$('#player').youTubeEmbed({
video : 'http://www.youtube.com/watch?v=u1zgFlCw8Aw',
width : 600, // Height is calculated automatically
progressBar : false // Hide the progress bar
});
You can grab the plugin from the download button above, and start with the first step.
Step 1 – XHTML
Our plugin depends on jQuery SWFObject to embed the SWF files in the page. Below you can see the combined markup that is generated by both of the plugins.
youtube-player.html
<div class="flashContainer" style="width: 640px; height: 360px;">
<object height="360" width="640" id="video_26ELpS3Wc4Q" type="application/x-shockwave-flash"
data="http://www.youtube.com/apiplayer?enablejsapi=1&version=3">
<param value="always" name="allowScriptAccess">
<param value="transparent" name="wmode">
<param value="video_id=26ELpS3Wc4Q&playerapiid=26ELpS3Wc4Q"
name="flashvars">
<param value="http://www.youtube.com/apiplayer?enablejsapi=1&version=3"
name="movie">
</object>
<div class="controlDiv play"></div>
<div class="progressBar">
<div class="elapsed"></div>
</div>
</div>
The .flashContainerDiv is dynamically created by the plugin for each video on the page. It is populated with the embed code generated by SWFObject, the .controlDiv (which acts as a play/pause button) and the progress bar.
As mentioned above, the insertion of the player itself is handled by the SWFObject plugin. Depending on the browser, it can output either an object element, or a non-standard embed element for IE. This lifts the burden from us and allows us to concentrate on tasks such as querying YouTube’s APIs and building the player controls.
Custom YouTube Player
Step 2 – jQuery
The plugin’s code is located in the youTubeEmbed-jquery-1.0.js file. However, before being able to use it, you need to include the latest version of the jQuery library in the page, along with the jQuery SWFObject plugin and lastly script.js, which inserts two videos in the demonstration page and handles the submissions of the preview form.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="jquery.swfobject.1-1-1.min.js"></script>
<script src="youTubeEmbed/youTubeEmbed-jquery-1.0.js"></script>
<script src="script.js"></script>
Before we start digging into the player plugin’s code, lets take a look at a sample response from YouTube’s gdata api. It can give you a lot of useful information about a video, including duration, access control (both of which used by the plugin) and all sorts of additional data such as title, description, tags, screenshots and more.
Sample JSON response
{
"id": "u1zgFlCw8Aw",
"uploaded": "2008-03-05T01:22:17.000Z",
"updated": "2010-07-23T01:02:42.000Z",
"uploader": "GoogleDevelopers",
"category": "People",
"title": "The YouTube API: Upload, Player APIs and more!",
"description": "Listen to the YouTube APIs and Tools team talk about...",
"tags": ["youtube", "launch", "api", "engineering"],
"thumbnail": {
"sqDefault": "http://i.ytimg.com/vi/u1zgFlCw8Aw/default.jpg",
"hqDefault": "http://i.ytimg.com/vi/u1zgFlCw8Aw/hqdefault.jpg"
},
"player": {
"default": "http://www.youtube.com/watch?v=u1zgFlCw8Aw",
"mobile": "http://m.youtube.com/details?v=u1zgFlCw8Aw"
},
"content": {
"1": "rtsp://v4.cache5.c.youtube.com/CiILE..",
"5": "http://www.youtube.com/v/u1zgFlCw8Aw?f..",
"6": "rtsp://v3.cache4.c.youtube.com/CiILENy73.."
},
"duration": 259,
"location": "san bruno, ca",
"rating": 4.3,
"likeCount": "119",
"ratingCount": 144,
"viewCount": 251024,
"favoriteCount": 164,
"commentCount": 118,
"accessControl": {
"syndicate": "allowed",
"commentVote": "allowed",
"rate": "allowed",
"list": "allowed",
"comment": "allowed",
"embed": "allowed",
"videoRespond": "allowed"
}
}
All the fields of this response objects are available as properties in the data variable (data.fieldname). You could potentially modify the plugin to show the title with a link to the video page on youtube, or show the rating of the video.
Now lets dive directly into the script’s source code.
youTubeEmbed-jquery-1.0.js – Part 1
(function($){
$.fn.youTubeEmbed = function(settings){
// Settings can be either a URL string,
// or an object
if(typeof settings == 'string'){
settings = {'video' : settings}
}
// Default values
var def = {
width : 640,
progressBar : true
};
settings = $.extend(def,settings);
var elements = {
originalDIV : this, // The "this" of the plugin
container : null, // A container div, inserted by the plugin
control : null, // The control play/pause button
player : null, // The flash player
progress : null, // Progress bar
elapsed : null // The light blue elapsed bar
};
try{
settings.videoID = settings.video.match(/v=(\w+)/)[1];
// safeID is a stripped version of videoID,
// ready for use as a JavaScript function name
settings.safeID = settings.videoID.replace(/[^a-z0-9]/ig,'');
} catch (e){
// If the url was invalid, just return the "this"
return elements.originalDIV;
}
// Fetch data about the video from YouTube's API
var youtubeAPI = 'http://gdata.youtube.com/feeds/api/videos?v=2&alt=jsonc';
$.get(youtubeAPI,{'q':settings.videoID},function(response){
var data = response.data;
if(!data.totalItems || data.items[0].accessControl.embed!="allowed"){
// If the video was not found, or embedding is not allowed;
return elements.originalDIV;
}
// data holds API info about the video:
data = data.items[0];
settings.ratio = 3/4;
if(data.aspectRatio == "widescreen"){
settings.ratio = 9/16;
}
settings.height = Math.round(settings.width*settings.ratio);
We start by defining our script as a jQuery plugin by adding it as a function to the $.fn object. To make the code easier to follow and read, I put all the elements of the page, such as the control and the progressBar divs in a structure called elements.
After extracting the id of the video (a unique 11 character sequence after the ?v= parameter), we send a JSONP request to youtube’s gdata API. Depending on whether such a video exists, and on whether embedding is allowed on it, we proceed with calculating the aspect ratio. The height of the video is calculated by using this ratio and multiplying it to the width.
youTubeEmbed-jquery-1.0.js – Part 2
// Creating a container inside the original div, which will
// hold the object/embed code of the video
elements.container = $('<div>',{className:'flashContainer',css:{
width : settings.width,
height : settings.height
}}).appendTo(elements.originalDIV);
// Embedding the YouTube chromeless player
// and loading the video inside it:
elements.container.flash({
swf : 'http://www.youtube.com/apiplayer?enablejsapi=1&version=3',
id : 'video_'+settings.safeID,
height : settings.height,
width : settings.width,
allowScriptAccess:'always',
wmode : 'transparent',
flashvars : {
"video_id" : settings.videoID,
"playerapiid" : settings.safeID
}
});
// We use get, because we need the DOM element
// itself, and not a jquery object:
elements.player = elements.container.flash().get(0);
// Creating the control Div. It will act as a ply/pause button
elements.control = $('<div>',{className:'controlDiv play'})
.appendTo(elements.container);
// If the user wants to show the progress bar:
if(settings.progressBar){
elements.progress = $('<div>',{className:'progressBar'})
.appendTo(elements.container);
elements.elapsed = $('<div>',{className:'elapsed'})
.appendTo(elements.progress);
elements.progress.click(function(e){
// When a click occurs on the progress bar, seek to the
// appropriate moment of the video.
var ratio = (e.pageX-elements.progress.offset().left)/elements.progress.outerWidth();
elements.elapsed.width(ratio*100+'%');
elements.player.seekTo(Math.round(data.duration*ratio), true);
return false;
});
}
In the second part of the code, we use the SWFObject plugin to generate the embed code of the youtube chromeless player. Notice that the id of the video is passed as a flashvar so the player can load it directly. The safeID variable (a JavaScript safe version of the videoid) becomes the value of the id parameter of the to-be generated object element. This way we can later fetch the DOM element by running document.getElementById(‘video_’+settings.safeID) and get access to the methods which control the youtube player (play, pause etc).
youTubeEmbed-jquery-1.0.js – Part 3
var initialized = false;
// Creating a global event listening function for the video
// (required by YouTube's player API):
window['eventListener_'+settings.safeID] = function(status){
var interval;
if(status==-1) // video is loaded
{
if(!initialized)
{
// Listen for a click on the control button:
elements.control.click(function(){
if(!elements.container.hasClass('playing')){
// If the video is not currently playing, start it:
elements.control.removeClass('play replay').addClass('pause');
elements.container.addClass('playing');
elements.player.playVideo();
if(settings.progressBar){
interval = window.setInterval(function(){
elements.elapsed.width(
((elements.player.getCurrentTime()/data.duration)*100)+'%'
);
},1000);
}
} else {
// If the video is currently playing, pause it:
elements.control.removeClass('pause').addClass('play');
elements.container.removeClass('playing');
elements.player.pauseVideo();
if(settings.progressBar){
window.clearInterval(interval);
}
}
});
initialized = true;
}
else{
// This will happen if the user has clicked on the
// YouTube logo and has been redirected to youtube.com
if(elements.container.hasClass('playing'))
{
elements.control.click();
}
}
}
In order to be able to control the video player, we need to be notified when certain events (like playback stopped, video ready etc) occur. Normally, this would mean that we need to pass a callback function, which is executed by the player every time such an event happens.
Unfortunately, flash can only execute functions if they are defined in the global scope and cannot see the functions which are defined inside the plugin. However, by creating functions with unique names (with the safeID) and explicitly adding them to the window object we can make this happen. If it weren’t for this little trick, it would be impossible for the plugin to work.
youTubeEmbed-jquery-1.0.js – Part 4
if(status==0){ // video has ended
elements.control.removeClass('pause').addClass('replay');
elements.container.removeClass('playing');
}
}
// This global function is called when the player is loaded.
// It is shared by all the videos on the page:
if(!window.onYouTubePlayerReady)
{
window.onYouTubePlayerReady = function(playerID){
document.getElementById('video_'+playerID).addEventListener('onStateChange','eventListener_'+playerID);
}
}
},'jsonp');
return elements.originalDIV;
}
})(jQuery);
The event listening function we created in the previous section of the code, is attached to the player with the addEventListener method. It is called every time when a “stateChange” occurs (playback start, playback pause, end of playback etc). A numeric code is passed to the event listening function as a parameter, corresponding to the event.
Now lets take a look at how our plugin is used.
script.js
$(document).ready(function(){
$('#player').youTubeEmbed('http://www.youtube.com/watch?v=u1zgFlCw8Aw');
/*
//You can alternatively pass an object:
$('#player').youTubeEmbed({
video : 'http://www.youtube.com/watch?v=u1zgFlCw8Aw',
width : 600, // Height is calculated automatically
progressBar : false // Hide the progress bar
});
*/
});
You just need to call the youTubeEmbed() method and pass it either a string or a configuration object. If a string is passed, it is assumed to be the URL of a YouTube video. If you are passing an object make sure that you are passing the video property with a correct video URL.
Video Playing with a Progress Bar
Step 3 – CSS
Finally we are left with applying a few CSS styles to the player. They will change the design of the player controls and define the way they are positioned in the player window.
youTubeEmbed-jquery-1.0.css
.flashContainer{
/* Setting the container to relative positioning
so we can center the control div */
position:relative;
overflow:hidden;
}
.progressBar{
display:none;
position:absolute;
width:auto;
height:8px;
left:20px;
right:105px;
bottom:20px;
background-color:#141414;
overflow:hidden;
cursor:pointer;
/* A light CSS3 bottom highlight */
-moz-box-shadow:0 1px 0 rgba(255, 255, 255, 0.3);
-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, 0.3);
box-shadow:0 1px 0 rgba(255, 255, 255, 0.3);
}
.progressBar .elapsed{
position:absolute;
width:0;
height:100%;
background-color:#1fa2f6;
border-right:1px solid #49AFF0;
}
.controlDiv{
/* Centering the control div */
position:absolute;
width:120px;
height:120px;
cursor:pointer;
top:50%;
left:50%;
margin:-60px 0 0 -60px;
}
.controlDiv.play{
background:url('img/play.png') no-repeat center center;
}
.controlDiv.replay{
background:url('img/replay.png') no-repeat center center;
}
.controlDiv.pause{
background:url('img/pause.png') no-repeat -99999px;
}
.flashContainer:hover .controlDiv.pause{
background-position:center center;
}
/* Only show the progress bar when the video is playing */
.flashContainer.playing:hover .progressBar{
display:block;
}
To customize the look of the player you just need to change the color values above. Also you can edit the png files with the play/pause buttons. Clearly this is much easier than modifying the looks of the default youtube player. It also strips all of the unnecessary chrome and leaves you with what matters most – your video.
With this our Custom YouTube Player plugin is complete!
Did you like this tutorial? Share your thoughts in the comment section below.