Search Flex Components Free

Custom Search

December 15, 2007

A closer Look at IFrames and ExternalInterface in Flex

Well I've been super busy as usual, working on some pretty cool stuff, still managing to only put food on the table but also sticking to my guns and doing only Flex projects. Of course, my blogging has suffered dearly.

In one of my current projects, I am faced with the challenge of somehow embedding IFrames inside my flex app, however without having any control over the html wrapper that my Flex app will sit in. Sure I could 'advise' users on adding the appropriate javascript functions and the hidden div element at the bottom of the body, as we've seen in other Flex Iframe examples out there. But I figured there had to be a way to do this without needing to rely on this external dependency.

As it turns out I can do inline Javascript function calls within my ExternalInterface.call, an example of this would be:


ExternalInterface.call("function(){return window.location.href;}");which is a simple little function to quickly get the address of the current page. Another handy example is this one:


ExternalInterface.call("function(){document.location.href=document.location;}");This is a quick way for a user to 'logout' of the flex application, it simply reloads the web page. So as you can see, we can do a great deal without ever needing to touch the html wrapper. So why not do the same thing with Iframe support? Here's what I came up with:

ExternalInterface.call("function(){" + "var tempIFrame=document.createElement('div');" + "tempIFrame.setAttribute('id','vyFrame');" + "tempIFrame.style.position='absolute';" + "document.body.appendChild(tempIFrame);" + "tempIFrame.style.backgroundColor='transparent';" + "tempIFrame.style.border=0;" + "tempIFrame.style.visibility='hidden';}"); I am going to try and create a div element in memory and append it to the DOM. It's best to run this code during the application preinitialize() event. However, before I move on to explain the rest I just want to mention that I did run into some issues here with IE6. As you'll notice I appendChild and then I set the styles. Turns out that if I manipulate a new element too much prior to adding it to the DOM, it just gets all flaky and will not work. Believe me, this was not an easy bug to track down!

Now, we need to change the remaining externalInterface calls as well... things like move, hide, show and source. Building on the example at deitte.com that first got me started ages ago, I changed all the calls as they are found in his IFrame.mxml component:

ExternalInterface.call("moveIFrame",globalPt.x ,
globalPt.y, this.width, this.height);
Becomes:
ExternalInterface.call("function(){" + "var frameRef=document.getElementById('vyFrame');" + "frameRef.style.left=" + globalPt.x + ";"+ "frameRef.style.top=" + globalPt.y + ";" + "var iFrameRef=document.getElementById('vyIFrame');" + "iFrameRef.width=" + this.width + ";" + "iFrameRef.height=" + this.height + ";}");ExternalInterface.call("loadIFrame", source);
Becomes:
ExternalInterface.call("function(){vyFrame.innerHTML='" + "';}");ExternalInterface.call("showIFrame");
Becomes:
ExternalInterface.call("function(){" + "document.getElementById('vyFrame').style.visibility='visible';}");ExternalInterface.call("hideIFrame");
Becomes:
ExternalInterface.call("function(){" + "document.getElementById('vyFrame').style.visibility='hidden';}");
After a bit of testing I did manage to get this to work, sort of. I ended up spending some time playing with the compiler options in Flexbuilder. I found that if I turned off history management, my Iframes wouldn't appear. However removing the script reference to history.js seemed to have no real effect. For those of you that are not Flash-savvy :) it turned out that the only things to really watch out for, and again I am at the mercy of the users who embed my flex app into their html pages, is that the AC_FL_RunContent() has a final parameter setting of "wmode", "opaque" and the object embed tag also contains wmode="opaque". If this setting is not there or set incorrectly the Iframe will appear behind your flash player.

Related Flex Tutorials