Firefox 4 にてコンテキストメニューを開く際に右クリックしたノードを取得する方法

Firefox拡張機能 (アドオンの一種) の開発をして、コンテキストメニューに項目を追加し、コンテキストメニューからいろいろと操作をできるようにすることがあります。 コンテキストメニューを変更したり、イベントを取得したりする方法については次のページが参考になります。

コンテキストとして何がクリックされたか判定する

上に示したページにおいて、コンテキストメニューを開く際に右クリックしたノードを取得する方法として、次のことが書かれています。

コンテキストメニューはマウスだけではなく他の方法でも開かれ得るという事を覚えておく事は重要です。しかしながら、キーボードを使って開かれた場合でも、メニューが適用されるノード (コンテキスト) はあります。それは現在フォーカスのある要素です。マウスを使った場合には、コンテキストはクリックされた要素です。

この要素は document の popupNode プロパティを使って取得できます。次の例では、browser に取り付けられたポップアップで、popupNode プロパティをチェックして画像がクリックされたかどうかを判定しています。

詳しくは 該当箇所 を読んでください。 要は JavaScriptdocument.popupNode を参照することで、どのノードを右クリックしてコンテキストメニューを開いたのかがわかるわけです。 (Firefox 3.6 にて確認。)

Firefox 4 では menupopup.triggerNode を使う?

しかしながら、Firefox 4.0b6 でその方法を試してみたところ、document.popupNodenull になっており、ノードの取得ができませんでした ((もしかしたら私のコードの書き方が悪くて、うまくしたら document.popupNode を使うことができるのかも知れませんが、少なくとも Firefox 3.6 でちゃんと動いたコードが動かなかったことは確かです。))。 Firefox 4.0b7 で試したところ、問題なく document.popupNode を使うことができました。 Firefox 4.0b6 のバグか何かだったようです。

そこで、Firefox 4 への変更点を調べていると、次の記述を見つけました

The menupopup XUL element now has a triggerNode property, which indicates the node on which the event occurred that caused the popup to open.

XULmenupopup 要素を表すオブジェクトに triggerNode プロパティが追加され、そのプロパティを参照することで、コンテキストメニューを開く際にどのノードを右クリックしたのかがわかるようです。 実際に Firefox 4.0b6 で試してみましたが、問題なく使用することができました。

Firefox 3 と 4 で互換性がないのでちょっと注意が必要です。 menupopup.triggerNode に関しては互換性がありませんが、document.popupNodeFirefox 3 でも 4 でも使えそうです。

Firefox 4 で document.popupNode が使えないのかどうかについて (追記)

@saneyuki_s さんのついーと より。

最新のnightlyだと、document.popupNodeでも、ちゃんと値は返ってきたけどなあ。(alertで簡易確認だけど。)

確かに Firefox 4 のドキュメントを読んでも document.popupNode が使えなくなった、という記述は見つけられませんので、どんな場合にでも document.popupNode が使えないというわけではなさそうです。 どういう場合に使えてどういう場合に使えないのか、もうちょっと詳しく調べてみる必要がありそうです。 上でも述べましたが、どうやら Firefox 4.0b6 のバグのようです。 Firefox 4.0b7 では問題ありませんでした。

おまけ: popup 要素に関して

XUL の雑多な変更点 を読んでると次のことが書かれていました。 Firefox 4 では popup 要素の代わりに menupopup 要素を使うべきである、とのこと。

The popup element is no longer supported; you should use menupopup instead.

AppLauncher ver.0.6.3, ver.0.6.4

Firefox拡張機能 AppLauncher のバージョンアップを行いました。

AppLauncher とは

AppLauncher は Firefox拡張機能です。 右クリックメニュー (コンテキストメニュー) から外部アプリケーション (IE などのブラウザだとかその他色々) を起動することを目的に開発しています。

とりあえず現状では以下のようなことが可能です。

ダウンロードは下記ページにて行うことができます。

何か問題がありましたらブログへのコメントやメールにてお知らせいただければと思います。 要望とかもお待ちしております。 なお、ver.0.6.3 および ver.0.6.4 は Firefox 3.0 - 3.6 に対応しています。

AppLauncher ver.0.6.3 公開 (2010-01-23)

AppLauncher ver.0.6.2 までは Firefox 3.5 までに対応していましたが、Firefox 3.6 がリリースされたことを受けて Firefox 3.0 - 3.6 に対応した ver.0.6.3 を公開しました。
また、ver.0.6.3 よりアドオンの自動更新に対応しました。

AppLauncher ver.0.6.4 公開 (2010-02-14)

AppLauncher ver.0.6.3 では 「現在表示しているページの URL」 と 「現在表示しているページの URL を URI エンコードしたもの」 を設定項目内に指定することができましたが、「リンクを右クリックしてコンテキストメニューを開いたときに、そのリンク先 URL」 も設定項目内に指定したい、という要望があったため、それを可能にしました。
設定項目内に "&turl;" と書くと、リンクを右クリックしてコンテキストメニューを開いた場合はそのリンク先 URL が、そうでない場合は現在表示しているページの URL に置換されるようになりました。

AppLauncher ver.0.6.2

Firefox 拡張機能 AppLauncher のバグを見つけたので修正しました。

AppLauncher とは

AppLauncher は Firefox拡張機能です。 右クリックメニュー (コンテキストメニュー) から外部アプリケーション (Firefox 以外のブラウザだとかその他色々) を起動することを目的に開発しています。

とりあえず現状では以下のようなことが可能です。

AppLauncher ver.0.6.2 公開

Ver.0.6.1 において、インストールした直後に初めて設定変更を行おうとすると例外が発生するというバグを発見しました。 これは、ユーザ設定がないにもかかわらず文字列があるつもりで処理をしていたことが原因です。 同じ原因により、インストール直後に右クリックから "AppLauncher" の項目を選択しても、サブメニューが開かないという問題も発生していました。

この問題を修正したものを ver.0.6.2 として公開しました。 ダウンロードやインストールは下記ページよりお願いします。

何か問題がありましたらブログへのコメントやメールにてお知らせいただければと思います。 要望とかもお待ちしております。 なお、ver.0.6.2 は Firefox 3.0 - 3.5 に対応しています。

AppLauncher ver.0.6.1

本日院試の結果発表があったのですが、無事合格していました! 良かった良かった。 しかし友達が 2 人不合格だったのでちょっと悲しいです。 ついでに農工大から受けに来てた人もダメだったみたいで・・・うう。

んで今日は Firefox 拡張機能 AppLauncher のバグフィクスをしたので公開します。

AppLauncher とは

AppLauncher は Firefox拡張機能です。 右クリックメニュー (コンテキストメニュー) から外部アプリケーション (Firefox 以外のブラウザだとかその他色々) を起動することを目的に開発しています。

とりあえず現状では以下のようなことが可能です。

* 現在見ているページを IETester や IEOperaSafari などで開く
* 現在見ているページをはてなブックマークなどに追加する (ためのページを Firefox で開く)

AppLauncher ver.0.6.1 公開

Ver.0.6 では、設定項目の中に日本語 (というか非 ascii 文字) が混ざっていると正常に設定が保存されないという問題があったのですが、ver.0.6.1 ではその問題を解決しました。 ダウンロード、インストールは下記リンクよりお願いします。

何か問題がありましたらブログへのコメントやメールにてお知らせいただければと思います。 要望とかもお待ちしております。 なお、ver.0.6.1 は Firefox 3.0 - 3.5 に対応しています。

Firefox 拡張機能の設定項目の保存時に日本語が化ける

Firefox拡張機能でユーザに設定項目を入力させる場合、その設定内容は nsIPrefBranch を使って保存したり読み込んだりすることが多いと思います。

参考: 4章:XPCOM活用術〜高度な処理を実現する〜 (Firefox 拡張機能開発チュートリアル)

んで文字列を保存するときに、日本語等の非 ascii 文字も問題なく保存、読出しができるものだと思っていたのですが違うみたいですね。 以下のコードでテストしました。

/**
* 設定保存, 読出しで日本語が化けないかどうかのテスト
*/
var test = function() {
// 設定の情報を取得する XPCOM オブジェクトの生成
var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
var prefBranch = prefSvc.getBranch("extensions.applauncher.");
// 保存
prefBranch.setCharPref("test", "日本語テスト!");
// 読み出して、アラートで表示
// 実際はタイプ別に取得する関数を分けた方がいい (と思う) が, ここでは省略
window.alert( prefBranch.getCharPref("test") );
};

"日本語テスト!" と表示されるべきところですが、実際はよくわからん文字 (化けた文字) が表示されました。 そんなわけで日本語はそのままじゃ保存できないみたいです・・・。

日本語もちゃんと保存させるために

以下のように URL エンコード + エスケープすれば良いみたい。 4章:XPCOM活用術〜高度な処理を実現する〜 (Firefox 拡張機能開発チュートリアル) に書いてあるそのまんまですが。

/**
* 設定保存, 読出しで日本語が化けないかどうかのテスト
*/
var test = function() {
// 設定の情報を取得する XPCOM オブジェクトの生成
var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
var prefBranch = prefSvc.getBranch("extensions.applauncher.");
// 保存
prefBranch.setCharPref( "test", unescape(encodeURIComponent("日本語テスト!")) );
// 読み出して、アラートで表示
// 実際はタイプ別に取得する関数を分けた方がいい (と思う) が, ここでは省略
window.alert( decodeURIComponent(escape( prefBranch.getCharPref("test") )) );
};

AppLauncher ver.0.6

8 月 10 日に無事大学院の入試が終了しました! その後は最高で 40 度の熱が出てしまい寝込んでいたのですが、さすがに寝すぎて 「これ以上は寝られない! 暇!」 という状態になったので昨日の夕方から暇つぶしに AppLauncher の開発を再開しました。

AppLauncher に対する需要があるのかどうか謎ですが・・・。 まあ自分が便利に使えたらいいよね、なんて。

AppLauncher とは

AppLauncher は Firefox拡張機能です。 右クリックメニュー (コンテキストメニュー) から外部アプリケーション (Firefox 以外のブラウザだとかその他色々) を起動することを目的に開発しています。

とりあえず現状では以下のようなことが可能です。

AppLauncher ver.0.6 公開

昨日の夕方からせこせこ開発してましたが、ひと段落ついたので ver.0.6 として公開しました。 ダウンロードは以下のページよりお願いします。

何か問題がありましたらブログへのコメントやメールにてお知らせいただければと思います。 要望とかもお待ちしております。 なお、ver.0.6 は Firefox 3.0 - 3.5 に対応しています。

熱があるのにプログラミングするもんじゃないよね

熱があるのに暇つぶしにプログラムを書いてたわけだけど、ホントしょーもない間違いが多すぎて泣きそうになりました。 普段なら絶対しないようなミス。

文字列を二重引用符でくくるのを忘れたり、「function」 と書くつもりで 「file」 と書いてたり。 熱があるのにプログラミングなんてするもんじゃないよね!

XUL アプリ: 新しくページを読み込んだ時にコードを実行する方法

普通、web ページ内に置いた JavaScript コードがページ読み込み完了時に処理を行うためには、

window.addEventListener("load", func, false);
などと書きます。

が、XUL アプリケーションで上のような書き方をすると、ページ読み込み時ではなく XUL アプリケーションのロード時に処理 func が行われます。 ではどうすればいいかというと、window オブジェクトにイベントリスナを追加するのではなく、ブラウザのページ表示領域 (id="appcontent" の要素) に DOMContentLoaded イベントをキャッチするイベントリスナを追加すればよいのです。

var myExtension = {
init: function() {
// ページの表示領域取得
var appcontent = document.getElementById("appcontent");
if( appcontent ) {
// DOMContentLoaded イベントをキャッチするイベントリスナを追加
appcontent.addEventListener("DOMContentLoaded", myExtension.listener, true);
}
},
// DOMContentLoaded イベントをキャッチするイベントリスナ
listener: function( aEvent ) {
// "doc" はイベントが発生したドキュメント
var doc = aEvent.originalTarget;
// ここで処理を行う
}
}

window.addEventListener("load", function(evt) { myExtension.init(); }, false);

詳しくは MDC のページ読み込み時に処理を行う方法に関する文書 を見てください。