【问题标题】:Preventing tab to cycle through address bar防止选项卡循环浏览地址栏
【发布时间】:2013-03-12 07:56:51
【问题描述】:

我意识到这可能是一个可访问性问题,最好不要管它,但我想弄清楚是否有可能阻止标签在标签循环中访问地址栏。

我的应用程序有另一种循环输入区域的方法,但许多新用户本能地尝试使用该选项卡,但并没有按预期工作。

【问题讨论】:

  • 我不会管它的。一个简单的解决方案是让您的应用程序在弹出窗口中启动。然后你可以通过location=no隐藏地址字段。

标签: browser user-interface accessibility


【解决方案1】:

这是一个通用的 jquery 实现,您不必查找最大选项卡索引。请注意,如果您在 DOM 中添加或删除元素,此代码也将起作用。

$('body').on('keydown', function (e) {
    var jqTarget = $(e.target);
    if (e.keyCode == 9) {

        var jqVisibleInputs = $(':input:visible');
        var jqFirst = jqVisibleInputs.first();
        var jqLast = jqVisibleInputs.last();

        if (!e.shiftKey && jqTarget.is(jqLast)) {
            e.preventDefault();
            jqFirst.focus();
        } else if (e.shiftKey && jqTarget.is(jqFirst)) {
            e.preventDefault();
            jqLast.focus();
        }
    }
});

但是,您应该注意,上面的代码仅适用于可见输入。某些元素即使没有被输入也可能成为文档的 activeElement,因此如果是您的情况,您应该考虑将它们添加到 $(':input:visible') 选择器中。

我没有添加代码来滚动到焦点元素,因为这可能不是每个人都想要的行为......如果你需要它,只需在调用 focus() 之后添加它

【讨论】:

  • 谢谢,这很有帮助!在我找到并尝试了你的代码之前,我试图让它工作一段时间,效果很好!
【解决方案2】:

我曾经在 tabindex 1 和最后一个 tabindex 上添加两个微小的、不可见的元素。为这两个添加一个 onFocus:tabindex 为 1 的元素应该聚焦最后一个真实元素,具有 max tabindex 的元素应该聚焦第一个真实元素。确保将第一个真实元素集中在 Dom:loaded 上。

【讨论】:

    【解决方案3】:

    您可以使用全局 tabindex attribute 控制跳格顺序(以及哪些元素应该能够获得焦点)。

    但是,您不能阻止用户使用此属性进入另一个不受页面控制的上下文(例如浏览器的地址栏)。 (不过,它可能与 JavaScript 结合使用。)

    对于这种(邪恶的!)用例,您必须查看键盘陷阱

    WCAG 2.0 有指导方针:2.1.2 No Keyboard Trap。在Understanding SC 2.1.2,您可以找到本指南的“技术和故障”:

    所以也许你对这样的陷阱怎么可能有一些想法。

    【讨论】:

    • 我同意 unor,但我会不惜一切代价避免使用tabindex。如果您向页面添加新元素并忘记向其添加 tabindex,则使用 AT 或键盘导航的人将永远无法访问它。
    【解决方案4】:

    您可以使用 Javascript 并在具有最高“tabindex”的元素上捕获“keydown”事件。如果用户在没有“Shift”键 (event.shiftKey == false) 的情况下按下“TAB”键 (event.keyCode==9),则只需将焦点设置在 tabindex 最低的元素上。

    然后,您还需要对具有最低 tabindex 的元素执行相同的操作。捕获此元素的“keydown”事件。如果用户使用“Shift”键 (event.shiftKey == true) 按下“TAB”键 (event.keyCode==9),则将焦点设置在 tabindex 最高的元素上。

    这将有效地防止使用 TAB 键聚焦地址栏。我正在我当前的项目中使用这种技术。

    如果按下了正确的组合键,不要忘记取消 keydown 事件!对于 JQuery,它是“event.preventDefault()”。在标准 Javascript 中,我相信您只是“返回 false”。

    这是我正在使用的一个 JQuery-laden sn-p...

        $('#dos-area [tabindex=' + maxTabIndex + ']').on('keydown', function (e) {
            if (e.keyCode == 9 && e.shiftKey == false) {
                e.preventDefault();
                $('#dos-area [tabindex=1]').focus();
            }
        });
        $('#dos-area [tabindex=1]').on('keydown', function (e) {
            if (e.keyCode == 9 && e.shiftKey == true) {
                e.preventDefault();
                $('#dos-area [tabindex=' + maxTabIndex + ']').focus();
            }
        });
    

    另外请记住,设置 tabindex=0 会对事物聚焦的顺序产生不良影响。我一直记得(出于我的目的)tabindex 是一个从 1 开始的索引。

    【讨论】:

    【解决方案5】:

    您好,我有一个简单的解决方案。只需在页面末尾放置一个空跨度。给它一个 id 和 tabindex = 0,给这​​个跨度一个 onfocus 事件,当触发时让你的焦点跳转到你想要循环通过的页面上的第一个元素。这样您就不会失去对文档的关注,因为如果您这样做了,您的事件将不再起作用。

    【讨论】:

      【解决方案6】:

      我使用了m-albert 解决方案,它有效。但就我而言,我不控制 tabindex 属性。我的意图是当用户离开页面上的最后一个控件时,将焦点设置在页面顶部的工具栏上(第一个控件)

      $(':input:visible').last().on('keydown', function (e) {
          if (e.keyCode == 9 && e.shiftKey == false) {
              e.preventDefault();
              $('html, body').animate({
                  scrollTop: 0
              }, 500);
              $(':input:visible', context).first().focus();
          }
      });
      

      context 可以是任何 Jquery 对象、选择器,甚至是文档,也可以省略。

      滚动动画当然是可选的。

      【讨论】:

        【解决方案7】:

        不确定这是否仍然是一个问题,但我实现了自己的不使用 jQuery 的解决方案,可以在所有元素的 tabindex="0" 以及 DOM 可能发生变化的情况下使用。如果您想将 tabcycling 限制为包含 tabindex 元素的特定元素,我为上下文添加了一个额外的参数。

        关于论点的一些简要说明:

        min 必须小于或等于 ma​​x,并且 contextSelector 是一个可选字符串,如果使用它应该是一个有效的选择器。如果 contextSelector 是无效选择器或选择器不匹配任何元素,则使用 document 对象作为上下文。

        function PreventAddressBarTabCyle(min, max, contextSelector) {
            if( isNaN(min) ) throw new Error('Invalid argument: first argument needs to be a number type.')
            if( isNaN(max) ) throw new Error('Invalid argument: second argument needs to be a number type.')
            if( max < min ) throw new Error('Invalid arguments: first argument needs to be less than or equal to the second argument.')
            min = min |0;
            max = max |0;
            var isDocumentContext = typeof(contextSelector) != 'string' || contextSelector == '';
        
            if( min == max ) {
                var tabCycleListener = function(e) {
                    if( e.keyCode != 9 ) return;
        
                    var context = isDocumentContext ? document : document.querySelector(contextSelector);
                    if( !context && !('querySelectorAll' in context) ) {
                        context = document;
                    }
        
                    var tabindexElements = context.querySelectorAll('[tabindex]');
                    if( tabindexElements.length <= 0 ) return;
                    var targetIndex = -1;
                    for(var i = 0; i < tabindexElements.length; i++) {
                        if( e.target == tabindexElements[i] ) {
                            targetIndex = i;
                            break;
                        }
                    }
                    // Check if tabbing backward and reached first element
                    if( e.shiftKey == true && targetIndex == 0 ) {
                        e.preventDefault();
                        tabindexElements[tabindexElements.length-1].focus();
                    }
                    // Check if tabbing forward and reached last element
                    if( e.shiftKey == false && targetIndex == tabindexElements.length-1 ) {
                        e.preventDefault();
                        tabindexElements[0].focus();
                    }
                };
            } else {
                var tabCycleListener =  function(e) {
                    if( e.keyCode != 9 ) return;
        
                    var context = isDocumentContext ? document : document.querySelector(contextSelector);
                    if( !context && !('querySelectorAll' in context) ) {
                        context = document;
                    }
        
                    var tabindex = parseInt(e.target.getAttribute('tabindex'));
                    if( isNaN(tabindex) ) return;
                    // Check if tabbing backward and reached first element
                    if (e.shiftKey == true && tabindex == min) {
                        e.preventDefault();
                        context.querySelector('[tabindex="' + max + '"]').focus();
                    } 
                    // Check if tabbing forward and reached last element
                    else if (e.shiftKey == false && tabindex == max) {
                        e.preventDefault();
                        context.querySelector('[tabindex="' + min + '"]').focus();
                    }
                };
            }
            document.body.addEventListener('keydown', tabCycleListener, true);
        }
        

        更多注释:

        如果 min 等于 ma​​x,则标签循环将自然发生,直到到达上下文中的最后一个元素。如果 min 严格小于 ma​​x,则跳格会自然循环,直到达到 minma​​x .如果向后跳格并达到 min,或向前跳格并达到 ma​​x,则跳格将循环到 min 元素或 ma​​x 元素。

        示例用法:

        // For all tabindex elements inside the document
        PreventAddressBarTabCyle(0,0);
        // Same as above
        PreventAddressBarTabCyle(1,1);
        // NOTE: if min == max, the tabindex value doesn't matter
        //    it matches all elements with the tabindex attribute
        
        // For all tabindex elements between 1 and 15
        PreventAddressBarTabCyle(1,15);
        // For tabindex elements between 1 and 15 inside
        //   the first element that matches the selector: .some-form
        PreventAddressBarTabCyle(1,15, '.some-form');
        // For all tabindex elements inside the element
        //   that matches the selector: .some-form2
        PreventAddressBarTabCyle(1,1, '.some-form2');
        

        【讨论】:

          【解决方案8】:

          Salinan solution worked for me 把它放在你的 html 页面的开头:

          <span tabindex="0" id="prevent-outside-tab"></span>
          

          这在你的 html 页面的末尾。:

          <span tabindex="0" onfocus="foucsFirstElement()"></span>
          

          foucsFirstElement():

          foucsFirstElement() {
            document.getElementById("prevent-outside-tab").focus();
          },
          

          【讨论】:

            猜你喜欢
            • 2011-12-08
            • 1970-01-01
            • 2013-08-06
            • 2016-10-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-04-27
            • 1970-01-01
            相关资源
            最近更新 更多