AppLauncher ver.0.2 〜 コンテキストメニューへの追加と動的な変更 〜

Firefox拡張機能 (add-on の一種) を作ってみよう、ということで作り始めた AppLauncher。 前回は、ステータスバーに新たなパネルを追加し、それをクリックすると警告ウィンドウが表示されるというものを作りました。

今回はステータスバーではなく、コンテキストメニュー (右クリックをしたときに表示されるメニュー) に AppLauncher の項目を追加したいと思います。

AppLauncher ver.0.2 の作成

Firefox から外部アプリケーションを開く、という拡張機能 AppLauncher を作っていきます。

Ver.0.2 では、コンテキストメニューに AppLauncher の項目を追加します。 AppLauncher の項目を選ぶとサブメニューが開き、将来的にはそこから外部アプリケーションを起動するようにします。 そのため、サブメニュー内の項目は固定ではなく、動的に変更できるようにしておきます。

今回は、XUL のオーバーレイにより、サブメニュー内に 1 つの固定項目を作り、さらに JavaScript で動的に 1 つの項目を追加します。

なお、現時点 (ver.0.1) でのファイル構成は以下のようになっています。

[applauncher-0.1.xpi]
+--[chrome.manifest]
+--[install.rdf]
+--[content]
+--[launcher.xul]
+--[launcher.js]
+--[prefs.xul]

XUL のオーバーレイで、コンテキストメニューに要素を追加する

まずは固定のメニューを作成します。

XUL のオーバーレイを使用して、簡単にコンテキストメニューに要素を追加することが出来ます。 MDC のこの文書 が参考になります。

"content/launcher.xul" ファイルを以下のように書き換えました。

<?xml version="1.0" encoding="UTF-8"?>
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<!-- JavaScript を読み込み -->
<script type="application/x-javascript" src="chrome://applauncher/content/launcher.js" />

<!-- コンテキストメニューへの追加: cf. https://developer.mozilla.org/ja/XUL/PopupGuide/Extensions -->
<popup id="contentAreaContextMenu">
<menuseparator id="info.vividcode.applauncher.contextmenu.separator" />
<menu id="info.vividcode.applauncher.contextmenu" label="AppLauncher">
<menupopup id="info.vividcode.applauncher.contextmenu.items">
<menuitem id="info.vividcode.applauncher.contextmenu.item1" label="item1" />
<!-- JavaScript ("launcher.js") によってこの部分に要素を追加する -->
</menupopup>
</menu>
</popup>

</overlay>

この XUL ファイルの変更だけを行って Firefox拡張機能を再インストールすると、以下のように、コンテキストメニューに要素が追加されます。 現時点ではクリックしても何も起こりません。

JavaScript を使って、要素を動的に変更する

さて、固定的な要素の配置は XUL で行うことが出来ました。 次は JavaScript を使って動的に要素の追加を行います。

さきほど "content/launcher.xul" ファイルに書いたのを見てもらえばわかると思いますが、サブメニュー全体を表す要素が "menupopup" で、その中の項目が "menuitem" 要素です。 よって、新たに項目を加えるには、JavaScript 上で DOM を使って "menupopup" 要素を取得し、その子要素として新たに作成した "menuitem" 要素を加えてやることになります。

DOM は結構一般的な規格なので知っている人は知っていると思いますが、知らない人は XML のインターフェイスを動的に変更する方法の説明 (MDC) を読んでください。

また、メニューの項目をクリックしたときに JavaScript の関数を呼び出したいので、addEventListener 関数を使ってイベントリスナの登録も行います。 この関数も DOM の一部なので説明は省きますが、知らない方は addEventListener の説明 (MDC) を読んでください。

これらの内容を実装すると、"content/launcher.js" ファイルは以下のようになりました。

// AppLauncher の JavaScript
var AppLauncher = {

/**
* 外部アプリケーションを起動する関数
* 現在は、テスト用のアラートを表示するだけ.
*/
launch: function( evt ) {
window.alert( "Hello AppLauncher! (" + evt.currentTarget.getAttribute("label") + ")" );
},

/**
* 初期化関数
* AppLauncher に関するコンテキストメニューの変更を行う.
*/
init: function() {
// XUL で追加済みの "menuitem" 要素を取得し、イベントリスナを追加する
var item = document.getElementById("info.vividcode.applauncher.contextmenu.item1");
if( item ) {
// イベントリスナの追加
item.addEventListener("command", AppLauncher.launch, false);
}
// コンテキストメニュー内の、AppLauncher に関する "menupopup" 要素 (id で指定) を取得
var menupopup = document.getElementById("info.vividcode.applauncher.contextmenu.items");
if( menupopup ) {
// "menuitem" 要素の作成
item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem");
// "label" 属性に "adding item!" という値を設定
item.setAttribute("label", "item2");
// イベントリスナの追加
item.addEventListener("command", AppLauncher.launch, false);
// "menupopup" 要素の子ノードに追加
menupopup.appendChild(item);
}
menupopup = null;
item = null;
},

}

// 初期化関数をロード時に実行する
window.addEventListener("load", AppLauncher.init, false);

ここまでが ver.0.2 の内容です。 これを Firefox にインストールすると、コンテキストメニューが動的に書き換えられているはずです。 また、イベントリスナの追加を行ったので、クリックすると警告ウィンドウが開きます。

展望

今回は見た目の変更だけでしたが、次回はいよいよ外部アプリケーションの起動を行いたいと思います。