Embedding Flash accessibly
author: mike foskett uploaded: 15th September 2008
updated: 5th October 2008
A simple, unobtrusive, and lightweight method to embed Flash accessibly into your page. Content in the HTML is replaced with a Flash inset only if both JavaScript and the minimum level of Flash are supported. Multiple Flash insets are also catered for. The method depicted here is currently in use by Tesco Direct to deliver their TV adverts online.
Example
Here's the same example running on a bare bones demo page. There's a zipped complete set of the files and just the JavaScript used. The zipped set includes minified versions. The smallest of which is only 1.33 KB.
There are many advantages to this solution:
- The simplest of installation set-ups.
- Tests for the users Flash version, and only inserts if supported.
- Unobtrusive. No extra mark-up in the (X)HTML.
- Accessible with or with out JavaScript.
- Semantic W3C formal grammar, validates even after the Flash is embedded.
- Accessible, with or with out Flash.
- Very small footprint (1.33 KB).
- Multiple Flash insets per page.
- A cross-browser, cross-platform solution. Still in testing though.
Caveat: It will not make a Flash piece accessible in itself.
How to implement
All that is required is a link to the script and a contained image in the html:
<script type="text/javascript">flash_embed.js</script>
<div>
<img id="example" class="img2swf" src="example.jpg" width-"160" height="160" title="" alt="alt text here" />
</div>
Ensure the image id is unique on the page and it has a class name of img2swf.
The image and swf must be in the same location. They must also share the same name but with different extensions.
Place the script last in the <head> or last inside the<body> sections.
How it works
Once the page has loaded the script looks through all the images on the page and makes a list of those with a class name of img2swf.
For each one it then fetches the swf file and replaces the content of the image container. The <div> in the example.
Coding specifics
In the (X)HTML
Place a holding image which displays when Flash or JavaScript is unavailable. The image must have a unique id and a class of img2swf:
<div>
<img id="example" class="img2swf" src="example.jpg" width-"160" height="160" title="" alt="alt text here" />
</div>
Multiple images for replacement are allowed just ensure the id is different for each and they share the class name.
The JavaScript
Set the global variables
var minFlash=7;
var imgClass="img2swf";
MinFlash is the minimum version of Flash needed to run.
Use an onload mechanism to ensure the page has loaded before trying to replace the images. I use Simon Willisons onload handler:
function addLoadEvent(func){
var oldonload=window.onload;
if(typeof window.onload!='function')
window.onload=func
else
window.onload=function(){
oldonload();
func()
}
}
A neat little function to find the Flash version supported on the browser. This originally was part of a much larger script which has been stripped down to the bare essentials. I've lost the reference for the original, if anyone has a clue please contact me. The function does not detect Flash on all systems but if it can't detect it leaves the accessible alternative.
function isFlash(v){
var testTo=20, installed=0;
if(navigator.plugins && navigator.plugins.length){
for(var x=0;x<navigator.plugins.length;x++){
if(navigator.plugins[x].name.indexOf('Shockwave Flash')!=-1){
installed=parseInt(navigator.plugins[x].description.split('Shockwave Flash ')[1]);
break;
} } }
else if(window.ActiveXObject){
for(var x=2;x<=testTo;x++){
try{if(eval("new ActiveXObject('ShockwaveFlash.ShockwaveFlash."+x+"');"))installed=x}
catch(e){}
} }
return((installed>=v)?installed:0)
}
The work horse:
function flashInset(id){
if (isFlash(minFlash) && document.getElementById(id)){
var obj=document.getElementById(id);
if (obj.src){
/* Get the image properties */
var src=obj.src;
var width=obj.width;
var height=obj.height;
var altText=obj.alt;
var parent=obj.parentNode;
/* Replace the image src extension with swf */
var src=src.substring(0,src.lastIndexOf("."))+".swf";
/* If img in a link then go up a parent level */
if (parent.href) parent=parent.parentNode;
The build for the inset code uses Ian Hicksons object method which is simple, effective and does away with the <embed> tag.
/* Check required properties are available */
if (src && parent && width && height){
/* Build the Flash object */
var str='';
str+='<object id="'+id+'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version='+minFlash+',0,0,0" width="'+width+'" height="'+height+'">';
str+='<param name="movie" value="'+src+'" />';
str+='<param name="quality" value="high" />';
str+='<param name="bgcolor" value="#ffffff" />';
str+='<!--[if !IE]> <-->';
str+='<object data="'+src+'" width="'+width+'" height="'+height+'" type="application/x-shockwave-flash">';
str+='<param name="quality" value="high" />';
str+='<param name="bgcolor" value="#ffffff" />';
str+='</object>';
str+='<!--><p>'+altText+'</p><![endif]-->';
str+='</object>';
/* Replace the images parent with the built object */
parent.innerHTML=str;
}
}
}
}
Okay so I used innerHTML. It's smaller, faster and fully supported by all browsers.
One parameter that may be required if you use pop-up menus to overlay any part of the object is wmode which may be set to opaque or transparent.
str+=<param name="wmode" value="transparent">
Add it twice, once before each bgcolour parameter.
Set up. Find each image with the class img2swf and add it's id to an array. Then use the array to call the flashInset function.
function setup(){
var imgs=document.getElementsByTagName('img')
var imgIDs=new Array();
for (var i=0;i<imgs.length;i++){
if ((imgs[i].className==imgClass)){
imgIDs[i]=imgs[i].id;
}
}
for (var i=0;i<imgIDs.length;i++){
flashInset(imgIDs[i]);
}
}
addLoadEvent(setup);
Embedding Flash directly without JavaScipt support
author: david grudl uploaded: 5th October 2008
Not recommended but added to supply a complete picture of the alternatives.
If the Flash must be made available, even when JavaScript isn't, then maybe the following technique may be employed:
// author: David Grudl - http://latrine.dgx.cz/how-to-correctly-insert-a-flash-into-xhtml
<!--[if !IE]> -->
<object type="application/x-shockwave-flash" data="movie.swf" width="300" height="135">
<!-- <![endif]-->
<!--[if IE]>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="300" height="135">
<param name="movie" value="movie.swf" />
<!--><!-- -->
<param name="loop" value="true" />
<param name="menu" value="false" />
<p>This is <b>alternative</b> content.</p>
</object>
<!-- <![endif]-->
The solution doesn't get past the Eolas issue in IE, where you have to click to activate the Flash object, but adding the following script will sort that:
var obj=document.getElementsByTagName("object");
for(var i=0;i<obj.length;i++){
if(obj.type!="application/x-shockwave-flash"){
obj[i].outerHTML=obj[i].outerHTML;
}
}
if(!obj.type){obj[i].outerHTML=obj[i].outerHTML;}
A bare-bones no-javascript reliance demo. For more info please see the original article: How to correctly insert a Flash into XHTML with a byline of without reliance upon JavaScript.
The Flash object will appear under the maximum number of conditions, even without JavaScript support. but please be aware that systems that do not support JavaScript are also unlikely to support current versions of Flash.
Personally speaking I prefer the JavaScript replacement technique where if the ideal conditions are not met then supply alternatives. But it's up to you and the specific case in which your involved.
Audio, video and photo galleries
I use a similar method to embed audio players, photo galleries and video. A few more details are required though.
This article continues with Embedding Flash video
Further reading
- A List Apart article: Flash Embedding Cage Match by Bobby van der Sluis
- Perishable Press article: Embed Flash or Die Trying by Jeff Starr
- A List Apart article: Bye Bye Embed by Elizabeth Castro
- The fully featured swfObject Flash object embed method
- Object Paranoia by Gez Lemon