Jan 24, 2009

Firefox 3.1に向けてまたタブ回りが色々変わったのと、XUL要素のdisplayプロパティの値

タブのドラッグ&ドロップに関する色んなバグを一挙に解決するパッチ最後のタブの右に「新しいタブ」ボタンを表示するようにするパッチの両方が入って、タブ回りが色々変わった。何はともあれ、タブをクリックしようとしただけなのにうっかりドラッグになってしまって別ウィンドウが開かれてムキー、という事がなくなってよかった。

とりあえず自分が把握してる限りでは、ツリー型タブ等でscrollbox内の方の「新しいタブ」ボタン(今回追加された奴)をdisplay: none;で消してるせいか、ボタンを再表示させた時や新しいタブを追加した時などにタブやボタンの並び順が盛大にぶっ壊れるようになった。display: -moz-box; visibility: collapse;にしておくとこの問題は起こらないっぽいので、次版ではそうする予定。(コードはもうコミットしてある

あと、gBrowser.mTabContainer.childNodesが返す内容がタブとは限らなくなった(どんな要素でもタブバー内に置けるようになったので)ということで、タブを取得するのにこのプロパティを使ってる人は一応気をつけといた方がいいと思う。てかtabbrowser要素のmTabs自体がこれを参照してるし、現実的にはタブ以外を置いたら色んな所がぶっ壊れる事が予想されるから「置くなよ! 絶対置くなよ!!」って言ってるのと同じだよなあ。まあ一応対応しとくけどさ……

またさらに気付いたけど、タブのnextSiblingpreviousSiblingタブでない値を返す可能性がある状態になってる。XBLのソースに埋め込まれてるコメントノードの位置もタブの間に何故か移動してしまったりする事があるようで、前後のタブをこのプロパティで参照してる場合には被害を受ける事になる。ここも注意が必要だ。

全然話は変わるけど。

アドオンで要素の表示・非表示をCSSのdisplayプロパティで制御するにあたって、display: none;で非表示にするのはセオリー通りで別にいいんだけど、表示させる時にdisplay: inline;とかdisplay: block;とかにしてる人がたまにいてもにょる。Web上のCSSではそれで正解なんだけど、XULでこれをやるとボックスの並び順がぶっ壊れたりレイアウトがおかしくなったりする事があるので、よっぽどの事情(タブバーを多段表示させる時とか)がない限りはあくまでdisplay: -moz-box;の方を使って欲しい。最近見かけたものではPathtraqがそうだった。

XUL要素の表示・非表示を制御するには大別して3つ、細かく分けると7つの方法がある。

  • 要素を完全に消す(レイアウトのフローから完全に除外する)
    • node.hidden = truenode.hidden = false
    • node.setAttribute('hidden', true)node.removeAttribute('hidden')
    • node.style.display = 'none'node.style.display = '-moz-box'
  • 表示上見えなくする(レイアウト上は幅・高さ0でその位置にある物として扱う)
    • node.collapsed = truenode.collapsed = false
    • node.setAttribute('collapsed', true)node.removeAttribute('collapsed')
    • node.style.visibility = 'collapse'node.style.visibility = 'visible'
  • 表示上見えなくする(レイアウト上もその位置に本来の幅・高さで要素がある物として扱うが、その領域には何も描画しない)
    • node.style.visibility = 'hidden'node.style.visibility = 'visible'

いくつかのXUL要素では、hiddenプロパティやcollapsedプロパティに真偽値を代入しても何も起こらないので、setAttribute()removeAttribute()とした方がより確実ではある。プロパティでの代入にせよDOMの属性値での指定にせよ、最終的にはCSSでの指定と同じ物として扱われる。xul.cssの頭の方を見れば、どういう事かよく分かると思う。

上の例でnode.setAttribute('hidden', false)ではなくnode.removeAttribute('hidden')と書いているのにも理由がある。テーマやアドオンの中には「要素のhidden属性の値がtrueであるかどうか」ではなく「hidden属性に何らかの値がセットされているかどうか」しか考えてない場合があって、falseを設定したのに非表示のままになってしまう、というような事がたまにあるから。collapsedにも同じ注意が必要。

XULの世界的には物凄く基本的な事なんだけど、HTML+CSSの世界から入ってきたばっかりの人はこの辺の事を知らないままでいるかもしれないので、一応書いてみた。

こういう事(why:何故そう書かねばならないか)って、アドオンの実際のコード(how:どう書いたらよいか)をいくら見てても分からないんだよなあ……ほんとXULは地獄だぜ。

エントリを編集します。

wikieditish message: Ready to edit this entry.











拡張機能