NativeMenu のユーザー操作はイベント駆動型です。ユーザーがメニューアイテムを選択したり、メニューやサブメニューを開くと、NativeMenuItem オブジェクトによってイベントが送出されます。MenuBuilder フレームで作成した NativeMenu オブジェクトでは、個別の NativeMenuItem オブジェクトや NativeMenu にイベントリスナーを登録できます。これらのイベントの登録および応答の方法は、NativeMenu オブジェクトおよび NativeMenuItem オブジェクトを MenuBuilder フレームワークを使用せずに手動で作成した場合と同じです。詳しくは、
メニューイベント
を参照してください。
MenuBuilder フレームワークでは、標準のイベント処理を補完する方法として、メニューデータソース内のメニューアイテムに
select
イベントハンドラー関数を指定できます。メニューアイテムデータソースに
onSelect
フィールドを指定すると、ユーザーがそのメニューアイテムを選択したときに、指定した関数が呼び出されます。例えば、MenuBuilder フレームワークを使用して読み込んだデータソースに次の XML ノードが含まれているとします。該当するメニューアイテムを選択すると、
doSave()
という関数が呼び出されます。
<menuitem label="Save" onSelect="doSave"/>
onSelect
フィールドは、XML データソースでは String です。JSON 配列では、関数名の String を使用できます。また、JSON 配列でのみ、関数への変数参照をオブジェクトとして使用できます。ただし、JSON 配列で関数への変数参照を使用する場合は、
onload
イベントハンドラーの前または実行時にメニューを作成する必要があります。そうしない場合は、JavaScript セキュリティ違反が発生します。いずれの場合でも、指定した関数はグローバルスコープで定義する必要があります。
指定した関数が呼び出されると、その関数に対してランタイムから 2 つの引数が渡されます。最初の引数は、
select
イベントから送出されるイベントオブジェクトです。このオブジェクトは Event クラスのインスタンスです。関数に渡される 2 番目の引数は、メニューアイテムの作成に使用されたデータを含む匿名オブジェクトです。このオブジェクトには次のプロパティがあります。各プロパティの値は、元のデータ構造の値と一致します。元のデータ構造に設定されていないプロパティの値は
null
になります。
次の例では、NativeMenu イベントを試すことができます。この例には 2 つのメニューが含まれています。ウィンドウおよびアプリケーションメニューは、XML データソースを使用して作成されます。
<ul>
エレメントおよび
<li>
エレメントで示されるアイテムのリストのコンテキストメニューは、JSON 配列データソースを使用して作成されます。画面のテキスト領域には、ユーザーがメニューアイテムを選択したときに、各イベントに関する情報が表示されます。
アプリケーションのソースコードを次に示します。
<html>
<head>
<title>Menu event handling example</title>
<script type="text/javascript" src="AIRAliases.js"></script>
<script type="text/javascript" src="AIRMenuBuilder.js"></script>
<script type="text/javascript" src="printObject.js"></script>
<script type="text/javascript">
function fileMenuCommand(event, data) {
print("fileMenuCommand", event, data);
}
function editMenuCommand(event, data) {
print("editMenuCommand", event, data);
}
function moveItemUp(event, data) {
print("moveItemUp", event, data);
}
function moveItemDown(event, data) {
print("moveItemDown", event, data);
}
function print(command, event, data) {
var result = "";
result += "<h1>Command: " + command + '</h1>';
result += "<p>" + printObject(event) + "</p>";
result += "<p>Data:</p>";
result += "<ul>";
for (var s in data) {
result += "<li>" + s + ": " + printObject(data[s]) + "</li>";
}
result += "</ul>";
var o = document.getElementById("output");
o.innerHTML = result;
}
</script>
<style type="text/css">
#contextList {
position: absolute; left: 0; top: 25px; bottom: 0; width: 100px;
background: #eeeeee;
}
#output {
position: absolute; left: 125px; top: 25px; right: 0; bottom: 0;
}
</style>
</head>
<body>
<div id="contextList">
<ul>
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
</ul>
</div>
<div id="output">
Choose menu commands. Information about the events displays here.
</div>
<script type="text/javascript">
var mainMenu = air.ui.Menu.createFromXML("mainMenu.xml");
air.ui.Menu.setAsMenu(mainMenu);
var listContextMenu = air.ui.Menu.createFromJSON("listContextMenu.js");
air.ui.Menu.setAsContextMenu(listContextMenu, "contextList")
// clear the default context menu
air.ui.Menu.setAsContextMenu(null);
</script>
</body>|
</html>
メインメニューのデータソース(「mainMenu.xml」)を次に示します。
<?xml version="1.0" encoding="utf-8" ?>
<root>
<menuitem label="File">
<menuitem label="New" keyEquivalent="n" onSelect="fileMenuCommand"/>
<menuitem label="Open" keyEquivalent="o" onSelect="fileMenuCommand"/>
<menuitem label="Save" keyEquivalent="s" onSelect="fileMenuCommand"/>
<menuitem label="Save As..." keyEquivalent="S" onSelect="fileMenuCommand"/>
<menuitem label="Close" keyEquivalent="w" onSelect="fileMenuCommand"/>
</menuitem>
<menuitem label="Edit">
<menuitem label="Cut" keyEquivalent="x" onSelect="editMenuCommand"/>
<menuitem label="Copy" keyEquivalent="c" onSelect="editMenuCommand"/>
<menuitem label="Paste" keyEquivalent="v" onSelect="editMenuCommand"/>
</menuitem>
</root>
コンテキストメニューのデータソース(「listContextMenu.js」)を次に示します。
[
{label: "Move Item Up", onSelect: "moveItemUp"},
{label: "Move Item Down", onSelect: "moveItemDown"}
]
printObject.js ファイルのコードを次に示します。このファイルに含まれている
printObject()
関数は、アプリケーションで使用されますが、例でのメニュー操作には影響しません。
function printObject(obj) {
if (!obj) {
if (typeof obj == "undefined") { return "[undefined]"; };
if (typeof obj == "object") { return "[null]"; };
return "[false]";
} else {
if (typeof obj == "boolean") { return "[true]"; };
if (typeof obj == "object") {
if (typeof obj.length == "number") {
var ret = [];
for (var i=0; i<obj.length; i++) {
ret.push(printObject(obj[i]));
}
return ["[", ret.join(", "), "]"].join(" ");
} else {
var ret = [];
var hadChildren = false;
for (var k in obj) {
hadChildren = true;
ret.push ([k, " => ", printObject(obj[k])]);
}
if (hadChildren) {
return ["{\n", ret.join(",\n"), "\n}"].join("");
}
}
}
if (typeof obj == "function") { return "[Function]"; }
return String(obj);
}
}