4

TL;博士;

有没有办法强制focus在网页的模态框中?

问题是:我有一个经典的网页,包含文本、链接和表单。当我单击页面中的一个特定链接时,会出现一个模式框(类似于fancyboxor jQuery.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();
    }
}
4

1 回答 1

1

我不会进入编码,因为你已经有了代码,我会向你解释它背后的逻辑。

如果您的页面包含以下元素,

元素 0(标签索引 1)--> 元素 1(标签索引 2)--> 元素 2(标签索引 3)

为了防止焦点消失,您基本上创建了一个循环。

当在 element0 上按下 tab 键时,它会像往常一样转到 element1。

但是当在 element2 上按下 tab 键时,您需要阻止浏览器的默认行为(通过 event.preventDefault()),即转到 tabindex 较高的元素并将焦点放在 element0 上。

在 element0 上按下 shift+ tab 的方式相同,您需要阻止浏览器的默认行为(event.preventDefault())并手动将焦点放在 element2 上。

通过这种方式,您可以创建一个循环,使焦点永远不会向外。

于 2013-05-29T16:55:21.173 回答