How can restrict the tab key press only within the modal popup when its open?

放肆的年华 提交于 2019-12-05 09:54:53

You are asking about focus trap, it's nicely demonstrated in this demo: http://davidtheclark.github.io/focus-trap/demo/

Adding role="dialog" will not automatically provide trap the focus within that element. In fact, there's no native focus trap provided by browsers.

You need to go with one of following options:

be careful of any method relying only on javascript events as it won't correctly handle screenreaders

However, this cannot be achieved without javascript like already indicated in multiple questions like How to keep focus within modal dialog?

You have three steps to do:

1. disable screenreader interaction with any other nodes by setting aria-hidden=true on them

For instance:

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

2. disable any keyboard interaction with them

This has to be done in Javascript / or jQuery.

This is a one-liner instruction in jQuery, using jquery-ui

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

The reverse can be achieved using:

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

3. remove any pointer event for those elements to disable mouse interaction

css sample:

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

Here's my solution. It traps Tab or Shift+Tab as necessary on first/last element of modal dialog (in my case found with role="dialog"). Eligible elements being checked are all visible input controls whose HTML may be 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;
});

Right now also Angular CDK provides directive to add focus trap to the modal popup https://material.angular.io/cdk/a11y/api#CdkTrapFocus

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!