Tuesday, April 25, 2006

Dynamically Inserting FSCommand-Capable Flash Objects With innerHTML

Let me preface this post by saying that if you've never tried to dynamically write a bunch of FSCommand-enabled swfs into an HTML page, you'll probably be really confused by what follows. In point of fact, there's a good likelihood you'll be confused anyway, since my writing is not particulary lucid. But glean what you can. Forging ahead...

Suppose you have a series of SWF files to dynamically insert into a page (maybe, just maybe, as a result of the infernal Eolas patch) and these SWF files need to communicate via FSCommand. You must also add a script block for each swf, to capture the FSCommand calls. Typically, this would be a block of VB Script, like the one Flash puts into the HTML files it publishes with your SWF.

Now suppose we have the filenames of the swfs in an array, and we want to loop through the array and write each swf into the document. We need to dynamically create an ID for each one, create a VBScript for it, and then insert them into the document. Since you can't use innerHTML to insert VB Script, you have to use the DOM:

for(var i=0; i < swfArray.length; i++){
var mySwfId = "swf"+i;

var myVB = document.createElement("script");
myVB.language = "VBScript";
myVB.text = "Sub "+mySwfId+"_FSCommand(ByVal command, ByVal args) \n call "+mySwfId+"_DoFSCommand(command, args) \n end sub ";
// Insert the VBScript into the Head element
document.getElementsByTagName("head")[0].appendChild(myVB);

// Insert the swf into the target element
var mySwf = '< object id='+mySwfId+' ... swf code omitted ... < / object>';
targetElement.innerHTML = mySwf;
}

This method works pretty well as long as the VBScript is inserted before the swf is, and as long as you're doing this before the page load completes. For some reason, the VBScript doesn't seem to work if it is written into the page after loading completes. I fooled around with some techniques for simulating onDomReady in IE, but while some of them worked locally, none of them worked under live network conditions. This meant that I had to put my init() call before the closing body tag, which I hate to do because it makes my code less maintainable.

Happily, it turns out that you can use JavaScript instead of VBScript if you prefer, and JavaScript is much more forgiving in this matter. You can also insert the JavaScript via the innerHTML property:

for(var i=0; i < swfArray.length; i++){
var mySwfId = "swf"+i;

var myJS = '< script event=FSCommand(command,args) for='+mySwfId+'>\n '+mySwfId+'_DoFSCommand <\ /script>';

var mySwf = '< object id='+mySwfId+' ... swf code omitted ... < / object>';

// Insert the swf and the JavaScript into the target element.
targetElement.innerHTML = mySwf+myJS;
}

The order here is important: the JS must be inserted AFTER the swf for it to work if the swf is inserted after page load. If you insert the swf onDomReady, it seems to work in either order. I always add the JS after the swf just to be on the safe side.

Here's where I found out about using JavaScript instead of VBScript to catch the FSCommand calls.

I know this post is a bit confusing, since the code is pseudo-code and out of context. But I'll do my best to answer any questions you might have. At any rate, maybe this will help someone who, like me, was Googling for hours trying to find the answer to this obscure question.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

5 Comments:

Blogger tom said...

If you can post your code on a webpage somewhere and post the url here, I'll take a look and see if I can spot the problem.

7:28 AM  
Blogger Unknown said...

Hey Thanks! This really helped me a lot...Although I had to modify the script a bit...Here is the script-

myJS='<'+'script event=FSCommand(command,args) for='+mySwfId+'>\n'+mySwfId+'_DoFSCommand(command,args)<\/script>';

7:30 AM  
Anonymous Anonymous said...

Non of this work properly in ie6,7.
You don't need to write id_DoFSCommand inside 'script' tag. You just get two variables with names you defined in event listener code (it is command and args in your example). Try this:

<script event=\"FSCommand(command, args)\" for=\"rich\">\n alert('command: '+command+', args: '+args) <\/script>
Much simplier.

4:39 AM  
Anonymous Anonymous said...

Sorry, this will be correct:

<script event='FSCommand(command, args)' for='YOUR_SWF_ELEMENT_ID'> alert('command: '+command+', args: '+args) <\/script>

4:47 AM  
Anonymous Anonymous said...

This comment has been removed by the author.

6:27 PM  

Post a Comment

<< Home