Rendering Flash Content with Dynamic WMODE Attributes

We all know that to have Javascript menus and such overlay embedded Flash content, that we need to set the WMODE parameter of our embed code to “opaque” or “transparent”. This is usually pretty simple if you are generating the embed code yourself through SWFObject, or even simply through HTML.

Here’s the thing… what if your application allows users to embed SWF content from YouTube, Vimeo, and other such services? What if your system generates little edit menus that happen to overlap such content? These services generally do not include the proper WMODE values to allow dynamic overlays. If you are just accepting SWF embed content, it’s a simple task to just parse the embed string and store the necessary values in your application to spit back out later using your own embed code formatting. What if there are just too many unknowns about the content your users may need to embed in the application? What if you also accept plain HTML embeds from services like Twitter and Facebook or other non-SWF content that you cannot parse attributes from so predictably? Then you need to do some more tricks to get that WMODE parameter set for any potential Flash content!

I use jQuery quite a bit when I absolutely need to deal with Javascript and like how it keeps the code from getting out of hand. It also provides a ton of extra functionality that is really useful when trying to identify certain elements in your HTML document for manipulation. I’d already tagged any user embed containing elements with a class of “embedHolder”, so using jQuery it would be super simple to identify all user embedded elements. So the original plan was to use both append() and attr() to modify any object or embed tag nested within any of these tagged container elements in order to add the necessary WMODE parameters:

$(document).ready(function(){
	$(".embedHolder object").append('');
	$(".embedHolder embed").attr("wmode", "transparent");
}

This doesn’t work though! It will certainly go through and modify the elements as needed, but since the SWF content has already been drawn into the viewport, the WMODE parameters are ignored. Thankfully, jQuery is super-awesome and includes both a show() and a hide() method. When you use hide() on an element, it will remove it from the viewport. Using show() will make it visible again. this effectively forces the browser to reload and redraw the SWF content, this time taking the WMODE changes into account perfectly.

$(document).ready(function(){
	$(".embedHolder object").append('');
	$(".embedHolder embed").attr("wmode", "transparent");
	$(".embedHolder").hide();

	//a bunch of other code you may have

	$(".embedHolder").show();
}

Awesome!


UPDATE 1: Errr… awesome in some browsers. As Josh points out below, the actual behavior differs quite a bit between browsers. No problem- I have a plan and will update this tomorrow with a solution. (hopefully!)

UPDATE 2: Yeah- IE is the only problem browser I’ve come across. Surprised? No.

UPDATE 3: Here is a solution for all browsers (even IE!):

$(document).ready(function(){
	$(".embedHolder object").append('');
	$(".embedHolder embed").attr("wmode", "transparent");
	$(".embedHolder").each(
		function () {
			var cont = '
‘ + $(this).html() + ‘

‘; $(this).replaceWith(cont); } ); }

Now we are explicitly removing elements from the DOM and then reloading them into the same node, forcing the browser to redraw the SWF and activate the proper WMODE.

12 thoughts on “Rendering Flash Content with Dynamic WMODE Attributes”

  1. You should check to see what show() and hide() actually do. If it removes the embedded content from the DOM entirely and adds it again, you should be fine. However, if it simply modifies the “display” or other related styles, then it’s important to note that browsers all behave a little differently. Some will reload the SWF entirely. Some will simply hide it, as those styles imply, but leave it running. Be sure to do cross-browser testing!

  2. My understanding is that they modify the “display” CSS attribute to “none” and back again.

    This is the trouble with HTML- while everyone cries “STANDARDS!” every browser still adheres to their own specific implementation.

    Straight-up doesn’t work in IE!

  3. Yeah, this just sets the object to ‘display: none;’ – and as Josh / Joseph pointed out, it does something different in each browser. (Nevermind those crazy Firefox browser bugs with wmode=transparent… grrr.)

  4. Pingback: Rendering Flash Content with Dynamic WMODE Attributes – Revisited | In Flagrante Delicto!

  5. Hey there, trying to get this to work and it definitely seems (even with updated code) to fail in IE7 and IE8. Though I am also trying to add the wrappers dynamically cause it’s for a blog:

    my code:

    $(“object”).wrap(”);
    $(“object”).append(”);
    $(“.embedHolder embed”).attr(“wmode”, “transparent”);
    $(“.embedHolder”).each(
    function () {
    var cont = ” + $(this).html() + ”;
    $(this).replaceWith(cont);
    }
    );

    Any ideas?

  6. Thank you for this. If you want to use it without the embedWrapper class (and assuming your content folks are copying YouTube embed code, where an embed is wrapped in an object), lines 4 thru 9 can be replaced with:


    $('object').each(function() {
    var newContent = $(this).clone();
    $(this).replaceWith(newContent);
    });

    Thanks again!

  7. Hmm … JQuery aside for a moment, the following simple JavaScript code works perfectly for me.

    Considering the following object tag:

    Dynamically setting the rendered object’s wmode at runtime works like this:


    // Once I have reference to my player (the_player) (choose your method),
    // I simply do ...

    var param_wmode = document.createElement('param');
    param_wmode.setAttribute('name', 'wmode');
    param_wmode.setAttribute('value', 'opaque');
    the_player.appendChild(param_wmode);
    the_player.wmode = 'opaque';

    Done!

    Note:

        - This works just as well for embed tags; stand-alone (html5) or nested. Just set the embed's wmode attribute accordingly.
        - Success may also depend on your chosen doctype. I use the html5 doctype declaration, but I don't believe that's the secret here.
    
  8. I love you so much exactly was I was looking for!
    Tried already 5hours to solve this problem… very frustrating.
    Thanks!

  9. Great post! And still very much up to date. I have one small observation that you might find useful: “opaque” and “transparent” are not”100% identical. I believe the latter will draw more system resources because it needs to apply alpha filters for rendering, whether “opaque” does not. If you want, you can check out the Stack Overflow discussion on the matter: http://stackoverflow.com/questions/886864/differences-between-using-wmode-transparent-opaque-or-window-for-an-embe
    Cheers!

Leave a Comment

Your email address will not be published. Required fields are marked *