No-hassle IE movie embedding

Due to a lawsuit by Eolas against Microsoft, Internet Explorer (both 6 and 7) is not allowed to auto-load movies, flash, and other plugins. The effect is that users must click an empty area with a gray outline to load the content or start interacting with it. The standard approach to route around this usability fiasco is to dynamically load the <object> and <embed> tags with javascript. Here I present an easier, more readable, and unobtrusive technique for embedding content in IE6 and IE7.

Problems with existing techniques

Current techniques generally involve an external script that is called from an inline javascript block, as well as a <noscript> element with the same content as a fallback.

  • Duplicating your embed code is a bad practice. Sooner or later, one copy will get changed and the other won't.
  • When Quicktime movies are dynamically injected during page load in IE, the DOM-ready event will not occur until the movie is fully loaded. As a result, other components of the page which rely on javascript enhancements will not work for many seconds (or even minutes.)
  • Placing markup code into procedural code is another bad practice.

A solution should have one source for the markup, should load on DOM-ready and not during page load, and should not rely on page-specific javascript.

Use the <noscript> you already have

That <noscript> you have in your HTML is all you need. With some unobtrusive scripting, you can duplicate its contents and place the embed code just outside. Add an appropriate class name to it as a hook for an external script. Here's the HTML:

<div style="width: 502px; height: 321px;" class="ac-surround">
<!--[if IE]><noscript class="active-content-embed-v2"><![endif]-->
	<object data="/path/to/FlashPlayer.swf" type="application/x-shockwave-flash" width="502" height="321" class="W3C">
		<param name="wmode" value="transparent" />
		<param name="FlashVars" value="all&your&flash&variables" />

		<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="502" height="321" class="IE" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0">
			<param name="movie" value="/path/to/FlashPlayer.swf" />
			<param name="wmode" value="transparent" />
			<param name="FlashVars" value="all&your&flash&variables" />

			You appear to not have Adobe Flashplayer installed.

		</object>
	</object>
<!--[if IE]></noscript><![endif]-->
</div><!-- /.ac-surround -->

And here's the script, which relies on jQuery:

var re_ac_objects_start = /^.+<object.+<object/;
var re_ac_objects_end = /<\/object>.*<\/object>.+$/;
var re_unfriendly_whitespace = /[\r\n\t\v\f]/g;
var re_trimmable_whitespace = /^\s+|\s+$/g;

function lateLoadActiveContentV2(i)
{
	var newContent = this.innerHTML;

	if(newContent.indexOf('[if IE]') !== -1) // for IE6, since IE7 strips the outer object
	{
		newContent = newContent.replace(re_unfriendly_whitespace, ' ') // newlines wreak havoc with regexes
		                       .replace(re_ac_objects_start, '<object')
		                       .replace(re_ac_objects_end, '</object>');
	}
	else // others should at least trim the string
	{
		newContent = newContent.replace(re_trimmable_whitespace, ''); // trim
	}

	$(this).before(newContent).remove();
}


// Standard "run when DOM is ready" code that relies on jQuery
$(function(){
	$('noscript.active-content-embed-v2').each(lateLoadActiveContentV2);
});

I implemented this at work, and it works fine.

Update: Since Safari does not provide access to the contents of a noscript element, I had to add conditional comments around both of the noscript tags. That in turn prompted a change to the javascript (cutting out the conditional comments from the noscript's innerHTML), and while I was in there I took out the now unnecessary Firefox compatibility code.


Responses: One so far

  1. m.wittman says:

    Just wanted to say a huge THANKS for this jquery-javascript-noscript solution to my embed a quicktime movie without the IE click to activate madness!

    I've tried a number of complex jquery-oriented media wrangling approaches which never panned out. Your approach just clicked in my brain (hey, that's part of your domain namesake - ~interesting~) and it was straight forward to implement.

    Anyway, I thought I'd take a moment and comment my appreciation.