Web standards compliant Javascript Flash detect and embed

FlashObject now has a permanant home at this url: http://blog.deconcept.com/flashobject/.

This post is partially out of date, and has been superceeded by Proper Flash embedding: FlashObject Best Practices. I’ve also closed the comments, please leave feedback in the new post.

Nearly every project I work on these days has Macromedia Flash involved with it some way or another. If you’re into the whole web nerd thing, you’ll know that embedding Flash in a XHTML page doesn’t play so nice with these web standards everyone is raving about. Developers basically have two choices these days when working with XHTML and Flash:

  1. The Flash Satay method, which uses a single object tag to embed the Flash movie. This method’s main drawback is that the movie won’t start playing until it is 100% loaded. This can create problems with large Flash sites where the user would be left with a blank screen until the movie loads. There are ways around this, but it involves using another swf file that loads your main movie and placing the preloader inside the first swf. This can clutter up your directories with ‘holder’ movies and make adding Flash content much more time consuming than it should be.
  2. Use Javascript to write the object / embed tags – This seems to be the most common way of embedding Flash today. Drawbacks include reliance on Javascript being enabled on the user’s browser, and having to include a .js file with each Flash movie, or rewrite the object and embed code for each movie.

With these in mind, I decided to come up with a standard way to embed my Flash movies, whether it be a single movie on a page (full Flash site) or multiple inline Flash elements on a larger XHTML page.

The features I wanted are:

  • Ability to embed unmodified Flash movies without the aid of other Flash movies
  • Ability to detect the Flash player version in the user’s browser and display alternate content if needed
  • Alternate content options – plain text (HTML), redirect, or image
  • Must validate as XHTML 1.0 transitional and up
  • Must accommodate any type of Flash embedding, including additional parameters and variables passed in via the Flashvars parameter
  • Easy to use (even non-technical designers should be able to use it!)
  • Must be able to be bypassed. What if the user has Flash but the detect failed for some unknown reason? (new browsers, unexpected plugin architectures, etc.)

With all this in mind, I started to look around for what other people have already come up with. Most large sites I looked at used simple Javascript to write each Flash movie to the page, or some reusable code that accepted parameters for the Flash movies. ABC News had the most advanced version I could find, with some excellent reusable Javascript that detected the plugin and could not only write the object and embed to the page, but could also target an element on the page and place the Flash movie inside it.

The ABC News code to write a Flash movie to the page looks like this:

var logo = new Flash("/flash/abcnewslogo.swf", 64, 64, 6);
logo.setParam("wmode", "transparent");
logo.render('logocontainer');

To view their Flash embed code, look here.

This isn’t bad at all, but it’s missing a few of my requirements: No way to specify alternate content if the user doesn’t have Flash (and no non-Flash site redirect option), and there’s no way to bypass it – if someone has some new unknown browser with a Flash plugin, and this script can’t find their plugin, there is no way they will get to see your Flash content.

So. Using this code as a base (except for the plugin detect, which I already had a copy I pieced together a while back and was basically the same thing anyway) I put together a new version with everything that I needed.

Here is what a basic Flash embed would look like:

var flashDial = new FlashObject("xm_dial.swf", "xmdial", 527, 349, 6, "#ABAFAE");
flashDial.write();

You can also target a specific element to place the Flash movie in by passing an element id in the write() method, like this:

myFlash.write('mydiv');

And here is a sample of what it would look like if you placed the code on the page and included alternate content and a few other optional parameters:

myFlash = new FlashObject("swffile.swf", "swffile", 500, 300, 6);
myFlash.altTxt = "<h1>You need to upgrade your Flash Player!</h1>";
myFlash.addParam("wmode", "transparent");
myFlash.addParam("salign", "top");
myFlash.addVariable("varname", "varvalue");
myFlash.write();

And that’s it! If you need to overwrite a default parameter, like quality, you would just set the parameter:

myFlash.addParam('quality', 'low');

If the user has Flash, they see the Flash movie. If they don’t, they will see your alternate text and a link to disable the Flash detect. This is done by simple adding detectflash=false to the query string (the link is added to the alternate text automatically unless you overwrite it).

Here is a sample page with a little Flash movie. Try uninstalling your Flash plugin and viewing the page.

I’ve also made a Flash template for this (included in the .zip file), so you can publish the javascript code you need directly from Flash – it’s not perfect, and only provides the very basic embed code, but it’s a nice starting point.

Download the FlashObject source code. Check out the updated version for the latest code downloads.

UPDATE (10-15-2004): Mark Wubben pointed out that there were couple loose variables hanging around, so I fixed that up. I decided to leave the getFlashVersion() function out in the open so it can be used independantly. Maybe you would want to use it to provide a general help statement without embedding a Flash movie?

UPDATE (10-20-2004): Just a small update, I removed the codebase variable since it will never be used by the browser. The only reason it’s in there is to give the browser a URI to download the plugin from, but since the Javascript won’t write the plugin code if they don’t have the plugin, it will never be used.

UPDATE (10-20-2004): I just posted a little follow up to the whole application/xhtml+xml mime types problem.

UPDATE (11-11-2004): Martin Klasson wrote and told me about how escape() tends to munge up some characters like ø and ä to name a couple. So I took it out, and switched the example page to utf-8 (because it should have been anyway). You’ll just have to watch out for things like double quotes being passed in through flashvars, but ideally you wouldn’t be doing that anyway, right?

UPDATE (11-13-2004): Just found a bug in the getQueryParamValue() function and fixed it. I should also note that you can use that function to grab URL parameters and send them to your Flash movie, so I added a little note in the usage comments on how to do that.

UPDATE (11-15-2004): Fixed a small bug pointed out by Manoloweb where the alt text would be written in the script tag instead of the target div if you specify a target. All fixed up now.

110 thoughts on “Web standards compliant Javascript Flash detect and embed

  1. Pingback: the daily div » Embedding Flash and Web Standards

  2. Pingback: artERNATIVO » Flash estándar

  3. Pingback: ResourceBlog » Standards-compliant JavaScript Flash Detection

  4. Pingback: marcelfahle.com » WEB STANDARDS KONFORME EINBINDUNG VON FLASH

  5. Pingback: rhm.blogalicious » Cool Stuff…

  6. Pingback: Alex Jones » Standards Compliant Flash Detection and Embedding [No, not that Alex Jones... Really, I'm not the Alex Jones you think I am.]

  7. Pingback: jerhome, le blog sur la personnalisation, le web design, les mmorpg, les outils et autres balivernes

  8. Pingback: Weblog Tools Collection » Flash Embed - WordPress Plugin

  9. Hey Geoff,

    Nice work. The funny thing is that you use object only for IE, while for sIFR I had to use object for Opera and embed for all other browsers. But perhaps that’s because I wasn’t using innerHTML. The downside of innerHTML is that it won’t work in XML documents.

    The JavaScript is quite nice. You could make global methods such as detectFlash static methods of the FlashObject class. That would reduce the “polution” of the global scope (window object). In the getFlashVersion method you are using x and y variables without declaring them. This means they are declared in the global scope and could potentially affect other programs.

    Regards,

  10. Pingback: Diseorama

  11. I am loving the script. So far, however, I cannot get my own defined alt text to appear when Flash is disabled.
    Have you actually gotten this to work?

  12. Hah… that was it. I’m telling you, this is great.
    I am using this on a site that will launch within then next couple of weeks.
    I like the flexibility this offers. A note to anyone interested: The “bypassTxt” can be bypassed by declaring an empty variable for it on your page… ex. homeflash.bypassTxt = “”;
    Thanks for the great code, Geoff… if I notice any changes we make to the code, I’ll let you know.

  13. Pingback: JD on MX

  14. Thank you very much! I was looking for as script like yours for a very long time. The script is simple but … awsome! THANX

  15. Hi, i don’t know if I’m missing something but on the sample page I see no Flash movie, just a gray box. I’m on a Mac OSX 10.3, used Firefox and Safari. I don’t usually have problems viewing Flash with either browser.

    Anyone else having that problem?

  16. Dave,

    The test movie I was using was just a plain grey box – I just replaced it with a Flash movie that actually has something in it.

  17. dusoft,
    Can you pass all the parameters such as wmode, quality, flashvars, and all the others and have them work on all the browsers as well?

    Also, using that method I believe if someone had Flash 6 and was trying to view a Flash 7 movie, the browser would try to display it anyway, possibly causing some strange looking Flash movies.

    And last, I prefer the Javascript embed method because it supports redirection if the user doesn’t have Flash, not just alternate content on the same page.

  18. I want to thank you. I was actually writing something very close to this myself, but had not finished it. This is actually a bit simpler than what I had planned, which is great. I tend to overcomplicate things like this. Thanks for making my day!

  19. Nice, but as Mark Wubben pointed out, it won’t work with XML. Try to serve your XTHML pages as application/xhtml+xml (like you should) and see if it works.

  20. Indeed, but after spending the last few days looking at my options for using createElement and appendChild I have to say that I’m entirely unimpressed by how different browsers handle them and the Flash plugin. In Safari, the Flash plugin seems to ignore the parameter tags inside the object tag, IE magically pulls tons of parameters from what must be the Flash plugin. Firefox/Mozilla seem to handle it just fine, and Opera doesn’t seem to let me use setAttribute on an object tag for things that aren’t in the dtd (like width, and height).

    Mark’s method creates an embed tag and uses that in everything except for Opera. Now I could argue that since there is no such thing as an embed tag in xhtml, that using the sIFR embed is just as bad. The one advantage the sIFR method would have, of course, is that it actually works when using application/xhtml+xml mime types. :)

    Lastly, there’s the question of how many people are actually using application/xhtml+xml mime types and embedding Flash on their pages. I would argue that if you are that crazy about using web standards, you should find a way to present your content within those confines (ie not use 3rd party plugins).

  21. … and safari ignores the param tags, and opera doesn’t let you add width or height attributes to the object tag… the list goes on. I’m putting together a new post on all the little quirks. I should have it ready in the next few days.

  22. Geoff, thanks for the script. Excellent work.

    Not sure if anyone else has seen this, but I just did some testing and it appears that using flashObject.addVariable(“variable”, “value”) causes IE 5.2 on Mac OS X to not write the Flash.

  23. Pingback: Link-Fu

  24. Actually I have it working in IE, but it’s rather pointless since IE doesn’t support the application/xhtml+xml mime anyway, so really if the user has IE you could just flip to a innerHTML or document.write and be fine.

  25. This doesn’t work with IE 4.5 on Mac OS 9.2.2. I’m using this system just for testing, and i can see other flash files on other sites, but not this one.

  26. Thanks Glen.

    While I’m curious as to why it doesn’t work, I probably won’t make any large changes to accomodate it.

    I think IE 4.5 on OS9 is old enough to where I don’t think any client will ever specifically request Flash content to be displayed in it. Most of the sites I’ve worked on lately even cut out Netscape 4 and only go down to IE 4 (and even then only basic functionality).

  27. Hello Geoff!

    A great piece of code. I’ll be using it a lot. BUT (always a but…), I think I´ve found something that might not be working as intended (at least according to my needs). If the flash is not detected, the alTxt is written where the <script> resides, not within the container div, when a div is declared in the write() method.

    I just added the extra [if] in my local script, but maybe you want to do it in the source.

    Greetings!, and thank you for a nice and usefull script.

  28. Hi Geoff, I have added an address into the ‘this.redirect’ section: this.redirect = “http://www.google.com”; and am finding Netscape 6 on PC will not redirect, it hangs on the same page. I am not clever enough to figure this one out! Many thanks for the script.

  29. Hmm, looks like another bug. I added in an extra else on the redirect if statement and that seems to have fixed it.

    Grab the source again and try it out.

    Also, proper use of that would be like this:

    var myFlashObject = new FlashObject("walker.swf", "walker", "300", "150", 7, "#999999");
    myFlashObject.redirect = "http://www.google.com";
    myFlashObject.write();

    You don’t want to change it in the .js file since then all your Flash movies would redirect – this way you can redirect some of them and provide alternate content for others and use the same .js file.

  30. Hi. This looks like a great piece of script – nice one.
    One ask though – could you add functionality to fake “not having flash” via a param or argument?
    It might make testing the alternate content easier…

    Just a thought.

    G

  31. I’ve just been changing the code to require Flash 8 or 9 so it fails and shows me the alternate content. Once that is all looking good I’ll switch it back to whatever version of Flash I’m using.

    Like this:

    var myFlashObject = new FlashObject("walker.swf", "walker", "300", "150", 8, "#999999");

  32. Hmmm, I’m still wondering on the status for this method and flashVars when using Safari – I don’t have access to a mac to test this, but I know from my own troubles that ‘Standards Compliant’ methods and FlashVars with Safari are dodgy – does this script offer a Safari sniffer that ‘bodges’ the flashvars into the object tag if the browser does turn out to be Safari? A ‘bodge’ which gets the desired result is better than standards that don’t. I love standards and always try to use them and supply them to all browsers that support them – but if they don’t I have no qualms about supplying less compliant code to the crap browsers providing it doesn’t negatively effect the whole thing for everyone else.

  33. This method (FlashObject) works fine with Safari and all the extra options work because Safari uses the embed tag generated by the script. The reason why the other ‘standards compliant’ Flash embeds crap out on Safari is because it ignores param tags inside object tags.

    I’m working on an XML version of this that indeed checks for Safari and then adds the flashvars or other custom parameters and adds them to the object tag as attributes so Safari will see them.

  34. Ok Geoff, thanks for that, was it you who told me about the flashvars attribute on object tags working but not validating somehwere before – on another site, I just seem to remember thanking a guy called Geoff for that little tidbit before.

    This whole thing looks a good idea, for ages I was against the idea of javascript writing in flash content, until I realised that it is probably the most reliable and workable way to validate, check for flash, and provide the right flash content to the right browsers. Even if browsers suddenly come up with a uniform way to do it with all teh functionality available it’ll take a year or most likely more before it is ok to use it since people/organisations are so slow to update their browsers. I get very disheartened by the whole thing, I hate waiting, but I maintain the hope that in a few years things will all be lovely and standard.

  35. This should get me out of trouble with visitors who won’t trust ActiveX controls etc.
    Just 2 questions:
    myFlash.addVariable(“swLiveConnect”, “true”);
    Is that what I need for swLiveConnect?

    How to set width and height as percentages?

  36. The LiveConnect I’m not positive about, but I see no reason why that won’t work (it looks correct to me).

    As for the width and height as percentages, you just put the values in quotes, so it looks like this:

    myFlashObject = new FlashObject(..., "100%", "100%", ...);

    This way they are treated as strings and will be written into the object/embed tags correctly as percentages.

  37. Pingback: The Tao of Webdesign

Comments are closed.