Just Another Blog

Are you thinking what I'm thinking?

Friday, July 21, 2006

Flash disabled? No more! ;-)

Currently I'm working on a website that uses Flash on one of its pages. As you should already know, ActiveX interaction is disabled in Internet Explorer because of the Eolas issues. You can read more about this in the Activating ActiveX Controls article published in MSDN.

Since I want to write in valid HTML only, the HTML code should be written as something like this:

<object type="application/x-shockwave-flash" data="example.swf">
<img src="example.png" alt="Alternate content">
</object>

This works perfectly on anything but IE. In order to make IE happy, we have to add an extra param element:

<object type="application/x-shockwave-flash" data="example.swf">
<param name="movie" value="example.swf">
<img src="example.png" alt="Alternate content">
</object>

Now IE knows where the movie is and loads it properly. But the ActiveX control is disabled from user interaction. So a little JScript is needed here.

By googling, I came up with this informative blog post: Flash interaction disabled in Internet Explorer. The solution by David Merrilees is almost perfect. The idea is to remove the data attribute not recognized by IE, recreate the whole object element using outerHTML, and using CSS to prevent flickering.

But he is missing one important thing: what about user with JScript disabled, CSS enabled and Flash plugin installed and enabled? They will see nothing because the visibility is set to hidden initially.

So, instead of hiding the objects for all IE users, what about hiding the objects for all IE users with JScript enabled? While ideally we should use DOM method to modify the HTML content, we can't do so here as it will be already too later if we hide the Flash movie until window.onload. Fortunately, we can use document.write to output stylesheet that hide the objects before the document is loaded:

document.write( '<style type="text/css">' );
document.write( 'object { display: none }' );
document.write( '</style>' );

While I personally hate using document.write, it is OK here as IE only supports HTML (specifically (X)HTML served as text/html).

So the rest is almost identical to David Merrilees's solution, except that I've used display: none instead of visibility: hidden as I found it not working for me.

HTML

Conditional comment is used so that only IE will run this JScript (activex_fix.js). Be sure that it is included inside the head element, not the body element.

<!--[if IE]>
<script type="text/javascript" src="activex_fix.js"></script>
<![endif]-->

JScript (activex_fix.js)

window.attachEvent is used, so that it won't mess up other cross-browser onload handlers like window.onload (or better, DOMContentLoaded).

// Hide objects to prevent flickering when recreating the objects
document.write( '<style type="text/css" id="activex_fix">' );
document.write( 'object { display: none }' );
document.write( '</style>' );

// Recreate and reveal the hidden objects
window.attachEvent( "onload", function()
{
    // Recreate the objects
    var objects = document.getElementsByTagName( "object" );
    for ( var i = 0; i < objects.length; i++ )
    {
        var object = objects.item(i);

        // Fix flash object
        if ( object.type == "application/x-shockwave-flash" )
        {
            if ( object.getAttribute("data") )
            {
                object.removeAttribute( "data" );
            }
            object.outerHTML = object.outerHTML;
        }
    }

    // Reveal the objects by removing the stylesheet created by document.write
    var stylesheet = document.getElementById("activex_fix");
    stylesheet.parentNode.removeChild( stylesheet );
} );

This idea should also work for Opera 9, which follows IE's decision to disable user interaction with plugin content. I didn't bother to deal with it as it is not required by the client. :-P

0 Comments:

Note that troll and spam comments will be deleted without any notification.

Post a Comment

<< Home