Tuesday, 1 December 2009

Trying to get youtube videos/flash working in Wordpress posts

This morning I was doing some more work on my photo website.

First of all I wanted to test my theory about the problem with my slideshow javascript causing a stack overflow in IE, i.e. that the image onload function would fire it's parent function, which would then cause the image onload function to be run again, and so on, until all the images had loaded. This caused a build-up of functions running within functions until all the images had loaded, when the functions could return/exit. It's a bit hard to explain, but if you look at the code below, hopefully you can see the problem:
//function to load an image into cache
"loadImage" : function(i, data){

//Don't load the image if it's already loading
if(this.currentlyLoading === i)
{return;}

var img = new Image();
this.currentlyLoading = i;
img.onload = function(jj, i){
return function(){
//Store this image in the loaded images array
jj.images[i] = this;

//Delete it from the imagesToLoad array
delete jj.imagesToLoad[i];

//Load the next image
for(i in jj.imagesToLoad)
{
if(jj.imagesToLoad.hasOwnProperty(i)){
//This is the problem here - we're calling the same function
//that caused this function to run, and since this function won't
//return/exit until the below function has returned/exited,
//we have to wait until the last image is loaded, after which
//the functions will return in reverse order to the order they
//were called in
function(){jj.loadImage(i, jj.imagesToLoad[i]);
break;
}
}
}
}(this, i);
$(img).addClass('slideShowImg')
.css({"opacity" : 0})
.attr("alt", data.Headline)
.appendTo('#slideShowContainer');
img.src = STATIC2+'/Img/smallWebSize/'+data.filename;
alert(i);
},

So to test my theory, you can see I alerted the value of i at the bottom of the function. And in keeping with my theory, the values of i were alerted in the order from most to least, showing that the functions didn't start exit until the last image had been loaded, thus returning/exiting, so the 2nd to last function could return/exit, then the 3rd to last, etc. etc.

To fix this, I wrapped the call to load the image in a timeout, so this meant that the function could now finish, and the function to load the next image would be called separately:
//New
setTimeout(function(jj, i){ return function(){jj.loadImage(i, jj.imagesToLoad[i]);};}(jj, i), 25);
//Old
jj.loadImage(i, jj.imagesToLoad[i]);


After making this change, the page now worked fine in IE8, but when I tried it in IE6, I got a load of errors about data.Headline not being defined. I refreshed the page in case it was a cache problem, but still got the same problem.

So I fired up Visual Web Developer Express Edition, and started a debug session, then put some break points in the page to try and see where the data was getting lost. However, when I was checking the values of various variables, and stepping through the script manually, I didn't get any errors. I ran the page again without the break points, and now it worked fine. I guess that's IE for you.

I fixed some CSS problems with the blog in IE6, then noticed that the youtube video was just white (instead of the video). I figured this was probably something to do with using an XSL Stylesheet to produce the HTML for IE, and maybe invalid markup for embedding the video. I remembered that there was a problem with embedding Flash into XHTML pages, so I did some googling and came across How to correctly insert a Flash into XHTML. In the comments, there is also a link to a similar solution by Ian Hickson: Embedding flash without <embed>

After lunch I looked into implementing the correct XHTML compatible flash embedding code, but had quite a few problems.

The first was that HTML comments <!-- --> were being converted into &lt;!-- --&gt;. After lots of messing about, I eventually worked out that the Wordpress X-Valid plugin was causing this. To stop this behaviour, I had to comment out line 90 in xvalid.php
//add_filter('content_save_pre', array(&$this, 'filter_post'), 8);
I did try stopping this behaviour by adding
remove_filter('content_save_pre', array($xvalidator, 'filter_post'));
to my Theme's functions.php file (and also tried with the '8' as a third parameter), but this didn't seem to work - only commenting out the line in the actual plugin file would stop it from entity encoding HTML comments.

The second problem was that Wordpress was inserting an <object> into the code, thus breaking it. I fixed this by turning off 'WordPress should correct invalidly nested XHTML automatically' (Settings > Writing).

The third problem was that Wordpress was inserting <br/>s inside the object element where I had set the attributes of the object separated by line breaks. Also, Wordpress would sometimes insert <p> tags surrounding block level elements like divs, or sometimes insert an opening <p> tag in a random place. To fix this I had to add
remove_filter('the_content', 'wpautop');
to my functions.php file.

The fourth problem was that Wordpress was converting the -- bit of part of a conditional comment into a &#8212; em-dash entity. To fix this I had to add
remove_filter('the_content', 'wptexturize');
to my functions.php file.

After doing all that I finally had flash working in my Wordpress post.

I wrote most of this blog post, and then took Grandad on a walk round the block. Although it had been frosty this morning, there was virtually no wind, and so it was actually a lot warmer than it has been lately.

While I had got flash working on my Wordpress post, I hadn't actually changed it to display my youtube video, it was currently displaying a test flash animation from How to insert a Flash movie in (X)HTML valid way Example. But when I changed the parameters and attributes to the correct ones for my youtube video, I found that while it would work in most browsers, in IE6 and 8 (worked okay in IE7), I was just getting the white screen again instead of the video.

So I put back the code for embedding flash to how it was originally, and then changed the parameters one by one until it broke in IE. I found that it didn't break until I changed the video url to point at the youtube video.

After some thinking, I realised that probably the problem was that Youtube requires a higher flash version than was installed on the IE6 and IE8 virtual machines. This would also explain why it worked okay in IE7, since I run that from my main Vista installation rather than an XP Virtual Machine. To test this, I went on Youtube on one of IE Virtual machines, and I got a message saying that I needed javascript enabled or to upgrade my flash plugin.

So I knew that I needed to set a higher minimum Flash version to be required, but I wasn't sure how to do this. I could see that the IE <object> had an attribute like
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"
But I wasn't sure what version of Flash youtube requires and also what the codebase url should be for later versions of Flash.

After doing some googling I found that apparently youtube requires Flash 8, and I tried just changing the end of the codebase url to 8,0,0,0. Now on the IE virtual machines I would get a prompt to install the latest version of Flash. I found that when I clicked to cancel the install, the ending part of the conditional comment for IE was shown on the page. This was because I had changed the comment structure from the code on How to correctly insert a Flash into XHTML. Changing the code back to what was suggested there fixed the problem with the end tag of the IE Conditional Comment being shown when the installed version of flash doesn't meet the minimum requirements and the user chooses not to install the latest version.

I also tried out the Smart Youtube plugin for Wordpress. This inserts the youtube video using valid XHTML, however in my IE virtual machines, it wasn't prompting me to upgrade Flash, and just had an empty box.

I checked my email, then was wondering that since IE uses the codebase attribute to tell what version of Flash is required, how do Firefox et al know what version of Flash is needed? Doing some more Googling, I cam across a comparison of various different ways to embed a Flash youtube video in a page. Looking at the different methods shown there, it seems the answer is that Firefox etc. can't tell what version of Flash is needed. There is a pluginurl parameter for firefox, but it doesn't contain the version number in the url.

Next I modified the smartYouTube Wordpress plugin to use the embed code format from How to correctly insert a Flash into XHTML. I commented out line 523 of smartyoutube.php, and then added in the new code:
   if ($valid=="off")

$yte_tag = '<!-- Smart Youtube --><span class="youtube"><object width="'.$width.'" height="'.$height.'"><param name="movie" value="'.htmlspecialchars('http://www.youtube.com/v/'.$file.'&rel='.$disp_rel.'&color1='.$CustomColors[$disp_color][0].'&color2='.$CustomColors[$disp_color][1].'&border='.$disp_border.'&fs=1&hl=en&autoplay='.$autoplay.$disp_info.$disp_ann.'&showsearch='.$disp_search, ENT_QUOTES).$high.$time.'" /><param name="allowFullScreen" value="true" /><embed wmode="transparent" src="'.htmlspecialchars('http://www.youtube.com/v/'.$file.'&rel='.$disp_rel.'&color1='.$CustomColors[$disp_color][0].'&color2='.$CustomColors[$disp_color][1].'&border='.$disp_border.'&fs=1&hl=en&autoplay='.$autoplay.$disp_info.$disp_ann.'&showsearch='.$disp_search, ENT_QUOTES).$high.$time.'" type="application/x-shockwave-flash" allowfullscreen="true" width="'.$width.'" height="'.$height.'" ></embed><param name="wmode" value="transparent" /></object></span>';

else{

//$yte_tag = '<!-- Smart Youtube --><span class="youtube"><object type="application/x-shockwave-flash" width="'.$width.'" height="'.$height.'" data="'.htmlspecialchars('http://www.youtube.com/v/'.$file.'&rel='.$disp_rel.'&color1='.$CustomColors[$disp_color][0].'&color2='.$CustomColors[$disp_color][1].'&border='.$disp_border.'&fs=1&hl=en&autoplay='.$autoplay.$disp_info.$disp_ann.'&showsearch='.$disp_search, ENT_QUOTES).$high.$time.'"><param name="movie" value="'.htmlspecialchars('http://www.youtube.com/v/'.$file.'&rel='.$disp_rel.'&color1='.$CustomColors[$disp_color][0].'&color2='.$CustomColors[$disp_color][1].'&border='.$disp_border.'&fs=1&hl=en&autoplay='.$autoplay.$disp_info.$disp_ann.'&showsearch='.$disp_search, ENT_QUOTES).$high.$time.'" /><param name="allowFullScreen" value="true" /><param name="wmode" value="transparent" /></object></span>';

$movieURL = htmlspecialchars('http://www.youtube.com/v/'.$file.'&rel='.$disp_rel.'&color1='.$CustomColors[$disp_color][0].'&color2='.$CustomColors[$disp_color][1].'&border='.$disp_border.'&fs=1&hl=en&autoplay='.$autoplay.$disp_info.$disp_ann.'&showsearch='.$disp_search, ENT_QUOTES).$high.$time;

$yte_tag = '

<!-- Smart Youtube -->

<span class="youtube">

<!--[if !IE]> -->

<object type="application/x-shockwave-flash" data="'.$movieURL.'" width="'.$width.'" height="'.$height.'">

<!-- <![endif]-->

<!--[if IE]>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"

codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0"

width="'.$width.'" height="'.$height.'">

<param name="movie" value="'.$movieURL.'" />

<!--><!--dgx-->

<param name="allowFullScreen" value="true" />

<param name="allowscriptaccess" value="always" />

<param name="pluginURL" value="http://get.adobe.com/flashplayer/" />

<param name="wmode" value="transparent" />

<p>You need the <a href="http://get.adobe.com/flashplayer/">Adobe Flash Player plugin</a> installed to view this video.</p>

</object>

<!-- <![endif]-->

</span>';

}
After doing that I found that when I put a video in fullscreen mode on either of the IE Virtual Machines, the video wouldn't play. I checked Youtube.com, and the videos on the actual youtube site had the same problem.

Doing some googling I found YouTube Won't Work in Full Screen, which explains how to fix it - you right click on the flash video, choose 'Settings', then untick 'Enable hardware acceleration' on the first tab. Unfortunately, as this is a client side issue, there's not a lot you can do to fix it from the website end (as far as I'm aware), other than displaying a message saying how if the video doesn't play full screen, here's how to fix it.

After dinner I played on New Super Mario Bros Wii with Moccle and L a bit, then did some more work on my photo site blog. First I found my search page page was a 404. After fixing that, I found the format of the page wasn't in keeping with the rest of the blog. After fixing that, I found that it wasn't actually displaying the excerpt of the post in the search results. I did quite a bit of googling to try and find why it wasn't showing the real excerpt, but rather some excerpt it had created itself, but couldn't find anything.

Then I tried putting the_excerpt() into the page to see what that would give (I was previously using a filtered version of get_the_excerpt(), and I found that the_excerpt() was printing the same excerpt (i.e. not the actual excerpt saved with the post), but it was highlighting the search term in bold. So obviously it was the search plugin that was creating this excerpt. Now I could see the search term highlighted in bold (it wasn't using my filtered version of get_the_excerpt(), it made sense. So I changed the page to use the_excerpt().

I tested my raphael js page in Konqueror with the non-minified version of raphael, and found that why it didn't work with Konqueror was because Raphael couldn't tell that Konqueror supported svg, so it assumed that it supported VML instead. Doing some googling to see how to check if a browser supports SVG. Unfortunately, the suggested methods I found were what Raphael already used, so it seems there isn't a way of detecting that Konqueror supports SVG.

The weather today was nice and sunny all day, and we also had our first frost of this Autumn/Winter this morning. At sunset the sun started setting behind hazy cloud, but when it got near the horizon the cloud was quite thick, so there wasn't a visible sunset. In the evening it rained.

Food
Breakfast: Grapefruit marmalade toast sandwich; mug of honey & lemon drink.
Lunch: Grated mature cheddar cheese sandwich; a couple of cherry plum tomatoes; clementine; slice of home-made flapjack; cup o' tea.
Dinner: Toad in the hole; mustard; gravy; green beans; potato; Cauliflower. Pudding was 2x home-made mince pies with cream. Coffee.

No comments: