jQuery UI モーダルダイアログの仕組み

jQuery UI の Dialog 機能はダイアログをモーダル表示することができる。

サンプルを見ると、

  • 背景がグレーアウトされて、手前のダイアログしか操作できない
  • Tab キーを動かしてもダイアログからフォーカスを移せない

といった動作になっている。

いままでいろんなライブラリの擬似モーダル実装を見てきたが、Tab キーを押したらこっそり裏側の部分にフォーカスを移せるものばかりだったので、Tab キーにちゃんと対処していたところに驚いた。

どうやって実装してるんだろうと思って jquery.ui.dialog.js を見てみたら、次のように泥臭く実装していた。

    // prevent tabbing out of modal dialogs
    if (options.modal) {
        uiDialog.bind('keypress.ui-dialog', function(event) {
            if (event.keyCode !== $.ui.keyCode.TAB) {
                return;
            }

            var tabbables = $(':tabbable', this),
                first = tabbables.filter(':first'),
                last  = tabbables.filter(':last');

            if (event.target === last[0] && !event.shiftKey) {
                first.focus(1);
                return false;
            } else if (event.target === first[0] && event.shiftKey) {
                last.focus(1);
                return false;
            }
        });
    }

Tab キーが押されたら、ダイアログ外にフォーカスが移らないよう、無理やりダイアログ内にフォーカスを設定している。

ちなみに、ソース中に :tabbable という CSS 擬似クラスが登場しているが、これは jquery.ui.core.js で独自定義されているもので、標準の CSS や生の jQuery では利用できないので注意が必要だ。

フォーカスを無理やりなんとかするようなブラウザ拡張がインストールされていたら対処しきれないが、多くの場合ではこの実装で問題なさそうだ。