web-dev-qa-db-ja.com

モーダルポップアップが開いているときにのみタブキーの押下を制限するにはどうすればよいですか?

モーダルポップアップを開きました。アクセシビリティ要件があります。そこで、ARIA関連のラベルを追加しました。しかし、Tabキーをクリックすると、実際のページの後ろのページに移動し続けます。

htmlファイルにrole = "dialog"を追加

しかし、モーダルが開いたとき、私はフォーカスだけがモーダルポップアップ内をナビゲートしたいです。

取りかかっている Angular4, HTML5 事業。 HTMLファイル自体の中に解決策が見つかった方が良いこれを防ぐためにjavascript/jQuery関連のものを追加しないことを意味します

5
Prince

あなたはフォーカストラップについて質問しています、それはこのデモでうまく示されています: http://davidtheclark.github.io/focus-trap/demo/

role="dialog"を追加しても、その要素内にフォーカスをトラップすることは自動的には行われません。実際、ブラウザによって提供されるネイティブフォーカストラップなしがあります。

次のいずれかのオプションを選択する必要があります。

  • 自分でフォーカストラップを実装する
  • フォーカストラップのサードパーティソリューションを使用します。 https://github.com/davidtheclark/focus-trap
  • モーダルウィンドウのサードパーティソリューションを使用します。 https://github.com/sweetalert2/sweetalert2 これはWAI-ARIA仕様と完全に互換性があり、フォーカストラップを提供します
5
Limon Monte

スクリーンリーダーを正しく処理しないため、JavaScriptイベントのみに依存するメソッドには注意してください。

ただし、これは、 モーダルダイアログ内でフォーカスを維持する方法は? のような複数の質問ですでに示されているようなJavaScriptなしでは達成できません。

実行する3つのステップがあります。

1.ノードにaria-hidden=trueを設定して、他のノードとのスクリーンリーダーの相互作用を無効にします

例えば:

<main aria-hidden="true"><!-- main content here--></main>
<dialog>Your dialog here</dialog>

2.キーボードとのやり取りを無効にします

これは、Javascript /またはjQueryで実行する必要があります。

これは、jquery-uiを使用したjQueryのワンライナー命令です。

$("main :focusable").addClass("disabled").attr("tabindex", -1);

逆は、次を使用して実現できます。

$(".disabled").removeClass("disabled").attr("tabindex", 0);

3.これらの要素のポインタイベントを削除して、マウスの相互作用を無効にします

cssサンプル:

main[aria-hidden='true'] { pointer-events: none;}
3
Adam

これが私の解決策です。モーダルダイアログの最初/最後の要素で必要に応じてTabまたはShift + Tabをトラップします(私の場合はrole="dialog"で見つかります)。チェックされる適格な要素は、HTMLがinput,select,textarea,buttonである可能性のあるすべての表示可能な入力コントロールです。

$(document).on('keydown', function(e) {
    var target = e.target;
    var shiftPressed = e.shiftKey;
    // If TAB key pressed
    if (e.keyCode == 9) {
        // If inside a Modal dialog (determined by attribute role="dialog")
        if ($(target).parents('[role=dialog]').length) {                            
            // Find first or last input element in the dialog parent (depending on whether Shift was pressed). 
            // Input elements must be visible, and can be Input/Select/Button/Textarea.
            var borderElem = shiftPressed ?
                                $(target).closest('[role=dialog]').find('input:visible,select:visible,button:visible,textarea:visible').first() 
                             :
                                $(target).closest('[role=dialog]').find('input:visible,select:visible,button:visible,textarea:visible').last();
            if ($(borderElem).length) {
                if ($(target).is($(borderElem))) {
                    return false;
                } else {
                    return true;
                }
            }
        }
    }
    return true;
});
1
gene b.

現在もAngular CDKは、モーダルポップアップにフォーカストラップを追加するディレクティブを提供しています https://material.angular.io/cdk/a11y/api#CdkTrapFocus

0
Stefan

親ダイアログ要素には、これがダイアログであることを示すrole="dialog"が必要です。あなたの場合、フォーカスがモーダル内にのみ留まるべきであることをブラウザとスクリーンリーダーに伝えるaria-modal="true"もありません。

aria-modal="true"を使用すると、スクリーンリーダーから非表示にし、モーダルが開いている間はモーダルの外側でキーボードフォーカスを受け取らないようにする必要がある要素に、aria-hidden="true"を追加する必要がなくなります。

上記の方法が機能しない場合でも、キーボードがモーダルを離れないように、モーダルの外側の親要素にaria-hidden="true"を使用することをお勧めします。

それでも機能せず、キーボードフォーカスを手動で制御する必要がある場合は、モーダル外でキーボードフォーカスを受け取る要素を確認してから、tabindex属性をtabindex="-1"に設定できます。つまり、フォーカスを受け取ることはできますが、受け取ることはできません。キーボードから。このアプローチでは、モーダルが閉じたときに、これらの要素からtabindex="-1"を削除するか、tabindex="0"に戻すことで機能を復元する必要があるため、注意が必要です。

出典: W3C wai ariaプラクティス-例を含むダイアログモーダル

0
Shahar

モーダルの入力要素のみを循環する非jqueryソリューション


// place this line in the dialog show function - to only add the listener when the dialog is shown
window.addEventListener('keydown', handleKey);

// uncomment and place this in the dialog close/hide function to remove the listener when dialog is closed/hidden
// window.removeEventListener('keydown', handleKey);

function handleKey(e) {
    if (e.keyCode === 9) {
        let focusable = document.querySelector('#modal').querySelectorAll('input,button,select,textarea');
        if (focusable.length) {
            let first = focusable[0];
            let last = focusable[focusable.length - 1];
            let shift = e.shiftKey;
            if (shift) {
                if (e.target === first) { // shift-tab pressed on first input in dialog
                    last.focus();
                    e.preventDefault();
                }
            } else {
                if (e.target === last) { // tab pressed on last input in dialog
                    first.focus();
                    e.preventDefault();
                }
            }
        }
    }
}
0
lilotop