如何强制将焦点集中在网页上的模态框上

4

TL;DR;

有没有办法强制在网页的模态框内设置焦点?点击页面中的特定链接时,会出现一个模态框(类似于fancyboxjQuery.ui.dialog),包含链接和表单元素。如果用户使用"tab"键,则可以将焦点放在页面上的每个元素上,包括模态框内部和外部的元素。如果可能的话,我想在CSS或JavaScript中强制将焦点保持在模态框内。

我知道这是可能的,因为jQuery.ui.dialog可以使用modal选项来实现,以下是一个示例http://jsfiddle.net/pomeh/QjLJk/1/show/。我试图查看源代码,但我没有确切地了解它的工作原理。以下是我找到的jQuery UI源代码中解决此问题的代码:

this.document.bind( "focusin.dialog", function( event ) {
    if ( !that._allowInteraction( event ) ) {
        event.preventDefault();
        $(".ui-dialog:visible:last .ui-dialog-content")
            .data( widgetFullName )._focusTabbable();
    }
});

_allowInteraction: function( event ) {
    if ( $( event.target ).closest(".ui-dialog").length ) {
        return true;
    }

    // TODO: Remove hack when datepicker implements
    // the .ui-front logic (#8989)
    return !!$( event.target ).closest(".ui-datepicker").length;
},

_focusTabbable: function() {
    // Set focus to the first match:
    // 1. First element inside the dialog matching [autofocus]
    // 2. Tabbable element inside the content element
    // 3. Tabbable element inside the buttonpane
    // 4. The close button
    // 5. The dialog itself
    var hasFocus = this.element.find("[autofocus]");
    if ( !hasFocus.length ) {
        hasFocus = this.element.find(":tabbable");
    }
    if ( !hasFocus.length ) {
        hasFocus = this.uiDialogButtonPane.find(":tabbable");
    }
    if ( !hasFocus.length ) {
        hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
    }
    if ( !hasFocus.length ) {
        hasFocus = this.uiDialog;
    }
    hasFocus.eq( 0 ).focus();
}


keydown: function( event ) {
    if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
            event.keyCode === $.ui.keyCode.ESCAPE ) {
        event.preventDefault();
        this.close( event );
        return;
    }

    // prevent tabbing out of dialogs
    if ( event.keyCode !== $.ui.keyCode.TAB ) {
        return;
    }
    var tabbables = this.uiDialog.find(":tabbable"),
        first = tabbables.filter(":first"),
        last  = tabbables.filter(":last");

    if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
        first.focus( 1 );
        event.preventDefault();
    } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
        last.focus( 1 );
        event.preventDefault();
    }
}
1个回答

1
我不会讲解编码,因为您已经有了代码,我将向您解释其逻辑。
如果您的页面具有以下元素,
element0(tabindex 1)--> element1(tabindex 2)--> element2(tabindex 3)
为了防止焦点离开,您需要创建一个循环。
当在element0上按下tab键时,它会像通常一样转到element1。
但是当在element2上按下tab键时,您需要防止浏览器的默认行为(通过event.preventDefault()),即转到tabindex更高的元素,并将焦点给予element0。
同样,当在element0上按下shift+ tab键时,您需要防止浏览器的默认行为(通过event.preventDefault()),并手动将焦点给予element2。
通过这种方式,您可以创建一个循环,使焦点永远不会超出范围。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接