【问题标题】:How to lock focus in a specific div using javascript/jquery [duplicate]如何使用 javascript/jquery 将焦点锁定在特定 div [重复]
【发布时间】:2011-10-17 14:05:46
【问题描述】:

我正在使用 jQuery 开发某种模式弹出窗口,但焦点存在一些问题。

现在发生的情况是,当我按下 Tab 键时,焦点转到隐藏在弹出窗口后面的控件。

有没有办法强制焦点只停留在弹出窗口中的控件上?

【问题讨论】:

  • 您可以将onblur="this.focus()" 之类的内容放在弹出窗口的任何控件中,尽管这会将焦点锁定在当前选择的任何内容上。需要更多代码来确定是否应该允许任何获得焦点的内容获得焦点。
  • 谢谢,但是,这对我不起作用,因为我必须遵守 WCAG 2.0 AA 准则,并且所有控件都应该可以使用键盘访问。
  • 那你就自相矛盾了。 “不允许访问控件,但所有控件都必须是可访问的”。
  • 我希望在打开窗口时将焦点包含在弹出窗口内。当窗口关闭时,应该可以使用键盘访问其他控件。
  • 所以它是一个实际的弹出窗口,就像在一个新的浏览器窗口中一样?或者它是一个仍然包含在原始页面中的 jQuery 模式弹出窗口?

标签: javascript jquery


【解决方案1】:

有。您基本上需要在按下 Tab 键时进行监听,以便做出相应的响应。使用 jQuery,这是一般结构:

$(window).keydown(function(e){
    if(e.which ===9){ //it's the tab key!
        //do whatever you want here.

        e.preventDefault();
    }
});

你把你的自定义代码放在我评论do whatever you want here的地方,然后用e.preventDefault阻止默认操作(例如将焦点跳转到隐藏控件);

【讨论】:

  • 不行,tabkey还是要工作的,但只能在弹出的div上。
  • 对,这就是为什么你“在这里做任何你想做的事”。所以你可以检查当前哪个控件有焦点,然后在你想移动到的控件上调用“focus()”。
【解决方案2】:

您总是可以考虑删除tab 键的默认操作,有一个关于如何执行此操作的小教程here

但是,这是针对 entertab 键,但是如果您还查看 here,您会看到 tab 键是键号 9。因此,如果我们将代码更改为仅删除tab 键的默认操作您的行将类似于

    if ( key == 9 ) { }

而不是

    if ( key == 3 || key == 9 || key == 13 ) { }

编辑

好的,既然您已经声明您不想阻止tab 键的默认操作,但您仍然希望阻止该键关注模态窗口下方的元素。

我现在唯一能想到的是,检查用户是否专注于您的最后一个字段example 1/example 2(您可以将这些链接到您的最后一个输入/文本区域/复选框/收音机)。如果是这样,您可以做 2 件事中的 1 件事:

1) 使用上面的代码并阻止默认操作,从而阻止使用专注于模态下方的元素。

2) 重新关注模态窗口中的第一个字段,first_field.focus();

据我所知,通过坚持您的要求,第二选择是您的最佳选择。

【讨论】:

  • 不行,tabkey还是要工作的,但只能在弹出的div上。
【解决方案3】:

最后,我得到了以下解决方案:

当窗口打开时,我将所有不在弹出窗口中的元素的 tabindexes 保存在 jQuery.data 中,并将焦点设置到窗口的第一个元素。

然后,对于所有这些元素,我将 tabindex 设置为 -1,以防止使用 tab 键访问它们。

当窗口关闭时,我将所有 tabindex 恢复为之前的值。

【讨论】:

  • 我不明白。当您使用tabindex="-1" 时,使用tab 的元素不是可聚焦的吗?
  • 不,当tabindex="-1"时,元素不可聚焦。
【解决方案4】:

试试here。只是阻止用户按 Tab,否则您将不得不遍历您的字段并在它们上设置标签索引。

【讨论】:

  • 不行,tabkey还是要工作的,但只能在弹出的div上。
  • 我建议在窗口打开时使用 display:none 隐藏所有有问题的输入,浏览器不会选择它看不到的输入
【解决方案5】:

我使用添加到所有输入标签的通用焦点事件,当事件被触发时,我确定父 div 的 z-index 如果它高于预定阈值(例如 9950)然后我允许焦点,如果下面我防止焦点。为了防止焦点,我通过在适当的 div 中找到一个控件并在该项目上调用 .focus() 来做到这一点。

下面的伪代码。

$('input').bind('focus', function() 
{ 
 if ($(this).parents('div:first').css('z-index') <  9950) 
 {
    //prevent focus here
    //usually by finding a suitable target and setting focus
   $('input:first', $('.myModalClass')).focus(); 
 }
}); 

ps。还要在项目上设置 tabindex,以便“模态”窗口中的项目在选项卡索引中紧随其后。只是让事情变得更清洁

【讨论】:

    【解决方案6】:

    我遇到了类似的问题并创建了这个微型 jQUEeryUI 插件。简单地使用它(如果需要,在页面上的多个位置),这将使 TAB 或 shift+TAB 仅在 .someGroup 包装器内迭代。

    $(".someGroup").tabGuard();

    这里有更多内容,希望对某人有所帮助:

    http://tomaszegiert.seowebsolutions.com.au/tabguard/index.htm

    【讨论】:

      【解决方案7】:

      我想我可能有一个更好的解决方案来解决您的问题,它不涉及禁用选项卡或不必跟踪/禁用其他元素。不过它确实需要 jQueryUI。

      <div id="modalBgCover">
          <div onfocus="$(this).next('div').find(':tabbable').last().focus();" tabindex="0"></div>
          <div id="modal">
              <input id="input1">
              <input id="input2">
          </div>
          <div onfocus="$(this).prev('div').find(':tabbable').first().focus();" tabindex="0"></div>
      <div>
      

      这样做是创建两个可选项(但没有内容,因此不可见)的 div,它们获取并重定向焦点。

      将最后一个输入切换到底部 div 会将焦点返回到模态中的第一个可选项元素,同样,shift+tab 到顶部 div 会将焦点返回到模态中的底部输入。

      modalBgCover 用半透明层覆盖页面,防止点击通过。

      【讨论】:

        【解决方案8】:

        我已经实现了基于收集知识的迷你框架,包括这篇文章中的答案。

        它使用 JQuery UI。

        欢迎改进。

        这是框架对象:

        var TabLim = {};
        
        TabLim.activate = function(el) {
            TabLim.deactivate();
        
            TabLim._el = el;
        
            $(window).on('keydown', TabLim._handleTab);
        
            return TabLim;
        };
        
        TabLim.deactivate = function() {
            TabLim._el = null;
        
            // detach old focus events
            TabLim._detachFocusHandlers();
        
            TabLim._els = null;
            TabLim._currEl = null;
        
            $(window).off('keydown', TabLim._handleTab);
        
            return TabLim;
        };
        
        TabLim.setFocus = function(prev) {
            // detach old focus events
            TabLim._detachFocusHandlers();
        
            // scan for new tabbable elements
            var tabbables = TabLim._el.find(':tabbable');
            TabLim._els = [];
        
            // wrap elements in jquery
            for ( var i = 0; i < tabbables.length; i++) {
                var el = $(tabbables[i]);
                // set focus listener on each element
                el.on('focusin', TabLim._focusHandler);
                TabLim._els.push(el);
            }
        
            // determine the index of focused element so we will know who is
            // next/previous to be focused
            var currIdx = 0;
            for ( var i = 0; i < TabLim._els.length; i++) {
                var el = TabLim._els[i];
        
                // if focus is set already on some element
                if (TabLim._currEl) {
                    if (TabLim._currEl === el[0]) {
                        currIdx = i;
        
                        prev ? currIdx-- : currIdx++;
                        break;
                    }
        
                } else {
                    // focus is not set yet.
                    // let's set it by attribute "autofocus".
                    if (el.attr('autofocus') !== undefined) {
                        currIdx = i;
                        break;
                    }
                }
            }
        
            if (currIdx < 0) {
                currIdx += TabLim._els.length;
            }
            if (TabLim._els.length) {
                TabLim._els[Math.abs(currIdx % TabLim._els.length)].focus();
            }
        
            return TabLim;
        };
        
        TabLim._handleTab = function(e) {
            if (e.which === 9) {
                e.preventDefault();
        
                TabLim.setFocus(e.shiftKey);
            }
        };
        
        TabLim._focusHandler = function(e) {
            TabLim._currEl = e.currentTarget;
        };
        
        TabLim._detachFocusHandlers = function() {
            if (TabLim._els) {
                for ( var i = 0; i < TabLim._els.length; i++) {
                    TabLim._els[i].off('focusin', TabLim._focusHandler);
                }
            }
        };
        

        使用方法:

        1) 激活以限制对特定 div 的关注

        TabLim.activate($('.yourDic')).setFocus();
        

        2) 停用

        TabLim.deactivate();
        

        【讨论】:

          【解决方案9】:

          当您打开模态弹出窗口时,如果您试图在他们最初按下“tab”键时将焦点放在第一个输入上,那么一个非常简单的解决方案是将焦点放在模态弹出窗口中的第一个输入上窗口然后只需将 .blur() 应用于相同的输入。然后,当您点击“标签”时,它将开始关注该表单。

          $("#modalTestInput").focus();
          $("#modalTestInput").blur();
          

          如果您试图删除任何专注于模态弹出窗口后面的输入的能力,那么将tabindex = "-1" 应用于模态弹出窗口之外的输入的解决方案绝对是可行的方法。

          只是觉得您可能对更简单的解决方案感兴趣。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-12-29
            • 2016-12-31
            • 2020-03-06
            • 2023-03-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多