Pixelastic

You can cut our wings but we will always remember what it was like to fly.

Posts tagged with "swfobject"

swfobject.getObjectById() when flash not installed

SWFObject is the de-facto library used whenever you need to ember Flash files in your code. It takes care of smoothing all cross browser issues.

It has a getFlashPlayerVersion method that return a string of the current version in the form major.minor.release. Its value is 0.0.0 if Flash isn't installed.

It also provides a cross browser markup, including conditionnal comments for IE, that validate and works everywhere. The downside is that it forces you to create two elements in your markup with the same id.

Hopefully, the getObjectById method is here to return the correct DOM element based on the browser flash integration type.

But... It seems that the mechanisme is buggy when Flash isn't installed (on 2.2)

I've tested running IE9 without Flash installed and FF8 with Flash disabled, and the return of getObjectById differs : I got null in IE9 and the DOM element in FF8.

I've added a small patch to my code to take it into account :

var el = swfobject.getObjectById(id) || document.getElementById(id);

And I've also submitted a bug report.

Alternate content with SWFObject

SWFObject allow a web developer to add an alternate content in place of the swf file is the user doesn't have flash installed.

In the case of a web app this is great to provide your user with a link to the Adobe website. You then tell your users Flash is needed and provide a link for them to install it.

Unfortunatly, if for one reason or another the swf file you try to load is unreachable (maybe your host is down ?), SWFObject will display the same alternate content. Meaning that a user with a perfectly correct Flash version will see an error message telling him that he does not have Flash when in fact the error is on your side.

That's not very user friendly and makes you look bad.

So, to fix this, I added two error messages as alternate content :

<div id="alternateContent" class="alternateContent">
<div class="noFlash message">It seems that you do not have the Flash player installed. Please install it, by <a href="http://www.adobe.com/go/getflashplayer" target="_parent">following this link</a>.</div>
<div class="error404 message">Sorry, we were unable to load the game. Please try again in a few moments.</div>
</div>

Then, in CSS I decided to hide them both :

.alternateContent .message { display:none; }
.alternateContent.noFlash .noFlash { display:block; }
.alternateContent.error404 .error404 { display:block; }

And finally, in Javascript I checked for the current Flash version. If it's equal to zero, it means that Flash is not installed, so I display the noFlash error message, otherwise, I guess it's a 404 error and display the other message.

var flashVersion = swfobject.getFlashPlayerVersion(),
alternateContent = $('#alternateContent')
;
// Displaying one message or the other
if (flashVersion.minor=='0') {
alternateContent.addClass('noFlash');
} else {
alternateContent.addClass('error404');
}

This is not bulletproof : I only test for two cases. And a better solution would also have been to put the error message dynamically using Javascript instead of polluting the HTML markup with contradictory text.

SWFObject must be included in the <head>

We just discovered a strange behavior on one of our test VM (one without Flash installed). I don't know how we've missed it before.

When embedding the main flash file of our application, the alternate content wasn't displayed to players. In fact it seemed to be displayed very briefly then disappear.

I had correctly embeded it with the static publishing method and added a call to swfobject.registerObject to soften the edges. I remembered it working correctly in my tests, so I quickly made a small test case.

It occurs that the alternate content was corretcly displayed if I removed the swfobject.registerObject call and only used the static publishing.

I also found that everything worked fine if I called the swfobject.js file in the head, but started to bug when I moved it at the end of the page.

As I didn't want to add a call to a .js file in my head, I google a bit and I finally found that one have to call swfobject.switchOffAutoHideShow(); right before the swfobject.registerObject call. This seems to fix things by not hiding the alternate text

Edit

I spent some more hours trying to debug the last corner cases. We had a user using Firefox 3.5.3 with Flash 10.0.42.34. Using SWFObject, we required at least version 10.1. Unfortunatly, the app was still loading, but was buggy because of features not present in the user flash version.

After some tests, I discovered that the swfobject.js code MUST be included in the <head> of the document (well, before any .swf in the page, so better put it in the <head>).

Doing so, you won't even need the previous fix (swfobject.switchOffAutoHideShow()).

I would have loved putting it at the end of the page, with the others JS files, but I guess I won't have a choice here.

Making Flash and Javascript speaks to each other

I needed a Flash app and my Javascript code to be able to communicate. The Flash needed to call some methods in the Javascript, and in turn the Javascript needed to inject back some data into the Flash.

I let my Flash coder colleague took care of the Flash side, he needed to implement ExternalInterface, register some callbacks methods that I could call and more importantly change some security settings to make it work.

On my side, I just needed to get the object element holding the Flash (thanks to swfobject.getObjectById it was pretty easy) and call the callback method registered in Flash on it.

Piece of cake.

Have a look at this blog post from CircleCube, it does a pretty neat job at explaining all of that.

Update :

I finally had some issues with this implementation. It was working perfectly on some servers but not on others. We finally found that calling Security.allowDomain('*.mainhost.com') wasn't working.

You have to explicitly allow each domain/subdomain.

As our code would be deployed on various duplicate domains, we had to manually pass as a flash var the domain to allow.