Firefox 3ではじめる拡張機能開発

第3回機能を実装する(中編)

前回はXULのオーバーレイによってFirefoxの右クリックメニューへタグヘルパー拡張機能のメニュー項目を追加しました。今回はメニュー項目をクリックしたときの動作をJavaScriptで実装します。なお、第3回完成時点でのソースファイルは、下記URLから入手可能です。

ソースファイルのフォルダ構成

前回作成した「overlay.xul」では、クロムURLが「chrome://taghelper/content/overlay.js」で表されるJavaScriptファイルを、<script>タグを使って読み込んでいます。今回はこの「overlay.js」を作成します。⁠overlay.js」はcontentパッケージ内のソースファイルなので、当然「content」フォルダ内に配置します。したがって、第3回完成時点での各種ソースファイルのフォルダ構成は図1のようになります。また、第3回で新たに作成するソースファイルの概要を表1に示します。

図1 第3回完成時点でのフォルダ構成
図1 第3回完成時点でのフォルダ構成
表1 第3回で新たに作成するソースファイルの概要
ファイル名概要
overlay.jsoverlay.xul内で読み込まれるJavaScript。

機能のオブジェクト化

前回作成した「overlay.xul」では、オーバーレイで追加するmenuitem要素のoncommand属性に「TagHelper.generateTags();」と記述しました。これは、⁠TagHelper」オブジェクトの「generateTags」プロパティ(function型オブジェクト)を実行することを意味します。そこで、ひとまずは「overlay.js」リスト1のような雛形の内容を記述します。

リスト1 ⁠overlay.js」への記述内容1(雛形)
var TagHelper = {
  generateTags: function() {
  },
};

拡張機能がFirefoxのブラウザウィンドウへオーバーレイする際、オーバーレイするXUL(今回の場合は「overlay.xul⁠⁠)から読み込まれるJavaScript(今回の場合は「overlay.js⁠⁠)内で定義したグローバル変数や関数は、すべてFirefoxのブラウザウィンドウ「browser.xul」のwindowオブジェクトのプロパティとなることに注意してください。⁠browser.xul」のwindowオブジェクトのプロパティには、Firefox自体や他の拡張機能によって定義された変数や関数がいくつも混在しています。独立性を高めて拡張機能どうしの衝突を避けるためには、リスト1のように拡張機能で利用する変数や関数をすべてひとつのオブジェクトのプロパティとしてまとめてしまうのが効果的です。

選択範囲の取得

リスト1の段階では「generateTags」プロパティを実行しても、何の処理もしません。ここからは、現在表示しているWebページ上で選択されたすべての文字列を取得し、配列へ格納する処理を追加します。⁠overlay.js」リスト2の内容を追加してください。

リスト2 ⁠overlay.js」への記述内容2(選択範囲の取得処理を追加)
var TagHelper = {
  generateTags: function() {
    var keywords = [];
    var sel = window.content.getSelection();
    for (var i = 0; i < sel.rangeCount; i++) {
      var keyword = sel.getRangeAt(i).toString();
      keyword = keyword.replace(/^\s+|\s+$/g, "");
      keywords.push(keyword);
    }
    sel.removeAllRanges();
  },
};

リスト2で追加した内容を順を追って解説します。まず、⁠window.content」によってブラウザの表示エリア内のWebページに対応するDOM:windowオブジェクトを取得します。次に、windowオブジェクトのgetSelectionメソッドで、選択範囲に対応するDOM:selectionオブジェクトを取得します。Firefox 3ではCtrlキーを押下しながら複数の範囲を選択することが可能となりましたが、個々の選択範囲に対応するDOM:rangeオブジェクトは、selectionオブジェクトのgetRangeAtメソッドを使って取得します。rangeオブジェクトのtoStringメソッドは、選択範囲の文字列を返すので、これを正規表現によって先頭と末尾の空白を取り除いてから配列へ追加していきます。最後に、selectionオブジェクトのremoveAllRangesメソッドによって、すべての選択範囲を解除します。

FUELを利用したデバッグ

引き続き、⁠generateTags」プロパティへ選択範囲の文字列からタグ付けする処理を追加していきたいところですが、いったんここまでの処理が正常にできているかを確認するため、配列「keywords」の内容をエラーコンソールの「メッセージ」パネルへ出力する処理を追加します。⁠overlay.js」リスト3の内容を追加してください。

リスト3 ⁠overlay.js」への記述内容3(FUELを使用したデバッグ処理を追加)
var TagHelper = {
  generateTags: function() {
    var keywords = [];
    var sel = window.content.getSelection();
    for (var i = 0; i < sel.rangeCount; i++) {
      var keyword = sel.getRangeAt(i).toString();
      keyword = keyword.replace(/^\s+|\s+$/g, "");
      keywords.push(keyword);
    }
    Application.console.log("keywords = " + keywords);
    sel.removeAllRanges();
  },
};

※8月1日訂正

エラーコンソールへ出力するために、Firefox 3で新たに追加されたFUELと呼ばれる拡張機能用のJavaScriptライブラリを利用します。FUELを利用することで、これまでXPCOMサービス呼び出しの手続きが必要だった処理を、少量のソースコードで実現できるようになる場合があります。例えば、Firefox 2でエラーコンソールの「メッセージ」パネルへ文字列を出力するためには、リスト4のようなソースコードを記述する必要がありました。

リスト4 FUELを使用しない場合のエラーコンソールの「メッセージ」パネルへの出力
var consoleSvc = Components.classes["@mozilla.org/consoleservice;1"].
                 getService(Components.interfaces.nsIConsoleService);
consoleSvc.logStringMessage("Hello!");

FUELを利用することで、リスト4の内容はリスト3で追加した部分のように置き換え可能となります。しかし、今のところFUELを使って実現できる機能はごくわずかであり、ほとんどの場合はリスト4のようなXPCOM呼び出しの手続きが必要となりますので、ご注意ください。なお、今回はデバッグ用にApplication.console.logを使用しましたが、場合によってDOM:window.alertによるメッセージボックス表示、DOM:window.dumpによるコンソールへの出力などを使い分けてください。

動作確認

ここまでのソースコード記述が完了したら、いったん動作確認を行います。今回修正したのは「overlay.js」なので、⁠overlay.js」の実際の読み込み先XULドキュメントである「browser.xul」⁠overlay.xul」「browser.xul」へオーバーレイされていることを思い出してください)を再読みすることで、⁠overlay.js」への変更が反映されます。つまり、Firefoxの新しいウィンドウを開けば、さきほど追加した機能の動作確認が可能となります[1]⁠。

Firefoxの新しいウィンドウを開き、適当なWebページ上でCtrlキーを押下しながら複数の範囲を選択し、右クリックメニューから「Generate Tags from Selection」を選択してください。エラーコンソールを開いて「メッセージ」パネルを選択すると、図2のように先ほど選択した文字列が出力されているはずです。

図2 エラーコンソールへの出力例
図2 エラーコンソールへの出力例

まとめと次回の予告

今回は「overlay.js」へJavaScriptのソースコードを追加し、機能の実装を行いました。選択範囲を取得する処理については、一部Geckoの独自拡張も含まれるものの、基本的にはDOMで定義されたオブジェクトの操作のみで実現できるので、簡単だと思われた方も多いのではないのでしょうか。

また、FUELについては、現時点ではまだ機能が少なく、それほど有用なものとはいえませんが、prototype.jsなどに近いコーディングスタイルが可能ですので、JavaScriptでWebアプリケーションの開発を行った経験のある方であれば、馴染みやすい形式のライブラリとなるかもしれません。

次回(後編)では、引き続き「overlay.js」に機能を追加していきます。XPCOMやPlacesのAPIを使い、より高度な処理を実装してきます。

おすすめ記事

記事・ニュース一覧