Flex IFrame – Web browser in flash (update)
You can not have a web browser inside your web flash applications right? Well, you can! This solution uses html iframe to generate fake build in browser. So the behaviour of the browser in flash is the same as the one you are previewing this flash in (it is the same one). The best part of it is, you can manipulate with the position and size of this browser directly from flash. sk.yoz.html.IFrame solution was inspired by Alistair Rutherford, www.netthreads.co.uk.
- sk.yoz.html.IFrame
- FlexIFrame.js
- Application
- Application html
Flex Iframe application
Core of this thing is sk.yoz.html.IFrame class. It extends Canvas that is used to inherit properties and methods for positioning and sizing. There is one in order to make it work – every IFrame element must have id!
package sk.yoz.html
{
import flash.events.Event;
import flash.external.ExternalInterface;
import flash.geom.Point;
import mx.containers.Canvas;
public class IFrame extends Canvas
{
public var methodResize:String = "FlexIFrame.resize";
public var methodMove:String = "FlexIFrame.move";
public var methodNavigate:String = "FlexIFrame.navigate";
public var methodVisibility:String = "FlexIFrame.visibility";
public var positionChanged:Boolean = false;
public var sizeChanged:Boolean = false;
private var _autoResize:Boolean = false;
private var _url:String = '';
public function IFrame()
{
super();
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler)
}
override public function set id(value:String):void
{
super.id = value;
}
protected function addedToStageHandler(event:Event):void
{
positionChanged = true;
sizeChanged = true;
invalidateProperties();
}
public function set autoResize(value:Boolean):void
{
_autoResize = value;
if(value)
addEventListener(Event.RESIZE, autoResizeHandler);
else
removeEventListener(Event.RESIZE, autoResizeHandler);
}
public function get autoResize():Boolean
{
return _autoResize;
}
protected function autoResizeHandler(event:Event):void
{
positionChanged = true;
sizeChanged = true;
invalidateProperties();
}
override protected function commitProperties():void
{
super.commitProperties();
if(positionChanged)
{
var point:Point = localToGlobal(new Point(0, 0));
callJS(methodMove, point.x, point.y);
positionChanged = false;
}
if(sizeChanged)
{
callJS(methodResize, width, height);
sizeChanged = false;
}
}
public function set url(value:String):void
{
_url = value;
callJS(methodNavigate, value)
}
public function get url():String
{
return _url;
}
protected function callJS(method:String, ... values):void
{
if(!id)
throw new Error("IFrame id is not defined");
var args:Array = [method, id];
try
{
ExternalInterface.call.apply(ExternalInterface, args.concat(values));
}
catch(error:Error)
{
trace(error.message);
}
}
override public function set visible(value:Boolean):void
{
super.visible = value;
callJS(methodVisibility, value);
}
override public function set width(value:Number):void
{
super.width = value;
callJS(methodResize, value, height);
}
override public function set height(value:Number):void
{
super.height = value;
callJS(methodResize, width, value);
}
override public function set x(value:Number):void
{
super.x = value;
var point:Point = localToGlobal(new Point(0, 0));
callJS(methodMove, point.x, point.y);
}
override public function set y(value:Number):void
{
super.y = value;
var point:Point = localToGlobal(new Point(0, 0));
callJS(methodMove, point.x, point.y);
}
}
}
FlexIFrame.js is JavaScript file. It uses your flex IFrame id from to create (html iframe) or use html element (any element) with the same id (id in flash = id in html). So you can use your prefabricated html elements (banners etc).
var FlexIFrame = {
get: function(id)
{
var iframe = document.getElementById(id);
if(!iframe)
return FlexIFrame.create(id);
return iframe;
},
create: function(id)
{
var iframe = document.createElement('iframe');
iframe.id = id;
iframe.frameborder = 0;
iframe.style.position = "absolute";
iframe.style.zIndex = 1;
iframe.style.border = "none";
document.body.insertBefore(iframe, document.body.firstChild);
return iframe;
},
resize: function(id, width, height)
{
var iframe = FlexIFrame.get(id);
iframe.style.width = width + "px";
iframe.style.height = height + "px";
},
move: function(id, x, y)
{
var iframe = FlexIFrame.get(id);
iframe.style.left = x + "px";
iframe.style.top = y + "px";
},
navigate: function(id, url)
{
var iframe = FlexIFrame.get(id);
iframe.src = url;
},
visibility: function(id, visible)
{
var iframe = FlexIFrame.get(id);
iframe.style.display = visible ? "block" : "none";
}
}
This is simple applicationion presenting draggable TitleWindow with “web browser” inside:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" applicationComplete="init()" xmlns:html="sk.yoz.html.*">
<mx:Script>
<![CDATA[
private function init():void
{
go();
}
private function go():void
{
iframe.url = iframeURL.text;
}
private function mouseDownHandler():void
{
container.startDrag();
container.addEventListener(Event.ENTER_FRAME, enterFrameDrag);
}
private function mouseUpHandler():void
{
container.stopDrag();
}
private function enterFrameDrag(event:Event):void
{
iframe.positionChanged = true;
iframe.invalidateProperties();
}
]]>
</mx:Script>
<mx:TitleWindow id="container" layout="vertical" width="300" height="300"
mouseDown="mouseDownHandler()" mouseUp="mouseUpHandler()" >
<mx:HBox width="100%">
<mx:TextInput id="iframeURL" text="http://blog.yoz.sk" width="100%"
enter="go()"/>
<mx:Button label="Go" click="go()"/>
</mx:HBox>
<html:IFrame width="100%" height="100%" id="iframe" autoResize="true"/>
</mx:TitleWindow>
</mx:Application>
Finally do not forget to add flexiframe.js into your .html file:
<html>
<head>
<script type="text/javascript" src="js/flexiframe.js"></script>
...
Update (Feb 8, 2010): flexiframe.js resize() method uses style property for width and height (instead of original html element width, height)

Hello from Russia!
Can I quote a post “No teme” in your blog with the link to you?
sure
[...] post connects my 3 previous posts: Flex IFrame – Web browser in flash, FacebookLogger and Facebook Extended Permissions With Authorization by Overriding Class in swc in [...]
[...] import flexiframe.js used for positioning html input on correct [...]
Hey Jozef.. yeap you are right! we can have HTML on our flash apps.. but the IFrame is the wors’t thing we can have in a Flex app, why? Because all PopUps will remain behind the IFrame, you have to implement workarounds like hiding the IFrame if a PopUp has to show, other little terrible thing, is that you have to relocate the IFrame if your browser is resize.
That’s why I’m against the IFrame.. so for everybody who reads this, if you don´t really have to render HTML in your app, don´t do it.
Hi Pedro, thanks for your comment. I think you misunderstood the whole example and aim of this Class. It does not mean that all your PopUps are gonna be raplaced by HTML iframe. HTML iframe only overlaps the sk.yoz.html.IFrame class! Its aim IS to show iframe positioned and sized over this element. There is no workaround needed for hidding etc. You can hide it using IFrame.visible = false. Yes, you are right that in specific case (when your flash app extends with browser resize), you need to call:
iframe.positionChanged = true;
iframe.sizeChanged = true;
iframe.invalidateProperties();
it is meant to be used that way
whats more, sk.yoz.html.IFrame, can be used for positioning any other html element, see some examples here:
http://blog.yoz.sk/2010/02/textinput-wmode-opaque-transparent-workaround/
http://blog.yoz.sk/2010/01/elegant-facebook-login-for-desktop-application/
hi..
im trying to do this a lot of time in my websites,
you can download rar file that include all works?
thanks
@bar just copy paste content of these 3 files + add .js line into your main html wrapper thats all
It works!
Thank you for this post. It helped me a lot.