splitmenu のUIがダメダメで萎えた

拡張開発でFirefox4から使用できる、Firefoxボタンにも使用されているsplitmenuを使ってみた。
が、微妙すぎて萎えた。

splitmenuは、単なるメニューとは違い、自身をクリックすれば相応のコマンドが発行され、少しポインタを重ねておけば、子のメニューがポップアップされて表示されるというもの。

経緯として、僕はPanoという拡張機能を開発していて、これは他のタブグループへのアクセス性を高めようという狙いの拡張機能なんだけど、「タブグループ」→「配下のタブ」と選択するところを「タブグループ」をクリックしてもスイッチできるようにしたいよねってことでsplitmenuを使ってみようと思い立った。

が、UIが残念すぎる。

  1. 元メニューと重なる(メニュー配下のポップアップが右側に収まらなくて折り返す時)
  2. 該当メニュー以外のポップアップが閉じない場合がある
  3. キーボード操作できない
  4. commandイベントがバブリングされない

元メニューと重なる


これは自分が作っているPanoという拡張でsplitmenuを使ってみたキャプチャ画像。タブ一覧のボタンを拡張して「他グループ」のリストを出しているところ。

「タブ一覧」ボタン → 「他グループ」 → 「グループ名1」(ここがsplitmenu) → 「Firefox 4 for developers -...」と選択している図である。元々のボタンがFirefoxのウィンドウの右端なので画面右端にどうしても近くなり折り返ししてポップアップされる。

んで、そのポップアップと「グループ名1」のメニューが被ってしまって自分が何を選択したのか分からない。

該当メニュー以外のポップアップが閉じない

上図で、GitHubへのメニューが一番トップにあるポップアップの背後に見えている。一度5番目のsplitmenuのポップアップを表示させた後、1番目にポインタを合わせるとこうなる。ポップアップが表示されたままで閉じないのだ。

メニューがぐちゃぐちゃと重なって意味不明な感じになっている。

キーボード操作できない

普通のメニューなら,,,,Enter等で操作ができるのだが、splitmenuでは不可。

commandイベントがバブリングされない

XUL開発者ならお馴染みのcommandイベント。splitmenu内のXBLで

 <xul:menu ....
           oncommand="event.stopPropagation();">

としているので、バブリングフェーズで、これ以上親要素へイベントが伝播しない。

以下の様にバブリングを利用してイベントが発行された時の動作を一つにまとめようとした時、event.stopPropagation()により阻止されてしまう。

<menu label="他グループ" oncommand="doCommand(event);">
  <menupopup>
    <splitmenu label="foobar">
      <menupopup>
        <menuitem label="tab 1"/>
        <menuitem label="tab 2"/>
      </menupopup>
    </splitmenu>
  </menupopup>
</menu>
function doCommand (aEvent) {
  var target = aEvent.target;
  if (target.localName == "hbox") {
    // splitmenu の動作 
  } else if (target.localName == "menuitem") {
    // 配下の menuitem の動作
  }
}

一個一個oncommandを定義するのは非常に億劫なのだが...