Flex: IFrame Resizing

In place of a demo I thought I would try and have another stab at describing how to resize the contents of your IFrame to match the size the IFrame itself.

Firstly have a look at the communications demo mentioned in the previous post. Once you understand what’s going on between the page and the Flex app through FABridge this will all make more sense.

The trick is that you want to pass the width and height of your Flex IFrame to the hosted html page and get it to resize it’s contents accordingly. You must place your contents inside an enclosing named ‘div’ which will be resized. Bear in mind I have lifted some of this code from flexTraffic.

1) Add a resize event handler to your IFrame


mapView.addEventListener(ResizeEvent.RESIZE, onResize);

Where mapView is my IFrame instance.

The onResize function looks like this:


private function onResize(event:Event):void
{
    __controller.onResize();
}

2) In my mapController class (the _controller ref in the previous snippet) I have a handler:


public function onResize():void
{
    var ev:ResizeFrameEvent = new ResizeFrameEvent(map.width, map.height); 
    this.dispatchEvent(ev);
}

The ResizeFrameEvent is a bog standard Flex event i.e.


import flash.events.Event;

public class ResizeFrameEvent extends Event
{
	public static const EVENT_RESIZE_FRAME:String = "ResizeFrameEvent"		
	
	public var width:Number;
	public var height:Number;
		
	public function ResizeFrameEvent(width:Number, height:Number):void
	{
		super (EVENT_RESIZE_FRAME, true);
			
		this.width = width;
		this.height = height;
	}
}

The controller maintains a reference to the IFrame object i.e.


[Bindable] public var map:IFrame;

This is setup when the controller is created but basically it’s just a variable which points to the IFrame which holds the map.

You will need to examine the comms demo but what is happening is that the html page is registering an event handler with the Flex app through FABridge. When the event is triggered it’s payload is the new width and height of the Flex IFrame. NOTE that FABridge is automatically generating the functions “getHeight” and “getWidth” these aren’t defined in the ResizeFrameEvent code shown above.

All the following bits of code are javascript.


function load()
{
    this.parent.FABridge.addInitializationCallback("flash", function()
	{
	    var flexApp = parent.FABridge.flash.root();
	    
	    // ---------------------------------------------------------------
	    // Register event handler(s)
	    // ---------------------------------------------------------------
	    flexApp.addEventListener("ResizeFrameEvent", function(event) 
                  {resizeFrame(event.getWidth()-self.offset,
                                    event.getHeight()-self.offset)});
	});
}

Where ‘offset’ is a value which is different for each browser:


// Offset from the edge of the frame. Is more for IE than other browsers.
if (this.IS_IE)
{
   this.offset = 35;
}
else
{
    this.offset = 20;
}

3) You have an enclosing ‘div’ into which your html content is placed and it gets resized by a javscript function.

The javascript resize function takes the width and height and applies it to your target div (in my case it’s called “map)


resizeFrame = function(width, height)
{
    try
    {
        // Resize the frame
    	var mapDiv = document.getElementById("map");
    	mapDiv.style.width = width+"px";
    	mapDiv.style.height = height+"px";
    }
    catch(e)
    {
    	alert(e);
    }
}	

Phew..bit of a palaver and no mistake but it works a treat.

I can’t release the flexTraffic code as great big chunks of it are used in a commercial application particularly the map bit. Since this issue is causing people grief I will try and create a simple demo.

Comments

9 Responses to “Flex: IFrame Resizing”

  1. Larry Hughes on January 19th, 2008 6:06 pm

    Thanks so much! I finally got the resizing to work!

    I do notice another issue though, although I’m not sure if its strictly a browser issue. Using IE7, I did what you said about modal TitleWindows… when I popup up this window, I set the IFrame’s visibility to false which works well. The contents of my popup TitleWindow is like a form (registration form). It scrolls vertically. When the popup window first displays, everything looks normal. Once you start scrolling down (or back up), all of the fields seem to not refresh appropriately in the TitleWindow… making some fields disappear while others all jumbled up. It seems to only happen with IE7 (FireFox works just fine). Is this a known issue with IFrame and IE7? Just wondering if you knew anything about this and if so, I would I fix it.

    Thanks again for all your help!

    -Larry

  2. Administrator on January 21st, 2008 10:57 am

    Larry, I am glad you got this working. I didn’t know about the IE7 issue. Off the top of my head I guess you could sub-class the TitleWindow and try catching the scroll events and calling invalidateDisplayList to force a redraw. Is the contents of your TitleWindow a Flex form or another iframe?

  3. Larry Hughes on January 21st, 2008 3:41 pm

    I’ll give your suggestion a shot. The contents in the TitleWindow is just a Flex Form (not an IFrame). I was hoping you already knew an issue like this existed =(

  4. Larry Hughes on January 22nd, 2008 10:10 pm

    Another update: I’ve tried what you’ve suggested but instead of subclassing I just added an event listener to my title window listening for ScrollEvent.SCROLL, passing in a handler function which just calls invalidateDisplayList(). Not sure if this is the same as subclassing… but anyhow nothing seemed to work (same problem). Any other ideas? Thanks again!

    -Larry

  5. Administrator on January 23rd, 2008 10:19 am

    Larry, daft question I know, but did you breakpoint the scroll handler and check it was definitely getting called? This does sound like a bug of some kind. I’m clutching at straws here but how about:

    – put your iframe inside a viewstack along with a panel.
    – instead of making the iframe invisible when you open your title window you could set the viewstack to display the panel instead (the iframe can detect it has it’s not visible) and then switch back to the iframe when the titlewindow is closed.

    Al.

  6. Larry Hughes on January 25th, 2008 9:03 pm

    Hi,

    I just figured out what the problem is: wmode=opaque. Its not an explicit IFrame issue, just the mode to display the IFrame appropriately. Hence I will try to find a workaround to this (unless you have an idea). Seems to only affect ie7. Thanks for your help!

    -Larry

  7. Larry Hughes on January 25th, 2008 10:20 pm

    Ok,

    Well I hate doing this but what I did was edit the html template such that if it sees that the browser is IE, run the script without wmode/opaque, else run it with wmode/opaque. I’m not sure how to do this in the noscript tag (checking if browser is IE). Anyway, the wmode/opaque works perfectly in FireFox. Taking it out would make my Iframe content disappear. For IE, wmode/opaque works ok until I open popup windows (non-iframe) and then need to scroll the window. Here IE can’t seem to render the content fast enough such that the widgets are drawn all wrong.

    Unless someone knows what this wmode/opaque issue is with IE7 (and probably IE6 as well) for scrolling in popup windows, I’ll probably have to use this hack for now. Anyone have any ideas? Thanks!

    -Larry

  8. Administrator on January 25th, 2008 10:45 pm

    Interesting result Larry. Thanks for your input. I use the IFrame in a very specific way so it’s good to get some feedback on any potential problems. Thanks again.

  9. Larry Hughes on January 25th, 2008 11:07 pm

    I guess a good way for you to test is to popup a modal titlewindow on top of one of your apps, e.g. FlexTraffic, using IE. Make sure that their is content in this popup window such that you will need to scroll vertically. If you do this in IE, you will definitely see what I’m talking about (assuming you use wmode=opaque).

    -Larry

Leave a Reply