【问题标题】:Simulating a tab keypress using JavaScript使用 JavaScript 模拟 tab 按键
【发布时间】:2010-10-16 16:46:31
【问题描述】:

我想让浏览器的行为就像用户在点击某物时按下了 Tab 键一样。在点击处理程序中,我尝试了以下方法:

var event = document.createEvent('KeyboardEvent');
event.initKeyEvent("keypress", true, true, null, false, false, false, false, 9, 0);
this.input.focus()[0].dispatchEvent(event);

还有 jQuery:

this.input.focus().trigger({ type : 'keypress', which : 9 });

...我取自 here

第一种方法似乎是最好的选择,但不太奏效。如果我将最后两个参数更改为 98、98,实际上,在输入框中输入了一个“b”。但是 9, 0 和 9, 9(我直接从 MDC 网站获取的前者)在 FF3 下的 firebug 中都给了我这些错误:

Permission denied to get property XULElement.popupOpen
[Break on this error] this.input.focus()[0].dispatchEvent(event);

Permission denied to get property XULElement.overrideValue
[Break on this error] this.input.focus()[0].dispatchEvent(event);

Permission denied to get property XULElement.selectedIndex
[Break on this error] this.input.focus()[0].dispatchEvent(event);

Permission denied to set property XULElement.selectedIndex
[Break on this error] this.input.focus()[0].dispatchEvent(event);

我听说此类(没有明确定义“此类”)事件是“不受信任的”,这可能解释了这些错误。

第二种方法会导致我作为 event.which 输入的任何值都作为 event.which 传递,但没有效果(即使我使用 98 而不是 9,也不会在框中输入“b”。)如果我尝试在我传递的对象中设置 event.data,当事件被触发时,它最终是未定义的。以下是我用来查看的代码:

$('#hi').keypress(function(e) {
  console.log(e);
});

还有其他想法吗?

【问题讨论】:

  • 你想调用什么?您是否尝试将它们移至下一个输入?
  • 是的。但下一个“输入”不一定是输入或其他自然制表符元素。它也不一定非自然地制表符(即 $("[tabindex]") )。物理按 Tab(或 shift+tab)完全符合我的要求......
  • 谢谢。我只对您问题的第一个代码示例感兴趣,这真的很有帮助:)
  • 也遇到了这个问题,很想知道那些untrusted事件的列表
  • 相关:stackoverflow.com/questions/1601593/… 接受的答案提到了...firing an event doesn't trigger the default result of the user action, for security reasons...

标签: javascript jquery html events keyboard


【解决方案1】:

实际上,我想有办法,即使它是一个主要的 PITA。我可以确保每个元素,即使自然是制表位,都有一个 Xtabindex,以某种方式以正确的顺序排列,即使我将放入其他人的小部件,因此使用 jQuery 在事后添加这些,而不是能够在 HTML 或其他初始构建代码中指定它。然后,我的整个表单将有一个真正的 tabindex。虽然它有焦点,但它会吸收按键,如果它们是 tab 或 shift+tab,则根据 Xtabindex 移动假焦点。如果在表单中的最后一个元素(或第一个元素上的 shift+tab)上按下 tab,它不会吞噬击键,从而允许浏览器使用键盘正确地专注于表单之外的其他页面或浏览器 UI 元素。

我只能猜测这种方法会带来哪些意想不到的副作用。

实际上,这甚至不是一个解决方案,因为我仍然无法在使用它的最后一个元素上伪造标签。

【讨论】:

【解决方案2】:

这是我在我们的 webapp 上为两个自定义控件使用的解决方案,一个弹出日历和一个弹出单元/值权重选择器(单击文本框会弹出一个带有两个选择的 div)

function tab_focus(elem)
  var fields = elem.form.getElements()
  for(var i=0;i<fields.length;i++) {
    if(fields[i].id == elem.id){
      for(i=i+1;i<fields.length;i++){
        if(fields[i].type != 'hidden'){
          fields[i].focus()
          return    
        }
      }
      break;
    }
  }
  elem.form.focusFirstElement();
}

这是使用 Prototype 框架并期望扩展元素(即 $('thing_id'))作为其参数。

它获取元素所属的表单,并遍历表单的元素,直到找到它自己。

然后它会寻找它之后的第一个未被隐藏的元素,并将焦点传递给它。

如果表单中没有元素,它会将焦点移回表单中的第一个元素。我可以通过 document.forms 在页面上找到下一个表单,但我们的大多数页面都使用一个表单。

【讨论】:

  • 问题是,我的一些可聚焦的 UI 元素不是表单元素,因为它们是自定义小部件。
  • 对于 jquery 用户,将此函数的第一行替换为: var fields = $('form')[0];遍历表单元素。
【解决方案3】:

我最终采用的解决方案是在我想要的区域的任一侧创建一个“焦点窃取器”div(tabindex = -1--可以有焦点,但最初不能用标签显示)手动管理焦点。然后我放置了一个冒泡的真实事件监听器,用于对整个区域进行聚焦和模糊处理。当任何焦点出现在该区域上时,tabindex 值将更改为 -1,当出现任何模糊时,它们将更改为 0。这意味着当焦点在该区域时,您可以使用 tab 或 shift-tab 离开该区域并且正确地结束在其他页面元素或浏览器 UI 元素上,但是一旦您离开那里,焦点窃取器就会变成可选项卡,并且在焦点上它们正确设置手动区域并将焦点转移到最后的元素上,就像您单击了手动区域的一端或另一端一样。

【讨论】:

    【解决方案4】:

    我认为这些错误来自自动完成。您可以通过在调度事件之前将自动完成属性设置为“关闭”来关闭它们

    setAttribute('autocomplete','off')
    

    【讨论】:

      【解决方案5】:

      我创建了一个simple jQuery plugin,它确实解决了这个问题。它使用 jQuery UI 的 ':tabbable' 选择器来查找下一个 'tabbable' 元素并选择它。

      示例用法:

      // Simulate tab key when element is clicked 
      $('.myElement').bind('click', function(event){
          $.tabNext();
          return false;
      });
      

      【讨论】:

        猜你喜欢
        • 2012-03-02
        • 1970-01-01
        • 1970-01-01
        • 2018-08-14
        • 2011-04-26
        • 2021-12-26
        • 2012-01-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多