处理 AIR 中与 HTML 相关的事件

Adobe AIR 1.0 和更高版本

利用事件处理系统,程序员可以十分方便地响应用户输入和系统事件。Adobe® AIR® 事件模型不仅方便,而且符合标准。事件模型基于文档对象模型 (DOM) 第 3 级事件规范,是业界标准的事件处理体系结构,为程序员提供了强大而直观的事件处理工具。

HTMLLoader 事件

HTMLLoader 对象调度以下 Adobe® ActionScript® 3.0 事件:

事件

说明

htmlDOMInitialize

在创建 HTML 文档时调度,调度时未分析任何脚本或未将 DOM 节点添加到页面。

complete

在为响应加载操作而创建 HTML DOM 后,紧接在 HTML 页面中的 onload 事件后调度。

htmlBoundsChanged

在 contentWidth 和/或 contentHeight 属性发生了变化时调度。

locationChange

在 HTMLLoader 的 location 属性发生了变化时调度。

locationChanging

由于用户导航、JavaScript 调用或重定向,在 HTMLLoader 的位置发生变化前调度。当您调用 load() 、 loadString() 、 reload() 、 historyGo() 、 historyForward() 或 historyBack() 方法时未调度 locationChanging 事件。

调用所调度事件对象的 preventDefault() 方法会取消导航。

如果系统浏览器中打开某个链接,则不会调度 locationChanging 事件,因为 HTMLLoader 不会改变位置。

scroll

只要 HTML 引擎更改滚动位置,便会调度此事件。Scroll 事件的引发可能是由于导航到页面中的锚记链接( # 链接),也可能是由于调用 window.scrollTo() 方法。在文本输入或文本区域中输入文本也可能会引发 scroll 事件。

uncaughtScriptException

当在 HTMLLoader 中发生 JavaScript 异常,并且在 JavaScript 代码中未捕获到该异常时调度。

您也可以为 JavaScript 事件(如 onClick )注册 ActionScript 函数。有关详细信息,请参阅 使用 ActionScript 处理 DOM 事件 。

使用 ActionScript 处理 DOM 事件

可以注册 ActionScript 函数以响应 JavaScript 事件。以下面的 HTML 内容为例:

<html> 
<body> 
    <a href="#" id="testLink">Click me.</a> 
</html>

您可以将 ActionScript 函数注册为页面中任何事件的处理函数。例如,下面的代码添加 clickHandler() 函数,将其作为 HTML 页面中 testLink 元素的 onclick 事件的侦听器:

var html:HTMLLoader = new HTMLLoader( ); 
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( event:Object ):void { 
    trace("Event of type: " + event.type ); 
}

调度的事件对象不属于类型 flash.events.Event,也不是 Event 的一个子类。 使用 Object 类为事件处理函数参数声明一个类型。

您也可以使用 addEventListener() 方法来注册这些事件。例如,您可以将上一示例中的 completeHandler() 方法替换为下面的代码:

function completeHandler(event:Event):void { 
    var testLink:Object = html.window.document.getElementById("testLink"); 
    testLink.addEventListener("click", clickHandler); 
}

当侦听器引用特定的 DOM 元素时,先等父级 HTMLLoader 调度 complete 事件之后再添加事件侦听器是个好习惯。HTML 页面通常会加载多个文件,HTML DOM 的构建在所有文件的加载和分析完成以前不会全部完成。HTMLLoader 会在所有元素都创建完毕后调度 complete 事件。

响应未捕获的 JavaScript 异常

以下面的 HTML 为例:

<html> 
<head> 
    <script> 
        function throwError() { 
            var x = 400 * melbaToast; 
        } 
    </script> 
</head> 
<body> 
    <a href="#" onclick="throwError()">Click me.</a> 
</html>

它包含 JavaScript 函数 throwError() ,该函数引用一个未知变量 melbaToast :

var x = 400 * melbaToast;

如果 JavaScript 操作遇到一个非法操作,这个非法操作在带有 try / catch 结构的 JavaScript 代码中没有捕获到,则包含相应页面的 HTMLLoader 对象就会调度 HTMLUncaughtScriptExceptionEvent 事件。您可以注册此事件的处理函数,如下面的代码所示:

var html:HTMLLoader = new HTMLLoader(); 
var urlReq:URLRequest = new URLRequest("test.html"); 
html.load(urlReq); 
html.width = container.width; 
html.height = container.height; 
container.addChild(html); 
html.addEventListener(HTMLUncaughtScriptExceptionEvent.UNCAUGHT_SCRIPT_EXCEPTION, 
                           htmlErrorHandler); 
function htmlErrorHandler(event:HTMLUncaughtJavaScriptExceptionEvent):void  
{ 
    event.preventDefault(); 
    trace("exceptionValue:", event.exceptionValue) 
    for (var i:int = 0; i < event.stackTrace.length; i++) 
    { 
        trace("sourceURL:", event.stackTrace[i].sourceURL); 
        trace("line:", event.stackTrace[i].line); 
        trace("function:", event.stackTrace[i].functionName); 
    } 
}

在 JavaScript 中,您可以使用 window.htmlLoader 属性处理同一事件:

<html> 
<head> 
<script language="javascript" type="text/javascript" src="AIRAliases.js"></script> 
 
    <script> 
        function throwError() { 
            var x = 400 * melbaToast; 
        } 
         
        function htmlErrorHandler(event) { 
            event.preventDefault(); 
            var message = "exceptionValue:" + event.exceptionValue + "\n"; 
            for (var i = 0; i < event.stackTrace.length; i++){ 
                message += "sourceURL:" + event.stackTrace[i].sourceURL +"\n"; 
                message += "line:" + event.stackTrace[i].line +"\n"; 
                message += "function:" + event.stackTrace[i].functionName + "\n"; 
            } 
            alert(message); 
        } 
         
        window.htmlLoader.addEventListener("uncaughtScriptException", htmlErrorHandler); 
    </script> 
</head> 
<body> 
    <a href="#" onclick="throwError()">Click me.</a> 
</html>

htmlErrorHandler() 事件处理函数取消事件的默认行为(即将 JavaScript 错误消息发送到 AIR trace 输出),然后生成自己的输出消息。它输出 HTMLUncaughtScriptExceptionEvent 对象的 exceptionValue 的值。它输出 stackTrace 数组中每个对象的属性:

exceptionValue: ReferenceError: Can't find variable: melbaToast 
sourceURL: app:/test.html 
line: 5 
function: throwError 
sourceURL: app:/test.html 
line: 10 
function: onclick

使用 JavaScript 处理运行时事件

运行时类支持使用 addEventListener() 方法添加事件处理函数。若要为某个事件添加处理函数,请调用调度该事件的对象的 addEventListener() 方法,同时提供事件类型和处理函数。例如,若要侦听用户单击标题栏上的窗口关闭按钮时调度的 closing 事件,请使用下面的语句:

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

创建事件处理函数

下面的代码创建一个简单的 HTML 文件,用于显示有关主窗口位置的信息。一个名为 moveHandler() 的处理函数侦听主窗口的 move 事件(由 NativeWindowBoundsEvent 类定义)。

<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>

当用户移动此窗口时,textarea 元素会显示此窗口的更新的 X 位置和 Y 位置:

请注意,事件对象作为实参传递给 moveHandler() 方法。利用 event 参数,处理函数可以检查事件对象。在此示例中,使用事件对象的 type 属性报告该事件为 move 事件。

删除事件侦听器

可以使用 removeEventListener() 方法删除不再需要的事件侦听器。建议删除将不再使用的所有侦听器。必需的参数包括 eventName 和 listener 参数,这些参数与 addEventListener() 方法的必需参数相同。

删除执行导航的 HTML 页面中的事件侦听器

当 HTML 内容进行导航时,或者因包含 HTML 内容的窗口关闭而丢弃这些 HTML 内容时,不会自动删除引用已卸载的页面中对象的事件侦听器。当对象向已卸载的处理函数调度事件时,会显示下面的错误消息:“应用程序尝试引用不再处于已加载状态的 HTML 页面中的 JavaScript 对象。”(The application attempted to reference a JavaScript object in an HTML page that is no longer loaded.)

为避免出现此错误,请在 HTML 页面退出之前删除其中的 JavaScript 事件侦听器。如果发生页面导航(在 HTMLLoader 对象中),请在 window 对象的 unload 事件发生期间删除事件侦听器。

例如,下面的 JavaScript 代码删除 uncaughtScriptException 事件的事件侦听器:

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

为避免在关闭包含 HTML 内容的窗口时发生错误,请调用 cleanup 函数以响应 NativeWindow 对象 ( window.nativeWindow ) 的 closing 事件。例如,下面的 JavaScript 代码删除 uncaughtScriptException 事件的事件侦听器:

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

为了防止发生此错误,您还可以在事件侦听器运行时将其删除(如果该事件只需要处理一次)。例如,下面的 JavaScript 代码通过调用 HTMLLoader 类的 createRootWindow() 方法创建一个 html 窗口,并为 complete 事件添加一个事件侦听器。在调用 complete 事件处理函数时,它会使用 removeEventListener() 函数删除它自己的事件侦听器:

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"));

如果删除不需要的事件侦听器,则还会使系统垃圾回收器能回收与这些侦听器关联的任何内存空间。

检查有无现有的事件侦听器

hasEventListener() 方法用于检查某个对象是否存在事件侦听器。