Handling HTML-related events in AIR

Adobe AIR 1.0 and later

An event-handling system allows programmers to respond to user input and system events in a convenient way. The Adobe® AIR® event model is not only convenient, but also standards-compliant. Based on the Document Object Model (DOM) Level 3 Events Specification, an industry-standard event-handling architecture, the event model provides a powerful, yet intuitive, event-handling tool for programmers.

HTMLLoader events

An HTMLLoader object dispatches the following Adobe® ActionScript® 3.0 events:

Event

Description

htmlDOMInitialize

Dispatched when the HTML document is created, but before any scripts are parsed or DOM nodes are added to the page.

complete

Dispatched when the HTML DOM has been created in response to a load operation, immediately after the onload event in the HTML page.

htmlBoundsChanged

Dispatched when one or both of the contentWidth and contentHeight properties have changed.

locationChange

Dispatched when the location property of the HTMLLoader has changed.

locationChanging

Dispatched before the location of the HTMLLoader changes because of user navigation, a JavaScript call, or a redirect. The locationChanging event is not dispatched when you call the load() , loadString() , reload() , historyGo() , historyForward() , or historyBack() methods.

Calling the preventDefault() method of the dispatched event object cancels navigation.

If a link is opened in the system browser, a locationChanging event is not dispatched since the HTMLLoader does not change location.

scroll

Dispatched anytime the HTML engine changes the scroll position. Scroll events can be because of navigation to anchor links ( # links) in the page or because of calls to the window.scrollTo() method. Entering text in a text input or text area can also cause a scroll event.

uncaughtScriptException

Dispatched when a JavaScript exception occurs in the HTMLLoader and the exception is not caught in JavaScript code.

How AIR class-event handling differs from other event handling in the HTML DOM

The HTML DOM provides a few different ways to handle events:

  • Defining an on event handler within an HTML element opening tag, as in:

    <div id="myDiv" onclick="myHandler()">
  • Callback function properties, such as:

    document.getElementById("myDiv").onclick 
  • Event listeners that you register using the addEventListener() method, as in:

    document.getElementById("myDiv").addEventLister("click", clickHandler)

However, since runtime objects do not appear in the DOM, you can only add event listeners by calling the addEventListener() method of an AIR object.

As in JavaScript, events dispatched by AIR objects can be associated with default behaviors. (A default behavior is an action that AIR executes as the normal consequence of certain events.)

The event objects dispatched by runtime objects are an instance of the Event class or one of its subclasses. An event object not only stores information about a specific event, but also contains methods that facilitate manipulation of the event object. For example, when AIR detects an I/O error event when reading a file asynchronously, it creates an event object (an instance of the IOErrorEvent class) to represent that particular I/O error event.

Any time you write event handler code, it follows the same basic structure:

function eventResponse(eventObject) 
{ 
    // Actions performed in response to the event go here. 
} 
 
eventTarget.addEventListener(EventType.EVENT_NAME, eventResponse);

This code does two things. First, it defines a handler function, which is the way to specify the actions to be performed in response to the event. Next, it calls the addEventListener() method of the source object, in essence subscribing the function to the specified event so that when the event happens, the handler actions are carried out. When the event actually happens, the event target checks its list of all the functions and methods that are registered with event listeners. It then calls each one in turn, passing the event object as a parameter.

Default behaviors

Developers are usually responsible for writing code that responds to events. In some cases, however, a behavior is so commonly associated with an event that AIR automatically executes the behavior unless the developer adds code to cancel it. Because AIR automatically exhibits the behavior, such behaviors are called default behaviors.

For example, when a user clicks the close box of a window of an application, the expectation that the window will close is so common that the behavior is built into AIR. If you do not want this default behavior to occur, you can cancel it using the event-handling system. When a user clicks the close box of a window, the NativeWindow object that represents the window dispatches a closing event. To prevent the runtime from closing the window, you must call the preventDefault() method of the dispatched event object.

Not all default behaviors can be prevented. For example, the runtime generates an OutputProgressEvent object as a FileStream object writes data to a file. The default behavior, which cannot be prevented, is that the content of the file is updated with the new data.

Many types of event objects do not have associated default behaviors. For example, a Sound object dispatches an id3 event when enough data from an MP3 file is read to provide ID3 information, but there is no default behavior associated with it. The API documentation for the Event class and its subclasses lists each type of event and describes any associated default behavior, and whether that behavior can be prevented.

Note: Default behaviors are associated only with event objects dispatched by the runtime directly, and do not exist for event objects dispatched programmatically through JavaScript. For example, you can use the methods of the EventDispatcher class to dispatch an event object, but dispatching the event does not trigger the default behavior.

The event flow

SWF file content running in AIR uses the ActionScript 3.0 display list architecture to display visual content. The ActionScript 3.0 display list provides a parent-child relationship for content, and events (such as mouse-click events) in SWF file content that propagates between parent and child display objects. The HTML DOM has its own, separate event flow that traverses only the DOM elements. When writing HTML-based applications for AIR, you primarily use the HTML DOM instead of the ActionScript 3.0 display list, so you can generally disregard the information on event phases that appears in the AIR reference documentation.

Adobe AIR event objects

Event objects serve two main purposes in the event-handling system. First, event objects represent actual events by storing information about specific events in a set of properties. Second, event objects contain a set of methods that allow you to manipulate event objects and affect the behavior of the event-handling system.

The AIR API defines an Event class that serves as the base class for all event objects dispatched by the AIR API classes. The Event class defines a fundamental set of properties and methods that are common to all event objects.

To use Event objects, it’s important to first understand the Event class properties and methods and why subclasses of the Event class exist.

Understanding Event class properties

The Event class defines several read-only properties and constants that provide important information about an event. The following are especially important:

  • Event.type describes the type of event that an event object represents.

  • Event.cancelable is a Boolean value that reports whether the default behavior associated with the event, if any, can be canceled.

  • Event flow information is contained in the remaining properties, and is only of interest when using ActionScript 3.0 in SWF content in AIR.

Event object types

Every event object has an associated event type. Event types are stored in the Event.type property as string values. It is useful to know the type of an event object so that your code can distinguish objects of different types from one another. For example, the following code registers a fileReadHandler() listener function to respond to a complete event dispatched by myFileStream :

myFileStream.addEventListener(Event.COMPLETE, fileReadHandler);

The AIR Event class defines many class constants, such as COMPLETE , CLOSING , and ID3 , to represent the types of events dispatched by runtime objects. These constants are listed in the Event class page of the Adobe AIR API Reference for HTML Developers .

Event constants provide an easy way to refer to specific event types. Using a constant instead of the string value helps you identify typographical errors more quickly. If you misspell a constant name in your code, the JavaScript parser will catch the mistake. If you instead misspell an event string, the event handler will be registered for a type of event that will never be dispatched. Thus, when adding an event listener, it is a better practice to use the following code:

myFileStream.addEventListener(Event.COMPLETE, htmlRenderHandler);

rather than:

myFileStream.addEventListener("complete", htmlRenderHandler);

Default behavior information

Your code can check whether the default behavior for any given event object can be prevented by accessing the cancelable property. The cancelable property holds a Boolean value that indicates whether a default behavior can be prevented. You can prevent, or cancel, the default behavior associated with a small number of events using the preventDefault() method. For more information, see Canceling default event behavior .

Understanding Event class methods

There are three categories of Event class methods:

  • Utility methods, which can create copies of an event object or convert it to a string.

  • Event flow methods, which remove event objects from the event flow (primarily of use when using ActionScript 3.0 in SWF content for the runtime—see The event flow ).

  • Default behavior methods, which prevent default behavior or check whether it has been prevented.

Event class utility methods

The Event class has two utility methods. The clone() method allows you to create copies of an event object. The toString() method allows you to generate a string representation of the properties of an event object along with their values.

Canceling default event behavior

The two methods that pertain to canceling default behavior are the preventDefault() method and the isDefaultPrevented() method. Call the preventDefault() method to cancel the default behavior associated with an event. Check whether preventDefault() has already been called on an event object, with the isDefaultPrevented() method.

The preventDefault() method works only if the event’s default behavior can be canceled. You can check whether an event has behavior that can be canceled by referring to the API documentation, or by examining the cancelable property of the event object.

Canceling the default behavior has no effect on the progress of an event object through the event flow. Use the event flow methods of the Event class to remove an event object from the event flow.

Subclasses of the Event class

For many events, the common set of properties defined in the Event class is sufficient. Representing other events, however, requires properties not available in the Event class. For these events, the AIR API defines several subclasses of the Event class.

Each subclass provides additional properties and event types that are unique to that category of events. For example, events related to mouse input provide properties describing the mouse location when the event occurred. Likewise, the InvokeEvent class adds properties containing the file path of the invoking file and any arguments passed as parameters in the command-line invocation.

An Event subclass frequently defines additional constants to represent the event types that are associated with the subclass. For example, the FileListEvent class defines constants for the directoryListing and selectMultiple event types.

Handling runtime events with JavaScript

The runtime classes support adding event handlers with the addEventListener() method. To add a handler function for an event, call the addEventListener() method of the object that dispatches the event, providing the event type and the handling function. For example, to listen for the closing event dispatched when a user clicks the window close button on the title bar, use the following statement:

window.nativeWindow.addEventListener(air.NativeWindow.CLOSING, handleWindowClosing);

The type parameter of the addEventListener() method is a string, but the AIR APIs define constants for all runtime event types. Using these constants can help pinpoint typographic errors entered in the type parameter more quickly than using the string version.

Creating an event handler function

The following code creates a simple HTML file that displays information about the position of the main window. A handler function named moveHandler() , listens for a move event (defined by the NativeWindowBoundsEvent class) of the main window.

<html> 
    <script src="AIRAliases.js" /> 
    <script> 
        function init() { 
            writeValues(); 
            window.nativeWindow.addEventListener(air.NativeWindowBoundsEvent.MOVE, 
                                                     moveHandler); 
        } 
        function writeValues() { 
            document.getElementById("xText").value = window.nativeWindow.x; 
            document.getElementById("yText").value = window.nativeWindow.y; 
        } 
        function moveHandler(event) { 
            air.trace(event.type); // move 
            writeValues(); 
        } 
    </script> 
    <body onload="init()" /> 
        <table> 
            <tr> 
                <td>Window X:</td> 
                <td><textarea id="xText"></textarea></td> 
            </tr> 
            <tr> 
                <td>Window Y:</td> 
                <td><textarea id="yText"></textarea></td> 
            </tr> 
        </table> 
    </body> 
</html>

When a user moves the window, the textarea elements display the updated X and Y positions of the window:

Notice that the event object is passed as an argument to the moveHandler() method. The event parameter allows your handler function to examine the event object. In this example, you use the event object's type property to report that the event is a move event.

Note: Do not use parentheses when you specify the listener parameter. For example, the moveHandler() function is specified without parentheses in the following call to the addEventListener() method: addEventListener(Event.MOVE, moveHandler) .

The addEventListener() method has three other parameters, described in the Adobe AIR API Reference for HTML Developers ; these parameters are useCapture , priority , and useWeakReference .

Removing event listeners

You can use the removeEventListener() method to remove an event listener that you no longer need. It is a good idea to remove any listeners that will no longer be used. Required parameters include the eventName and listener parameters, which are the same as the required parameters for the addEventListener() method.

Removing event listeners in HTML pages that navigate

When HTML content navigates, or when HTML content is discarded because a window that contains it is closed, the event listeners that reference objects on the unloaded page are not automatically removed. When an object dispatches an event to a handler that has already been unloaded, you see the following error message: “The application attempted to reference a JavaScript object in an HTML page that is no longer loaded.”

To avoid this error, remove JavaScript event listeners in an HTML page before it goes away. In the case of page navigation (within an HTMLLoader object), remove the event listener during the unload event of the window object.

For example, the following JavaScript code removes an event listener for an uncaughtScriptException event:

window.onunload = cleanup; 
window.htmlLoader.addEventListener('uncaughtScriptException', uncaughtScriptException); 
function cleanup() 
{ 
    window.htmlLoader.removeEventListener('uncaughtScriptException', 
                            uncaughtScriptExceptionHandler); 
}

To prevent the error from occurring when closing windows that contain HTML content, call a cleanup function in response to the closing event of the NativeWindow object ( window.nativeWindow ). For example, the following JavaScript code removes an event listener for an uncaughtScriptException event:

window.nativeWindow.addEventListener(air.Event.CLOSING, cleanup); 
function cleanup() 
{ 
    window.htmlLoader.removeEventListener('uncaughtScriptException', 
                            uncaughtScriptExceptionHandler); 
}

You can also prevent this error from occurring by removing an event listener as soon as it runs (if the event only needs to be handled once). For example, the following JavaScript code creates an html window by calling the createRootWindow() method of the HTMLLoader class and adds an event listener for the complete event. When the complete event handler is called, it removes its own event listener using the removeEventListener() function:

var html = runtime.flash.html.HTMLLoader.createRootWindow(true); 
html.addEventListener('complete', htmlCompleteListener); 
function htmlCompleteListener() 
{ 
    html.removeEventListener(complete, arguments.callee) 
    // handler code.. 
} 
html.load(new runtime.flash.net.URLRequest("second.html"));

Removing unneeded event listeners also allows the system garbage collector to reclaim any memory associated with those listeners.

Checking for existing event listeners

The hasEventListener() method lets you check for the existence of an event listener on an object.

Error events without listeners

Exceptions, rather than events, are the primary mechanism for error handling in the runtime classes. However, exception handling does not work for asynchronous operations such as loading files. If an error occurs during an asynchronous operation, the runtime dispatches an error event object. If you do not create a listener for the error event, the AIR Debug Launcher presents a dialog box with information about the error.

Most error events are based on the ErrorEvent class, and have a property named text that is used to store a descriptive error message. An exception is the StatusEvent class, which has a level property instead of a text property. When the value of the level property is error , the StatusEvent is considered to be an error event.

An error event does not cause an application to stop executing. It manifests only as a dialog box on the AIR Debug Launcher. It does not manifest at all in the installed AIR application running in the runtime.

// Ethnio survey code removed