在 AIR 中處理 HTML 相關事件

Adobe AIR 1.0 以及更新的版本

事件處理系統可讓程式設計人員很方便地針對使用者輸入動作與系統事件做出回應。Adobe® AIR® 事件模型不僅方便好用,而且也符合業界標準。根據「文件物件模型第 3 層事件規格」(Document Object Model (DOM) Level 3 Events Specification,這是遵循業界標準的事件處理架構),這個事件模型可提供程式設計人員強大且直覺式的事件處理工具。

HTMLLoader 事件

HTMLLoader 物件會傳送下列 Adobe® ActionScript® 3.0 事件:

事件

說明

htmlDOMInitialize

當建立 HTML 文件時 (但是會在剖析任何指令碼之前,或者將 DOM 節點加入至網頁之前) 傳送。

complete

在 HTML 網頁中引發 onload 事件之後,立即於建立 HTML DOM 以回應載入作業時傳送。

htmlBoundsChanged

contentWidth contentHeight 兩個屬性其中之一或兩者皆已變更時傳送。

locationChange

當 HTMLLoader 的 location 屬性已變更時傳送。

locationChanging

在 HTMLLoader 的位置因為使用者瀏覽、JavaScript 呼叫或重新導向而變更之前傳送。當您呼叫 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>

它包含 throwError() 這個 JavaScript 函數,這個函數會參考未知的變數 melbaToast

var x = 400 * melbaToast;

當 JavaScript 作業遇到不合規定的作業,而後者未在 JavaScript 中被 try / catch 結構捕捉到時,包含這個網頁的 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() 方法,移除不再需要的事件偵聽程式。移除不再用到的事件偵聽程式是很好的作法。與 addEventListener() 方法所需的參數一樣,使用上述方法必須搭配 eventName listener 參數。

移除瀏覽之 HTML 網頁中的事件偵聽程式

當 HTML 內容在瀏覽時,或者當因為包含 HTML 內容的視窗關閉進而捨棄 HTML 內容時,並不會自動移除參考已取消載入網頁之物件的事件偵聽程式。在物件將事件傳送至已取消載入的處理常式時,您會看到下列錯誤訊息:「應用程式嘗試參考已不存在之 HTML 網頁中的 JavaScript 物件」。

若要避免這個錯誤,請在 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() 方法可以讓您檢查物件的事件偵聽程式是否存在。