03
Feb 09

IE7 Flash Embed Bug
(Re: The DOM is a Mess)

It’s somewhat ironic that I happened to notice a paticular DOM bug today, of all days. Today, John Resig posted a blog entry called “The DOM is a Mess” in which he described–and posted a video link to–a talk he was asked to give at Yahoo recently.

As the title suggests, the talk was about how javascript is inextricably linked to the DOM, and how this entanglement has caused DOM-specific javascript to have lots of browser-specific bugs. In one of his slides, John says:

Nearly every DOM method is broken in some way, in some browser.

This is hard to believe, I know; but it’s true.

So, back to why we’re here. It just happens to be a coincidence that the day I watched John Resig’s video, I found a particularly nasty bug in IE. Now, I know I’m using the word bug loosely. I have yet to actually figure out what is causing the error. It is possible the error lies with flash. But as you will see in a moment, it is certainly very peculiar.

I noticed the bug when I was testing this very blog in IE 7. Here’s the wierd behavior:

Whenever I would refresh, leave, or close a tab in IE7 of a document which contained an <embed> element, I was receiving an “Object required” error. If that isn’t strange enough, the error seemed to always occur on “Line 53, character 3″ regardless of where the <embed> tag was in the page.

Here is my bug report page with bug isolated: http://polymath.mit.edu/projects/ieBugs/objectRequired/ieError.html.

Fortunately, I found a very simple fix. (Found here.)

<embed id="ieFixID"></embed>
<script type="text/javascript">
window.onbeforeunload = ieFix;
function ieFix() {
	var ieFixElement = document.getElementById("ieFixID");
	ieFixElement.parentNode.removeNode(ieFixElement);
}
</script>

The idea is to use the onbeforeunload event to remove the <embed> element before you leave the page. I’m still not 100% sure why this solution works, but hey, it does. So let’s not complain.

If anyone has seen this bug before and has any insight, it would be much appreciated.


Tags: , , ,


15 Responses to “IE7 Flash Embed Bug
(Re: The DOM is a Mess)”

  1. Maitane Says:

    commenting usually isnt my thing, but ive spent an hour on the site, so thanks for the info

  2. Jonathan Says:

    Thanks so much for posting this! It’s the kind of thing I probably never would have figured out on my own.

    Can you make any suggestion for what to do, for example, on a blog that aggregates multiple posts on the main page? I could put the ieFix in each individual post, but on the main page where mulitple posts are aggregated it seems like the onbeforeunload only does it’s job once and so doesn’t take care of all embeds from the separate posts (at least that’s how it seemed to me as I was messing around with it late at night).

  3. Jonathan Says:

    Also, I tested it on my work laptop (running IE6) and confirmed the bug with IE6 too.

  4. adam Says:

    @Jonathan
    I’m glad I could help. You wouldn’t need an ieFix function for each post, but you would need to add a removeNode for each embed tag you had on the page. For example you could do something like this:

    <embed id="ieFixID1"></embed>
    <embed id="ieFixID2"></embed>
    <embed id="ieFixID3"></embed>
    <script>
    window.onbeforeunload = ieFix;
    function ieFix() {
    	var ieFixElement1 = document.getElementById("ieFixID1");
    	var ieFixElement2 = document.getElementById("ieFixID2");
    	var ieFixElement3 = document.getElementById("ieFixID3");
    	ieFixElement1.parentNode.removeNode(ieFixElement1);
    	ieFixElement2.parentNode.removeNode(ieFixElement2);
    	ieFixElement3.parentNode.removeNode(ieFixElement3);
    }
    </script>
    
  5. Jonathan Says:

    That’s what I did and it worked for multiple embeds within a single post/page. What didn’t work was when multiple posts were aggregated on the front page of the blog.

    Let me try to describe the problem better:

    Blog post 1 has an embed. Blog post 2 has an embed. The script works on the permalink page for blog post 1 and the permalink page for blog post 2. However, on the front page of the blog (where post 1 and post 2 appear together), it doesn’t work. One of the embeds still creates an error. window.onbeforeunload is called (or whatever the proper term is) in the post 1 part of the main page and in the post 2 part of the main page, but maybe it can only works once per page?

  6. adam Says:

    @Jonathan
    Ahh, I now understand the situation. This can easily be solved in a number of ways. I’ll first tell you the one which will work well with what we already have.

    Method 1

    First, check out the addEvent() function found here. Using this function we can get multiple functions to be triggered using the same event. So you’ll want to put this function in a functions.js file on your server and add it to your wordpress template’s <head>.

    Next, to avoid collisions, you’ll want to make sure that the ieFix() functions are renamed to ieFix_something() where the “something” is unique from post to post. (Otherwise on the front page we’ll have two javascript functions with the same name.) Other than renaming these functions, the contents can stay the same. (However, again, the “ieFixID1″ and similar IDs will also need to be unique throughout the different posts.)

    Lastly, instead of writing:

    window.onbeforeunload = ieFix;

    you’ll need to write:

    addEvent(ieFix);

    The addEvent() function will take care of the rest.

    Method 2

    This method is probably better, but it might be harder for inexperienced javascript developers to follow.

    First, download the jQuery javascript library and add it as a script to your documents <head>

    Next, don’t even bother giving id’s to all of your embeds. Instead give them all the same class:

    <embed class="ieFixMe"></embed>

    and add this javascript code to your template (not individually to each post).

    window.onbeforeunload = function(){
    	$(".ieFixMe").remove();
    }
  7. Jonathan Says:

    Thanks Adam. I’ll give it a try sometime soon. I use Drupal, not Wordpress, but presumably Google will be my friend and teach me how to add javascript to my Drupal template, etc.

  8. Jonathan Says:

    Seems like Method 2 should be pretty easy for me to do since jQuery is baked in to Drupal and it looks like I can just drop a script.js file into the theme’s folder.

    http://drupal.org/node/171213

  9. Jonathan Says:

    I’ve got Method 2 working! Thanks!

  10. adam Says:

    @Jonathan
    No problem. Glad to help.

  11. wk Says:

    Thanks, it worked for me as well, much appreciated.

  12. Willie Says:

    Hi, your solution worked wonderfully!

    Let me share with you the “mootools” version. If say all of your problematic DIVs where of class “jw_player”, then the code would be like:

    window.addEvent (’beforeunload’, function() {
    $each($$(’jw-player’), function(el) { el.dispose; });
    });

    You can change the class name to whatever you wand and add several $each sentences as classes you have.

    Willie.

  13. adam Says:

    @Willie: Thanks for the mootools port!

  14. Frank Says:

    Thanks, that comes in very handy. As I am using mootools for nearly every project, the port is exactly what I need!

    keep up the good work!

  15. Issac Maez Says:

    Great insight. I agree completely



Leave a Reply