处理 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() 方法用于检查某个对象是否存在事件侦听器。