Now browsing the archives for 9月, 2010.

persist 属性による属性値の永続化

属性の永続化とは?

XUL要素に persist 属性によって値を保存したい属性の名前を指定しておくと、その属性の値が次回XULドキュメントをロードした時に復元される。保存された属性の値は Firefox 終了時にローカルファイル(プロファイルフォルダ下の localstore.rdf)へ書き出されるので、 Firefox を終了しても保持される。

XULアプリで何らかの設定値を保存するには、 Preferences の仕組みを使って保存する方法が有名だが、UIの見た目に関する設定値(ウィンドウの位置や大きさ、ツールバーのボタンの並び順など)は属性の永続化によって保存される場合が多い。

具体的な例

Firefoxのウィンドウの位置や大きさは、前回開いたときの状態が復元される。これは属性の永続化によって実現されている。 browser.xul のソースを見ると、以下のように persist 属性によって保存したい属性のリストが指定されている。

browser.xul
<window id="main-window"
        ...
        persist="screenX screenY width height sizemode">

localstore.rdf には以下のように {XULドキュメントのURL}#{要素のid} をキーとしてして保存対象の各属性の値が保存される。

localstore.rdf
  <RDF:Description RDF:about="chrome://browser/content/browser.xul#main-window"
                   screenX="115"
                   screenY="87"
                   width="823"
                   height="645"
                   sizemode="normal" />

基本的な使い方

例として、以下のように persist 属性にて value 属性を永続化するようにした xul:label 要素を作成する。idの無い要素は属性の永続化ができないことに注意。

test.xul
<label id="testLabel" value="Test" persist="value" />

次に、以下のようなボタンを作って、 value 属性の値を動的に変更してみる。

test.xul
<button label="Write value"
        oncommand="document.getElementById('testLabel').setAttribute('value', 'xxx');" />

いったん Firefox を終了し、 localstore.rdf を開いてみると、以下のように変更後の foo 属性の値が保存されていることがわかる。

localstore.rdf
  <RDF:Description RDF:about="chrome://.../content/test.xul#testLabel"
                   value="xxx" />

引き続き Firefox を起動して test.xul を開いてみると、ラベルの文言が変更後の xxx になっていることがわかる。

次に、以下のようなボタンを追加し、ボタンをクリックして value 属性の値を削除してみる。

test.xul
<button label="Delete value"
        oncommand="document.getElementById('testLabel').removeAttribute('value');" />

Firefox を終了して localstore.rdf を見ると、 value 属性の値を保存していた部分が削除されていることがわかる。また、 Firefox を起動して test.xul を開いてみると、ラベルの文言が初期値の Test になっていることがわかる。

persist 属性の落とし穴

persist 属性には永続化したい属性の名前(複数ある場合はスペース区切りで連結)を指定するが、注意すべき点として、 persist 属性に指定した属性の名前に部分一致する属性までもが永続化の対象となることが挙げられる。

先ほどの persist="value" とした xul:label 要素の例で、以下のようなボタンを追加する。

test.xul
<button label="Write val"
        oncommand="document.getElementById('testLabel').setAttribute('val', 'xxx');" />

ボタンをクリックして val 属性の値に xxx をセットし、 Firefox を終了して localstore.rdf を見ると、永続化の対象外と思われた val 属性の値までもがちゃっかり保存さていることがわかる。

localstore.rdf
  <RDF:Description RDF:about="chrome://.../content/test.xul#testLabel"
                   val="xxx" />

これはFirefox 本体側のバグと思われる。
Bug 231333 – Unexpected persist when the persisted attribute name contains another

document.persist

document.persist メソッドによって、 persist 属性を使わずに属性の永続化をすることも可能である。

test.xul
<label id="testLabel" value="Test" />
<button label="Write value"
        oncommand="document.getElementById('testLabel').setAttribute('value', 'xxx');
                   document.persist('testLabel', 'value');" />

persist 属性には前述のように部分一致した属性も永続化される問題があるため、こちらの方法を使ったほうが無難かもしれない。

TOP