jQuery:当焦点离开元素的子元素时检测,然后将焦点返回到触发元素

时间:2012-10-10 14:52:02

标签: javascript jquery

我有一个模态窗口脚本,我们正在努力提高可访问性要求。要求说当你离开窗户时,它应该关闭。它还说,在解除窗口时,原始触发元素必须重新聚焦。

在做了一些挖掘后,我发现了这个:jQuery figuring out if parent has lost 'focus'。当你从窗口中跳出标签时,最简单的方法就是跟踪focusin事件,当焦点触发一个不是open模式子元素的元素时,关闭窗口。然而,这种方法是有问题的,因为你会看到(更不用说我的喜欢有点太重了)。以下是处理此问题的代码:

$('body').focusin(function(e) {
        if (!$(e.target).parent().is('.current-window')) {
            closeModal();
        }
    });

和关闭窗口的函数:

function closeModal() {
        $('.modal-mask, .current-window').fadeOut('fast', function(){
            $(this).removeClass('current-window');
            $('.modal-mask').removeAttr('style');
            $('.modal-trigger').focus();
        });
    }

现在显然,当我运行此代码时,closeModal()在focusin事件之间来回触发直到最大调用堆栈,因此在将焦点提供给触发元素之前会抛出“超出最大调用堆栈”错误消息。 / p>

有关完整代码,请参阅此小提琴:http://jsfiddle.net/pbredenberg/wxX4T/

我正在尝试考虑一种更好的方法来处理这个要求,或者至少避免无限循环。有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:0)

我仍然无法发表评论,因此我必须将此作为答案提交: 为什么不跟踪你是否真的关闭了像window.closing这样的bool var的窗口? 我更新了示例:http://jsfiddle.net/kevkong/wxX4T/8/ 这是你打算做什么的吗?

答案 1 :(得分:0)

每当您打开模态时,都会存储对单击元素的引用。然后当模态关闭时,您可以检索它并重新聚焦元素。

工作演示: http://jsfiddle.net/wxX4T/12/

function closeModal(e) {
    if (e) e.preventDefault();

    // Rather than using a .current-window class
    // we can use the jQuery :visible pseudo-selector
    var $window = $(".window:visible");

    // Get our refernce to the focus target that was 
    // stored when the window was open.
    var $trigger = $window.data("focusTarget");

    // Close the window and mask
    $('.modal-mask, .window').fadeOut('fast', function() {
        // Focus on the original trigger
        $trigger.focus();
    });
}

$('.modal').click(function(e) {
    e.preventDefault();

    var $trigger = $(this);
    var $modal = $($trigger.attr("href")).fadeIn(300)
    $('.modal-mask').fadeIn(200);

    // I have omitted all the code that positions
    // the window (for the sake of clarity)
    // Feel free to add it back.
    // Store a reference to the trigger link in the modal's "data" hash 
    // so that when we close it later, we can retrieve the original 
    // trigger that opened the window.
    $modal.data("focusTarget", $trigger);
});


// Trigger window close based on Tab key
$(document).on("keydown", function(e) {
    // Only close modal if the tab key is pressed
    // AND if there is a visible modal window.
    if ((e.keyCode || e.which) === 9 && $(".window:visible").length > 0) {
        e.preventDefault();
        closeModal();
    }
});

$(document).on("click", ".window .close", closeModal);

$(document).on("click", ".modal-mask", function() {
    $(this).hide();
    closeModal();
});​