レポート機能を呼び出す設定をする
まず、TouchUpWeb拡張機能のウィザードからレポート機能を呼び出すために、以下の2つの設定を行います。
- UI(ウィザード)にレポート機能を呼び出すボタンを追加する。
- ボタンがクリックされたときに呼び出す関数を指定する。
UI関係の設定は.xulファイルに記述します。ウィザードの設定は「wizard.xul」に記述されています。中身を見てみると<wizardpage>
でくくられた部分がいくつかあることが分かります。<wizardpage>
はその名の通りウィザードの各ページデザインを設定する項目です。レポート機能はパッチ適用後のウィザードから呼び出しますので、「<wizardpage pageid="patchApplied" …
」で始まる部分を見てみましょう。
<wizardpage pageid="patchApplied" label="&patchApplied.title;" onpageshow="onPatchAppliedPageShow();" onpagerewound="return onPatchAppliedPageRewound();" onpagehide="restoreButtonLabels();" cancelbutton="&patchApplied.cancelbutton.label;" backbutton="&patchApplied.backbutton.label;" nextbutton="&patchApplied.nextbutton.label;"> <description class="number">&patchApplied.label;</description> <description hidden="true">&patchApplied.multi.label;</description> <separator class="thin" /> <hbox> <checkbox id="cb2" label="&patchApplied.cb.label;" accesskey="&patchApplied.cb.accesskey;" oncommand="patchAppliedPageCheck(this.checked)" /> <spacer flex="1" /> </hbox> <separator /> <separator class="groove-thin" /> <separator /> <!-- ここから --> <description>&patchApplied.diff.desc.label;</description> <hbox> <spacer flex="1" /> <button label="&patchApplied.diff.button.label;" accesskey="&patchApplied.diff.button.accesskey;" oncommand="showDiffInit();" /> </hbox> <!-- ここまで --> </wizardpage>
レポート機能に関する指定は最後の「ここから」から「ここまで」で括った部分です。<description>
でウィザードに表示される文字列を、<button>
でボタンに関する設定をしています。label
はボタンに表示する文字列、accesskey
はそのボタンへのショートカットキーです。
重要なのはoncommand
で指定した部分で、ボタンをクリックするとここで指定した関数が呼び出されます。ここではshowDiffInit();
を指定していますので、レポート機能はshowDiffInit
関数が起点になっていることが分かります。
なお、<description>
やlabel
などに"&"で始まる文字列が指定されていますが、これは多言語に対応するための仕組みで、別途指定したリソースファイルで設定されている文字列と置き換えられることを表しています。TouchUpWeb拡張機能の場合、リソースファイルの設定は「wizard.xul」の冒頭部分で行われています。
<!DOCTYPE dialog SYSTEM "chrome://touchupweb/locale/wizard.ent">
この場合、"&"で始まる文字列は「locale/(lang)/wizard.ent」内で指定した文字列と置き換えられます。「(lang)」の部分は日本語環境の場合はja、英語環境の場合はenになり、ユーザーの環境によって表示言語が自動的に変更されます。
このように「wizard.xul」の中に直接文字列を記述せず、別のリソースファイルに分けることによって、多言語への対応も簡単にできるようになっているのです。
テンプレートの読み込み
レポート表示のボタンがクリックされるとshowDiffInit
が呼び出され、さらにshowDiffInit
は「report.js」中の関数tuwShowDiff
を呼び出します。
以下にtuwShowDiff
のソースを示します。tuwShowDiff
はレポートのテンプレート「template.html」を読み込み、読み込みが完了すると関数tuwShowDiffMain
を呼び出しています。
function tuwShowDiff() { tuwReportTabBrowser = gBrowser; gBrowser.selectedTab = gBrowser.addTab("chrome://touchupweb/content/diff/template.html"); gBrowser.addEventListener("pageshow", tuwShowDiffMain, false); } function tuwShowDiffMain() { gBrowser.removeEventListener("pageshow", tuwShowDiffMain, false);
ここでのポイントは、tuwShowDiffMain
を直接呼び出さずにイベントリスナー(addEventListener
)を使っていることです。もし、イベントリスナーを使わずに直接次の関数(tuwShowDiffMain
)を呼び出すと、テンプレートの読み込みが終了する前に次の処理(tuwShowDiffMain
)に進んでしまいます。ところが、tuwShowDiffMain
はテンプレートの要素にデータを埋め込んでいくため、テンプレートの読み込みが完了していないと正常に動作しません。読み込み完了までtuwShowDiffMain
を呼び出さないようにしないといけないのです。
そこで登場するのがイベントリスナーです。addEventListener
の第一引数に指定されたイベントが発生すると、第二引数で指定した関数が呼び出されます。ここでは第一引数として、ページが表示された時に発生するイベントpageshow
が指定されています。そのため、現在読み込み中のページ(template.html)の読み込みが完了するまで待ってtuwShowDiffMain
が呼ばれることになります。
なお、呼び出された関数(tuwShowDiffMain
)側では、removeEventListener
を使ってイベントリスナーの設定を解除するのを忘れないようにしてください。そうしないと、ページが読み込まれるたびにtuwShowDiffMain
が呼ばれてしまいます。
レポートの構築
tuwShowDiff
から呼び出されたtuwShowDiffMain
では、テンプレートにレポートのコンテンツを埋め込み、レポートを作成します。
まず、「template.html」の内容を見てみましょう。
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> ... 中略 ... </head> <body> <div id="wrapper"> <div id="header"> <p><a href="http://www.touchupweb.org/"> <span>TouchUpWeb Project</span></a></p> </div> <div id="content"> <h1>TouchUpWeb Detailed Report</h1> <h2>Browser Information</h2> <table id="report"> <tr><th>Date:</th><td id="date"></td></tr> <tr><th>URL:</th><td><a id="url"></a></td></tr> <tr><th>Product:</th><td id="product"></td></tr> <tr><th>Gecko Version:</th><td id="gecko"></td></tr> <tr><th>User Agent:</th><td id="userAgent"></td></tr> <tr><th>Build Config:</th><td id="buildConfig"></td></tr> <tr><th>Platform:</th><td id="platform"></td></tr> <tr><th>OS:</th><td id="oscpu"></td></tr> <tr><th>Language:</th><td id="lang"></td></tr> </table> <h2>Applied Script</h2> <div id="appliedScripts"></div> <h2>Source Diff</h2> <div id="touchupDetails"></div> </div> <div id="footer"> <p>Copyright © <span id="year"></span> TouchUpWeb Project</p> </div> </div> </body> </html>
<td id="date">
や<div id="appliedScripts">
のようにid
が指定されたタグが並んでいます。このように、コンテンツを埋め込みたいタグにid
を付けておくと、拡張機能からid
を指定してコンテンツを埋め込むことができます。具体的には、DOM(Document Object Model)のgetElementById
メソッドを使って、「document.getElementById("id名").innerHTML = "コンテンツ";
」 のように指定します。
例えば、
var doc = window._content.document; doc.getElementById("date").innerHTML = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
のように指定すると、テンプレート中の「<td id="date"></td>
」は「<td id="date">2006-10-20 12:34:56</td>
」のように置き換えられます。
このようにテンプレートとDOMを利用すれば、テンプレートの切り替えによってレポートのデザインや構成を簡単に変えることができます(TouchUpWeb拡張機能のレポートの場合はあまり需要がないと思いますが、必要とされるアプリケーションもたくさんあります。)。
なお、レポートには修正スクリプト適用前後のコンテンツの比較結果が含まれます。修正前後のコンテンツを比較し、差分をとる処理は、tuwShowDiffMain
から呼び出している「diff.js」のtuwDiffString
関数で行われています。差分作成処理は本記事のスコープから外れるので省略しますが、興味のある方は水谷敏行氏のページを参考にしてください。
おわりに
TouchUpWeb拡張機能のレポート作成機能を題材に、Firefox拡張機能の仕組みを見てきました。本記事で解説した内容をまとめると、以下の4点になります。
- XULによるUIの設定
- 多言語化の仕組み
- イベントリスナーの利用
- テンプレートとDOMの利用
いずれの解説もさわり程度ではありますが、拡張機能の仕組みを理解するお手伝いにはなるのではないかと思います。
Firefoxの拡張機能開発に必要な言語はJavaScriptとXML(XUL)だけですし、ある程度JavaScriptの知識がある方であれば、拡張機能の開発は決して難しいことではないでしょう。本記事が少しでも拡張機能開発の日本語情報の拡充に役立てれば幸いです。
あなたもFirefoxの拡張機能を作ってみませんか?
参考資料
- Firefoxまとめサイト
- CodeZine 『不完全なHTMLを動的にタッチアップ』 飯尾淳 著、2006年8月
- TouchUpWebプロジェクト
- Mozilla Firefoxまとめサイトの拡張機能開発チュートリアル
- diff生成スクリプトが公開されている水谷敏行氏のページ