xul:filefield

xul:filefield

ユーザが選択したファイルやフォルダを表示するような設定UIを作る場合には xul:filefield 要素が便利である。例えば Firefox のダウンロード先フォルダの設定UIには xul:filefield 要素が使われている。

XUL

filefield 要素を使うためには、以下の2つのスタイルシート参照する処理命令を追加する必要がある。2つめのスタイルシートは Firefox 専用である。

<?xml-stylesheet href="chrome://mozapps/content/preferences/preferences.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>

多くの場合、 filefield 要素はファイルを選択するためのボタンとセットで使用される。

<hbox align="center">
    <filefield id="myFileField" flex="1" />
    <button label="Browse..." oncommand="selectFile();" />
</hbox>

JavaScript

「Browse…」ボタンを押したときの selectFile 関数を定義する。 nsIFilePicker を使ってファイル選択ダイアログを表示し、ユーザがファイルを選択すると、その選択したファイル (nsILocalFile 型) を filefield 要素の file プロパティへセットする。すると、ファイル名とアイコンが表示される。
Windows の場合、選択したファイルがアプリケーションであれば、ファイルのプロパティで「バージョン情報」の「説明」に設定された文字列が表示される。例えば「iexplore.exe」であれば「Internet Explorer」のようにアプリケーション名となる。

function selectFile() {
    var filePicker = Components.classes["@mozilla.org/filepicker;1"]
                     .createInstance(Components.interfaces.nsIFilePicker);
    filePicker.init(window, "Choose a file.", filePicker.modeOpen);
    if (filePicker.show() == filePicker.returnOK) {
        var fileField = document.getElementById("myFileField");
        fileField.file = filePicker.file;
    }
}

nsIFilePicker#modeGetFolder を使ってフォルダ選択ダイアログを表示させ、ユーザにフォルダを選択させる場合、 filefield 要素の file プロパティへフォルダを表す nsILocalFile をセットしてもアイコンしか表示されない。この場合、以下のように filefield 要素の label プロパティへフォルダのパスなどを表示させるよう処理を加える。

fileField.label = filePicker.file.path;

応用例

実際のところ filefield 要素は prefwindow 要素で作成した設定画面内に配置することが多い。 preference[type=”file”] の要素と組み合わせて使用する例を下記に示す。

<?xml version="1.0"?>

<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mozapps/content/preferences/preferences.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>

<prefwindow id="testPrefWindow"
            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
            style="width: 30em;">

    <prefpane id="mainPane" onpaneload="updateUI();">
        <preferences>
            <preference id="extensions.hoge.testDir" name="extensions.hoge.testDir" type="file" />
        </preferences>
        <script type="application/x-javascript"><![CDATA[
            function updateUI() {
                var file = document.getElementById("extensions.hoge.testDir").value;
                if (file) {
                    var fileField = document.getElementById("myFileField");
                    fileField.file = file;
                    fileField.label = file.path;
                }
            }
            function selectDir() {
                var filePicker = Components.classes["@mozilla.org/filepicker;1"]
                                 .createInstance(Components.interfaces.nsIFilePicker);
                filePicker.init(window, "Choose a folder.", filePicker.modeGetFolder);
                if (filePicker.show() == filePicker.returnOK) {
                    document.getElementById("extensions.hoge.testDir").value = filePicker.file;
                    updateUI();
                }
            }
        ]]></script>
        <hbox align="center">
            <filefield id="myFileField" flex="1" />
            <button label="Browse..." oncommand="selectDir();" />
        </hbox>
    </prefpane>

</prefwindow>

参考

chrome://mozapps/content/preferences/preferences.xml#fileField

TOP

prefpane には必ず id を付与する

設定値 browser.preferences.animateFadeIn が true の場合に、 id を持たない prefpane が丸ごと表示されない。

<prefpane id="paneMain">

というように必ず id を付与しなければならない。
確かに MDC の prefpane の解説 にも id は必ず付与すべしと書いてある。

prefwindow を使用している場合はパネルの中身が見切れるなどのトラブルがつき物なので、可能な限り以下のような観点での動作確認をした方がよさそうだ。

  • 各パネルの中身が正しく表示されるか?
  • 最後に選択したパネルが次回正しく初期選択されるか?
  • browser.preferences.animateFadeIn が true の場合の動作確認
  • browser.preferences.instantApply が true の場合の動作確認
  • 上記を {Firefox 2 | Minefield} × {Win | Mac | Linux} の6パターンで動作確認

TOP

Prefwindow のパネル切り替えの挙動がおかしい

prefwindow 要素で作成した設定ウィンドウで、ウィンドウ上部のパネル切り替えボタンと実際に選択されるパネルに食い違いが発生するおかしな挙動に悩まされた。

原因は prefwindow 要素直下に script 要素を配置していたことだった。
Preferences System:prefwindow – MDC にも書いてある通り、 prefpane 以外の要素を配置する場合は prefpane 要素よりも後に記述しなければならない。

<prefwindow ... >
    <prefpane label="General" ... >
        ...
    </prefpane>
    <prefpane label="Advanced" ... >
        ...
    </prefpane>
    <script type="application/x-javascript" src="prefs.js" />
</prefwindow>

TOP