June 4, 2010 0

IE6, MooTools, and MultiBox: A Tale of Woe

By in javascript, mootools

On a recent project, I traveled to the depths of hell and came out alive. Here’s how it went down…

The initial task wasn’t all that unique or difficult. We were to add a few videos (most hosted on YouTube, with a couple self-hosted) that would open in a lightbox-style popup when the thumbnails were clicked. MooTools was already being used on the project, so we selected MultiBox by phatfusion as the pop-up of choice. I won’t go into the reason(s) for selecting MultiBox. The more I work with it, the less I like it; but that’s for another post. So, we have MooTools as the JavaScript framework and MultiBox as the plug-in.

Base Functionality

Keeping progressive enhancement techniques in mind, we set the destination URL of the thumbnails to be the video page on YouTube. This gives crawlers the ability to find the true video destination, as well as user’s without JavaScript the ability to find the video. Now, I realize that YouTube doesn’t even work without JavaScript, but that’s their problem. (On a side-note, it’s really sad that they use JavaScript to inject the Flash video player, when the SWFObject static publishing method would work just fine).

So the first problem we run into is that, by default, the MultiBox media type of youtube expects the link URL to point directly to the video and not to the video page on YouTube (one reason to ditch MultiBox). Note the difference in URLs below. The video identifier is the same in both (eCzEkiIucUk) but rather than passing it as a parameter to the ‘watch’ page, we can pass it as the slug to /v.

Video page on YouTube: http://www.youtube.com/watch?v=eCzEkiIucUk
Actual video on YouTube: http://www.youtube.com/v/eCzEkiIucUk

To deal with this, I wrote a quick script that executes ondomready. It parses the v parameter value out of the query-string and rewrites the URL to point directly to the video. This way, when MultiBox opens and inspects the URL to load, the video itself is opened in the MultiBox pop-up rather than the entire YouTube page.

Roadblock #1 : MultiBox ‘types’

At this point, everything is working as expected until the client requests that we provide a customized fallback message for users without Flash. This is a perfectly reasonable request. Ideally the fallback content would be a transcript of the video and perhaps some still images from the video. Maybe even a link to the raw H.264 video. Of course, in this case we are requested to simply provide a ‘Please install Flash’ message. Unfortunately, MultiBox doesn’t have a way to provide custom fallback content for its youtube type. (Yet another reason to ditch MultiBox.)

Rather than using the youtube type and its out-of-the-box functionality, we’ll switch over to the element type. This type allows you to target an element in the dom and the targeted element (and children) is cloned into the MultiBox pop-up. For this to work, we’ll provide our own object element, complete with cross-browser nesting of objects (see SWFObject static publishing) and our own custom no-flash fallback content. Each video thumbnail will now have the actual video markup next to it in the source, hidden via CSS. The thumbnail is marked up to link to the video page on YouTube (for JS-off users). On page load, the links are rewritten to point to the fragment identifier of the video object in the page (e.g. href="#video1"). This way, when MultiBox is activated using the ‘element’ type, it will grab the object element with id="video1" and clone its contents into the pop-up.

Roadblock #2: MooTools ‘clone()’

With the exception of IE6, everything works as expected across browsers both with and without JavaScript. However, it fails in IE6 (of course). Upon inspection of the cloned object elements after they are inserted into the pop-ups, we notice that they no longer contain the param children they’re supposed to. The original object elements still contain their param children, but the clones do not. Internally, MultiBox uses the MooTools clone() method on the base Element class so I put together a quick test page to verify that MooTools’ clone() method works properly in IE6 on object elements. It failed the test, and I filed a bug against MooTools.

The workaround for the MooTools clone() bug is to use the old-school innerHTML property ourselves rather than allowing MooTools to do proper DOM manipulation in the background. So I open up MultiBox and find the routine whereby it uses clone() and add a quick hack. I check if the browser is IE6 and if so, use innerHTML to copy the object element (and all its children) into the pop-up.

Roadblock #3: IE6 ‘flashvars’

So now we have the object being correctly cloned into the pop-up when a user clicks the video thumbnail. An then I get another ticket. All the YouTube videos are playing, but the self-hosted video is not. Why is the video not playing? This particular video is played using a SWF player which takes the FLV file name to play via the flashvars param. I notice that the FLV file isn’t being requested in IE6. But we just fixed the param bug and the children are all there! Or are they really? After some more debugging and googling, I find that IE6 resets the value of the flashvars param when its innerHTML is modified.

You’re not surprised, are you?

After some more searching, I find a great blog post that describes the solution. Rather than passing the different variables to the flash player using the flashvars param, we’ll just add them to the SWF query-string. So this:

<object … >
  <param name="movie" value="player.swf" />
  <param name="flashvars" value="path=video1.flv" />

becomes this:

<object … >
  <param name="movie" value="player.swf?path=video1.flv" />

Since we’re using SWFObject’s static publishing method, there are 2 object elements. One intended for IE, and another one, intended for everyone else. The proper object (for Firefox, Chrome, et. al.) is nested within the IE object and hidden via Conditional Comments. Since this whole flashvars mess is only a problem for IE6, we only need to modify the outer object element.

Roadblock #4: MultiBox’s flvplayer

Just when you thought we were out of the woods, we have one last issue. Now that we have the video objects with proper fallbacks, and the elements being cloned properly, and the config file information passed correctly, we still don’t have a functioning video in IE. Since we modified the outer IE object element, thanks to the previous issue, we’ve broken the video in all versions of IE. What’s the problem this time? It turns out that the flvplayer.swf that comes packaged with the phatfusion MultiBox doesn’t stream the video properly when the FLV file name is passed via query-string. Solution? Ditch phatfusion’s flvplayer and use another! (I recommend any of the JW players if your situation fits the non-commercial bill)

When the bugs align…

So at the end of this ordeal, I had three more reasons to avoid phatfusion’s MultiBox widget, I had filed yet another bug against MooTools, and I had conquered yet another bug in IE6. And it all piled up because of a tiny bug in a particular flvplayer; that was caused by the solution to a specific bug in IE6; which was only a problem because of a bug in a particular version of MooTools; which was only a problem because of a poorly designed API in MultiBox; which was encountered because the client wanted to display a download button for Flash; mostly for users who aren’t even able to install Flash if they wanted to. Don’t you just love web development?


Tags: , , , ,

Leave a Reply

You must be logged in to post a comment.