Adding HTML content to SWF-based applications
Back to: Apollo Documentation home page
The HTMLControl class defines a display object that can display HTML content in a SWF file.
For example, the following code loads a URL into an HTMLControl object, and sets the object as a child of a Sprite object:
var container:Sprite;
var html:HTMLControl = new HTMLControl;
html.width = 400;
html.height = 600;
var urlReq:URLRequest = new URLRequest("http://www.adobe.com/");
html.load(urlReq);
container.addChild(html);
Note: In the Flex framework, only classes that extend the UIComponent class can be added as children of a Flex Container. For this reason, you cannot directly add an HTMLControl as a child of a Flex Container; however you can use the Flex HTML control, you can build a custom class that extends UIComponent and contains an HTMLControl as a child of the UIComponent, or you can add the HTMLControl as a child of a UIComponent and add the UIComponent to the Flex container. For details, see Wrapping an HTMLControl in a UIComponent.
The HTMLControl has full support for all standard HTML tags, JavaScript, images, and CSS.
Note: The TextField class can also render HTML text, but its capabilities are limited. For example, a TextField object can only render a subset of HTML tags, a TextField object cannot process JavaScript, and there are many other limitations to the capabilities of the TextField HTML capabilities. The limited HTML capabilities of the TextField class are imposed because of the need for Flash Player to be small in size. (The HTMLControl included in Apollo is not available in Flash Player.)
The Apollo HTMLControl feature is built on the WebKit open source web browser engine (http://webkit.org/).
Loading HTML content from a URL
The load() method of an HTMLControl object loads content into the HTMLControl object from a URL defined by a URLRequest object:
var html:HTMLControl;
var urlReq:URLRequest = new URLRequest("http://www.adobe.com/");
html.load(urlReq);
URLRequest objects in Apollo
You can use any of the following URL schemes in defining the url property of a URLRequest object:
- file — Use this to specify a path relative to the root of the file system. For example:
- file:///c:/Apollo Test/test.txt
- app-resource — Use this to specify a path relative to the root directory of the installed application (the directory that contains the application.xml file for the installed application). For example, the following path points to a test.log file in a logs subdirectory of the directory of the installed application:
- app-resource:/logs/test.log
- app-storage — Use this to specify a path relative to the application store directory. For each installed application, Apollo defines a unique application store directory, which is a useful place to store data specific to that application. For example, the following path points to a prefs.xml file in a settings subdirectory of the application store directory:
- app-storage:/settings/prefs.xml
- http</tt> — A standard HTTP request:
- http://www.adobe.com
- https</tt> — A standard HTTPS request:
- https://secure.example.com
In HTML content running in Apollo, you can also use each of these URL schemes in defining src attributes for img, frame, iframe, and script tags, in the href attribute of a link tag, and anyplace you can provide a URL.
Note: You can access the location of the app-resource directory using flash.filesystem.File.appResourceDirectory in ActionScript or runtime.flash.filesystem.File.appResourceDirectory in JavaScript. You can access the location of the app-storage directory using flash.filesystem.File.appStorageDirectory in ActionScript or runtime.flash.filesystem.File.appStorageDirectory in JavaScript.
In SWF content running in Flash Player (not in the Apollo runtime), only the http: and https: URL schemes are supported.
You can use a URLRequest object that uses any of these URL schemes to define the URL request for a number of different objects, such as an HTMLControl object, a File object, a Loader object, a URLStream object, or a Sound object.
Loading HTML content from a string
The loadString() method of an HTMLControl object loads a string of HTML content into the HTMLControl object:
var html:HTMLControl; var htmlStr:String = "<html><body>Hello <b>world</b>.</body></html>"; html.loadString(htmlStr);
You may consider using the XML class to represent large amounts of HTML data, and then use the toXMLString() method of the XML object to convert the data to a string:
var xHTML:XML =
<html>
<head>
<style>
tr { font-family: Verdana }
</style>
<script>
function init() {
alert("Document loaded.");
}
</script>
</head onLoad="init()">
<body>
<table>
<tr>
<th>HTMLControl feature</th>
<th>Description</th>
<tr>
<td>Full HTML tag support</td>
<td>Including tables, etc.</td>
</tr>
<tr>
<td>CSS support</td>
<td>As shown here</td>
</tr>
<tr>
<td>JavaScript support</td>
<td>Including cross-script communication to ActionScript.</td>
</tr>
</table>
</body>
</html>;
var htmlStr:String = xHTML.toXMLString();
var html:HTMLControl = new HTMLControl();;
html.width = 400;
html.height = 200;
addChild(html);
html.loadString(htmlStr);
Note: In the XML object used to contain the HTML code, use the { character code in place of the "{" character. The MXML compiler does not correctly interpret a "{" character in this context.
Display properties of HTMLControl objects
The HTMLControl class is a subclass of the Sprite class, and as such, you can set and get any of the properties in that class. For example, you can set the height, width, and position. You can also set properties that control more advance visual effects, such as the filters array:
var html:HTMLControl = new HTMLControl();
var urlReq:URLRequest = new URLRequest("http://www.adobe.com/");
html.load(urlReq);
html.width = 800;
html.height = 600;
var blur:BlurFilter = new BlurFilter(8);
var filters:Array = [blur];
html.filters = filters;
Note that an HTMLControl object's width and height properties are both set to 0 by default. You will want to set these before adding an HTMLControl object to the stage.
Scrolling HTML content
The HTMLControl class includes the following properties that let you control the scrolling of HTML content.
| Property | Description |
|---|---|
| htmlHeight | The height, in pixels, of the HTML content. |
| htmlWidth | The width, in pixels, of the HTML content. |
| scrollH | The horizonal scroll position of the HTML content within the HTMLControl object. |
| scrollV | The vertical scroll position of the HTML content within the HTMLControl object. |
The HTMLControl does not include horizontal and vertical scroll bars. You can implement these in ActionScript (or by using a Flex component if you are developing with the Flex framework).
Events dispatched by an HTMLControl object
A HTML control only dispatches the following events:
- domInitialize Dispatched when the HTML document is created.
- complete Dispatched when the HTML DOM has been created in response to a load operation.
- htmlBoundsChanged Dispatched when one or both of the htmlWidth and htmlHeight properties have changed.
- locationChange Dispatched when the location property of the HTMLControl has changed
- scroll Dispatched anytime the HTML engine changes the scroll position. This can be due to navigation to # links in the page or to JavaScript calls to the window.scrollTo() method. Typing in a text input or text area can also cause a scroll.
- uncaughtJavaScriptException Dispatched when an uncaught JavaScript exception occurs in the HTMLControl.
You can also register an ActionScript function for a JavaScript event (such as onLoad or onClick), as in the following:
var html:HTMLControl = new HTMLControl( );
var xhtml:XML =
<html>
<body>
<a id="link1" href="#">Test</a>
</body>
</html>;
html.addEventListener(Event.COMPLETE, completeHandler);
html.loadString(xhtml.toXMLString( ));
function completeHandler(event:Event):void {
var link:Object = html.window.document.getElementById("link1");
link.onclick = clickHandler;
}
function clickHandler(event:Object):void {
trace("clicked");
}
Accessing the HTML DOM and JavaScript in an HTML page
Once the HTML page is loaded, and the HTMLControl object dispatches the domInitialize event, you can access the objects in the HTML DOM (document object model) for the page. This includes display elements (such as div and p objects in the page) as well as JavaScript variables and functions. If possible, wait for the complete event before accessing the HTML DOM.
For example, consider the following HTML page:
<html>
<script>
foo = 333;
function test() {
return "OK.";
}
</script>
<body>
<p id="p1">Hi.</p>
</body>
</html>
This simple HTML page has a JavaScript variable named "foo" and a JavaScript function named "test()". Both of these are properties of the window object of the page (the page's DOM). Also, the window.document object includes a named P element (with the ID "p1"), which you can access using the getElementById() method. Once the the page is loaded (when the HTMLControl object dispatches the complete event), you can access each of these from ActionScript, as shown in the following ActionScript code:
var html:HTMLControl = new HTMLControl();
html.width = 300;
html.height = 300;
html.addEventListener(Event.COMPLETE, completeHandler);
var xhtml:XML =
<html>
<script>
foo = 333;
function test() {
return "OK.";
}
</script>
<body>
<p id="p1">Hi.
</body>
</html>;
html.loadString(xhtml.toString());
function completeHandler(e:Event):void {
trace(html.window.foo); // 333
trace(html.window.document.getElementById("p1").innerHTML); // Hi.
trace(html.window.test()); // OK.
}
To access the content of an HTML element, use the innerHTML property. For example, the previous code uses html.window.document.getElementById("p1").innerHTML to get the contents of the HTML element named "p1".
You can also set properties of the HTML page from ActionScript. For example, the following sets the contents of the p1 element on the page and it sets the value of the foo JavaScript variable on the page:
html.window.document.getElementById("p1").innerHTML = "eeee";
html.window.foo = 66;
Converting JavaScriptObject objects to the appropriate ActionScript type
From ActionScript, all DOM objects are of the ActionScript type JavaScriptObject, except for JavaScript functions, which are of type JavaScriptFunction. The JavaScriptObject and JavaScriptFunction class are defined in the flash.html package.
This is true for both JavaScript objects declared in a JavaScript script and other DOM elements (such as a P element of the window.document object).
For example, consider the following HTML:
<html>
<script>
var a = ['foo', 'bar', 33];
function insertIntoA(value) {
a = a.splice(0, 0, value);
};
</script>
<body>
<p id='p1'>Buenos días.
</body>
</html>
When you load this content into an HTMLControl object, the a property (defined in the JavaScript script) and the p element (of the document) are both of type JavaScriptObject (when accessed from ActionScript):
var html:HTMLControl = new HTMLControl();
var urlReq:URLRequest = new URLRequest("test.html");
html.load(urlReq);
html.addEventListener(Event.COMPLETE, htmlLoaded)
function htmlLoaded(e:Event):void {
trace(html.window.a is JavaScriptObject); // true
trace(html.window.insertIntoA is JavaScriptFunction); // true
trace(html.window.document.getElementById('p1') is JavaScriptObject); // true
}
Consider a JavaScript array, such as the a JavaScript property in the example HTML. If you tried to assign its contents to an ActionScript object of type Array, using the following code, an error would be thrown:
var asArray:Array = html.window.a;
The error results because the runtime cannot convert a JavaScriptObject to Array object. However, you can iterate through the members of the JavaScript object and pass them as properties of the ActionScript object:
var asArray:Array = new Array();
var jsArray = html.window.a;
for(var prop:Object in jsArray) {
asArray[prop] = jsArray[prop];
}
trace(asArray[1]); // bar
Manipulating an HTML stylesheet from ActionScript
Once the HTMLControl object has dispatched the domInitialize event (or better still, the complete event), you can examine and manipulate CSS styles in a page.
For example, consider the following simple HTML document:
<html>
<style>
.style1A { font-family:Arial; font-size:12px }
.style1B { font-family:Arial; font-size:24px }
</style>
<style>
.style2 { font-family:Arial; font-size:12px }
</style>
<body>
<p class="style1A">
Style 1A
</p>
<p class="style1B">
Style 1B
</p>
<p class="style2">
Style 2
</p>
</body>
</html>
After an HTMLControl object loads this content, you can manipulate the CSS styles in the page via the cssRules array of the window.document.styleSheets array, as shown here:
var html:HTMLControl = new HTMLControl( );
var urlReq:URLRequest = new URLRequest("test.html");
html.load(urlReq);
html.addEventListener(Event.COMPLETE, completeHandler);
function completeHandler(event:Event):void {
var styleSheet0:Object = html.window.document.styleSheets[0];
styleSheet0.cssRules[0].style.fontSize = "32px";
styleSheet0.cssRules[1].style.color = "#FF0000";
var styleSheet1:Object = html.window.document.styleSheets[1];
styleSheet1.cssRules[0].style.color = "blue";
styleSheet1.cssRules[0].style.font-family = "Monaco";
}
This code adjusts the CSS styles so that the resulting HTML document appears like the following:
- Style 1A
- Style 1B
- Style 2
Registering ActionScript functions to respond to JavaScript events
You can register ActionScript functions to respond to JavaScript events. For example, consider the following HTML content:
<html>
<body>
<a href="#" id="testLink">Click me.</a>
</html>
You can register an ActionScript function as a handler for any event in the page. For example, the following code adds the clickHandler() function as the listener for the onclick event of the testLink element in the HTML page:
var html:HTMLControl = new HTMLControl( );
var urlReq:URLRequest = new URLRequest("test.html");
html.load(urlReq);
html.addEventListener(Event.COMPLETE, completeHandler);
function completeHandler(event:Event):void {
html.window.document.getElementById("testLink").onclick = clickHandler;
}
function clickHandler():void {
trace("You clicked it!");
}
Note: It is good practice to wait for the HTMLControl to dispatches the complete event before adding these event listeners, as shown in the previous example.
Responding to uncaught JavaScript exceptions in ActionScript
Consider the following HTML:
<html>
<head>
<script>
function throwError() {
var x = 400 * melbaToast;
}
</script>
</head>
<body>
<a href="#" onclick="throwError()">Click me.</a>
</html>
It contains a JavaScript function, throwError(), that references an unknown object, melbaToast:
var x = 400 * melbaToast;
When a JavaScript operation encounters an illegal operation, the HTMLControl object dispatches an HTMLUncaughtJavaScriptExceptionEvent event. You can register an ActionScript method to listen for this event, as in the following code:
var html:HTMLControl = new HTMLControl();
var urlReq:URLRequest = new URLRequest("test.html");
html.load(urlReq);
html.width = container.width;
html.height = container.height;
container.addChild(html);
html.addEventListener(HTMLUncaughtJavaScriptExceptionEvent.UNCAUGHT_JAVASCRIPT_EXCEPTION,
htmlErrorHandler);
function htmlErrorHandler(event:HTMLUncaughtJavaScriptExceptionEvent):void
{
trace("exceptionValue:", event.exceptionValue)
for (var i:uint = 0; i < event.stackTrace.length; i++)
{
trace("___________________");
trace("sourceURL:", event.stackTrace[i].sourceURL);
trace("line:", event.stackTrace[i].line);
trace("function:", event.stackTrace[i].functionName);
}
}
In this example, the htmlErrorHandler() event handler outputs the value of the exceptionValue of the HTMLUncaughtJavaScriptExceptionEvent object. It also outputs the properties of each object in the stackTrace array:
exceptionValue: ReferenceError: Can't find variable: melbaToast ___________________ sourceURL: app-resource:/test.html line: 5 function: throwError ___________________ sourceURL: app-resource:/test.html line: 10 function: onclick
Accessing the Apollo runtime classes and functions from JavaScript
JavaScript can call classes and methods in the Apollo runtime. This is done using a JavaScript object named runtime, which is available to any JavaScript code loaded in the Apollo runtime. However, to allow JavaScript to access the Apollo runtime classes, you must set the exposeRuntime property of the HTMLControl object to true:
var html:HTMLControl = new HTMLControl( ); html.exposeRuntime = true;
For example, consider an HTML document (test.html) with the following content, which calls the runtime trace() function:
<html>
<body>
<a onClick="runtime.trace('Test clicked.')" href="#">Test</a>
</body>
</html>
The following ActionScript loads the file into an HTMLControl and sets the exposeRuntime property to true:
var html:HTMLControl = new HTMLControl( );
html.exposeRuntime = true;
var url:URLRequest = new URLRequest("test.html");
html.load(url);
If you use the loadString() method, content is loaded synchronously, so be sure to set exposeRuntime prior to calling loadString(), as in the following:
html.exposeRuntime = true; html.loadString(xhtml.toXMLString( ));
For more information, see the Calling Apollo runtime classes topic in the About HTML-based applications section of this documentation.
Making objects in the container display object available to JavaScript
JavaScript in the HTML page loaded by an HTMLCon