« March 2006 | Main | June 2006 »

May 2, 2006

A Sabbatical, Adobe, and Allaire

I haven't been active blogging or on message boards lately, but I'll be even less so for the next five weeks. I have started my sabbatical, which includes a five week journey where I won't have a laptop, work email access, or many other of the things that I've come to find nourishment from.

A great job where you get a sabbatical, get to work on something as cool as Flex, where you have managers who (I'm guessing reluctantly) let you jet away in the middle of a release. Did I mention we still have job openings for those interested?

To go on a tangent, I recently found a hilarious picture in my office, an advertisement I was in from the Allaire days. To embarrass myself, here it is.

Finally, if you'd like to read about my travels, you can do so.

Posted by Brian at 2:06 AM | Comments (1) | TrackBack

Update to Embedding HTML in a Flex Application

An update to this example for the final version of Flex 2 can be found here.

I updated the files for Embedding HTML in a Flex application in AS3 in this directory. I didn't test the files with beta 2, but they should work with the upcoming beta 3.

One important change is in the HTML wrapper, which was causing the HTML to sometimes disappear when using IE. There needs to be a parm setting wmode to opaque. I also updated the HTML wrapper to a newer version, and made a few other minor changes (which I would list, but it's been so long I've forgotten them...)

The migration text I promised a long time ago doesn't look like it'll ever get completed, so I'm just going to copy the 80% done version below for those interested.

When migrating Christophe's solution, Embedding HTML in a Flex application using an IFrame to Flex 2, I kept detailed notes of what I was doing. Below is the prettified version of these notes.

The Easy Changes

After writing this part of the migration explanation, I realized it wasn't really necessary, that it's easy for anybody to compile, see the errors, and look up in the help system any of the errors that come up. This worked very well, and I was easily able to figure out most of the issues I came across. But I kept writing things out, so here's the full migration info for those interested.

I took the compile-fix-repeat method of fixing the issues. A studying of a migration guides along with a more structured search and replace would make more sense for a large project, but I knew some of the issues already, and I'm only converting three files.

The first thing I did, without thinking, was change the mxml namespace from "http://www.macromedia.com/2003/mxml" to "http://www.macromedia.com/2005/mxml". The next change I made with my eyes closed was to add access modifiers to functions and type declarations variables. So "function moveIFrame()" became "private function moveIFrame()".

Adding a type declaration of Object to pt gave me the Error "Implicit coercion of a value with static type 'Object' to a possibly unrelated type 'flash.geom:Point'". This made it obvious that I needed to change:

var pt:Object={x:0, y:0};

to:

var pt:Point=new Point(0, 0);

After that, I compile the add and got the error "Overriding function that is not marked for override" in IFrame.mxml, which extends Canvas, on this method:

public function set visible(visible: Boolean): Void {

That's another thing I should done off the bat, which is add override to methods that override:

override public function set visible(visible: Boolean): Void {

Next I'm told that getURL doesn't exist:

getURL("javascript:hideIFrame()");

I search the help and see that this line now needs to be:

public var u:URLRequest = new URLRequest("javascript:hideIFrame()");
navigateToURL(u);

And I add "import flash.net.navigateToURL;" to the top of the Script block.

Next I saw "Type annotation is not a compile-time constant: Void", which means I needed to change Void to void everywhere I see it.

doLater() showed up as removed, so after searching the docs I changed this it to callLater, from:

doLater(this, 'moveIFrame')

to:

callLater(moveIFrame)

Dealing with HTML and ExternalInterface

At this point everything compiled fine. I put index.htm into the directory where the SWF was (since I couldn't tell Flex Builder to use a custom html wrapper) and then clicked on the file to display... nothing. Ah yes, the SWF name was different now, from IFrameDemo.mxml.swf to IFrameDemo.swf. So I load it again and... nothing. I load just the SWF and it displays. I take the script out of the HTML page and see this error from Flash:

SecurityError: Error #2051: Security sandbox violation: 'file:///C:/dev/flex/projects/iframe/IFrameDemo.swf' may not evaluate scripting URLs within 'file:///C:/dev/flex/projects/iframe/index2.htm'.

I remembered that there was a new restriction in Player 8 (and 8.5) where local files and network files could not be accessed in the same movie. I wondered if relative URLs were thought to be network files. Sure enough, when I loaded the SWF through JRun, I didn't get the error anymore. But the page within the page still didn't show up. I figured out that unlike getURL(), navigateToURL() would not work allow any frame to be given as the second argument. So I decided to go ahead and convert the navigateToURL() calls to ExternalInterface.

This took awhile. Converting the navigateToURL() calls was easy, as the ExternalInterface calls were very simple, like this:

ExternalInterface.call("loadIFrame", source);

But still the html page was not showing up. What was going on?

At this point I conceived my my "debugging strategy" in Javascript, which consisted of looking at Firefox's Javascript console and throwing alerts up as debug statements. Ug. Is there a better way to do this? After sifting through the methods, I figured out that only the first argument to moveIFrame had all of argument information in it. So I changed:

ExternalInterface.call("moveIFrame", pt.x+","+pt.y+","+this.width+","+this.height);

to:

ExternalInterface.call("moveIFrame", pt.x, pt.y, this.width, this.height);

Once changed, the html finally showed up. But the frame showed up in the upper left hand corner. localToGlobal did not look to be working correctly.

var newPt = this.localToGlobal(pt);

After this, everything finally worked!


Making Things Better

The one problem I had at first with the generated html in Flex Builder was that I didn't know there was a to interject Javascript into the page. (html-template)
Add the Javascript functions (moveFrame, etc). Added onMouseDown="document.body.focus();" to the embed, alhtough not sure if htat was needed. Also added + 'wmode="opaque"'
+ 'swLiveConnect="true"' to the embed. Added the iframe named 'myFrame'.

The Tree on the left still looked really odd. Apparently the......

Tried adding "rootVisible="false""

Change the change attribute value in Tree from :

iFrame.source=tree.selectedNode.attributes.path

to

iFrame.source=tree.selectedNode.path

I made a few cleanup changes. The VBScript and related Javascript method in index.htm were removed, since it was only needed for some commented-out fscommands. In IFrame.mxml, I added a check for ExternalInterface via ExternalInterface.available, throwing an Error if it wasn't available. In IFrameDemo.mxml, I added a third section of links for Flex sites.

Posted by Brian at 1:54 AM | Comments (13) | TrackBack