AIR における HTML 関連イベントの処理

Adobe AIR 1.0 およびそれ以降

イベント処理システムは、ユーザー入力やシステムイベントにプログラムが応答するための便利な仕組みです。Adobe® AIR® のイベントモデルは、便利なだけでなく、標準に準拠しています。業界標準のイベント処理アーキテクチャであるドキュメントオブジェクトモデル(DOM)Level 3 Events 仕様に基づいたイベントモデルにより、強力で直感的に使用できるイベント処理ツールが提供されます。

HTMLLoader イベント

HTMLLoader オブジェクトは、次の Adobe® ActionScript®3.0 イベントを送出します。

イベント

説明

htmlDOMInitialize

HTML ドキュメントが作成されたとき(ただし、スクリプトが解析される前、または DOM ノードがページに追加される前)に送出されます。

complete

読み込み操作に対する応答として HTML DOM が作成されたとき(HTML ページの onload イベントの直後)に送出されます。

htmlBoundsChanged

contentWidth および contentHeight プロパティの一方または両方が変更されたときに送出されます。

locationChange

HTMLLoader の location プロパティが変更されたときに送出されます。

locationChanging

ユーザーによるナビゲーション、JavaScript の呼び出しまたはリダイレクトにより、HTMLLoader の location が変更される前に送出されます。 locationChanging イベントは、 load() loadString() reload() historyGo() historyForward() または historyBack() メソッドの呼び出し時には送出されません。

送出されたイベントオブジェクトの preventDefault() メソッドを呼び出すと、ナビゲーションがキャンセルされます。

システムブラウザーでリンクが開いている場合、HTMLLoader は location を変更しないので、locationChanging イベントは送出されません。

scroll

HTML エンジンがスクロール位置を変更するたびに送出されます。scroll イベントは、ページ内のアンカーリンク( # リンク)への移動、または window.scrollTo() メソッドの呼び出しによって発生します。テキスト入力欄またはテキスト領域にテキストを入力した場合にも、scroll イベントが発生する可能性があります。

uncaughtScriptException

HTMLLoader で JavaScript 例外が発生し、その例外が JavaScript コードでキャッチされない場合に送出されます。

ActionScript 関数を JavaScript イベント(例えば onClick )について登録する、という方法もあります。詳しくは、 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>

この 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 トレース出力に送信する)をキャンセルし、独自の出力メッセージを生成します。このメッセージは、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 コンテンツを格納しているウィンドウが閉じられたためにそのコンテンツが破棄される場合、読み込みを解除されたページ上のオブジェクトを参照するイベントリスナーは、自動的には削除されません。オブジェクトが既に読み込みを解除されたハンドラーにイベントを送出すると、「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 コンテンツを格納したウィンドウを閉じる際にエラーが発生しないようにするには、NativeWindow オブジェクト( window.nativeWindow )の closing イベントに対する応答として、cleanup 関数を呼び出します。例えば、次の JavaScript コードでは、 uncaughtScriptException イベントをリッスンするイベントリスナーを削除します。

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

また、イベントの処理が 1 回のみの場合、実行後すぐにイベントリスナーを削除することで、このエラーが発生しないようにできます。例えば、次の JavaScript コードでは、HTMLLoader クラスの createRootWindow() メソッドを呼び出し、 complete イベントのイベントリスナーを追加することで、html ウィンドウを作成します。 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() メソッドを使用することで、あるオブジェクトに関してイベントリスナーが存在しているかどうかを確認することができます。