简体   繁体   English

使用JavaScript模拟tab键

[英]Simulating a tab keypress using JavaScript

I'd like to have the browser act as if the user had pressed the Tab key when they click on something. 我希望浏览器的行为就像用户点击某些内容时按Tab键一样。 In the click handler I've tried the following approaches: 在点击处理程序中,我尝试了以下方法:

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

And jQuery: 和jQuery:

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

...which I took from here . ......我从这里拿走

The first approach seems to be the best bet, but doesn't quite work. 第一种方法似乎是最好的选择,但并不是很有效。 If I change the last two parameters to 98, 98, indeed, a 'b' is typed into the input box. 如果我将最后两个参数更改为98,98,确实在输入框中输入了'b'。 But 9, 0 and 9, 9 (the former of which I took right from the MDC web site) both give me these errors in firebug under FF3: 但是,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);

I've heard such (with no clear definition of 'such') events are 'untrusted', which might explain these errors. 我听说过(没有明确定义'此类')事件是“不可信的”,这可能解释了这些错误。

The second approach causes whatever value I put as event.which to be passed as event.which, but to no effect (even if I use 98 instead of 9, no 'b' is typed in the box.) If I try setting event.data in the object I'm passing, it ends up undefined when the event is triggered. 第二种方法导致我作为event.which传递的任何值作为event.which,但没有效果(即使我使用98而不是9,在框中没有输入'b'。)如果我尝试设置事件在我传递的对象中的.data,当事件被触发时它最终未定义。 What follows is the code I'm using to view that: 以下是我用来查看的代码:

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

Any other ideas? 还有其他想法吗?

The solution I ended up going with is to create a "focus stealer" div (with tabindex = -1--can have the focus but can't be tabbed to initially) on either side of the area in which I want to manually manage the focus. 我最终得到的解决方案是在我想要手动管理的区域的两侧创建一个“焦点窃取器”div(tabindex = -1 - 可以有焦点,但最初不能选中)焦点。 Then I put a bubbling-true event listener for focus and blur on the whole area. 然后我在整个区域放置了一个冒泡真实的事件监听器,用于聚焦和模糊。 When any focus occurs on the area, the tabindex values are changed to -1, and when any blur occurs, they're changed to 0. This means that while focused in the area, you can tab or shift-tab out of it and correctly end up on other page elements or browser UI elements, but as soon as you focus out of there, the focus stealers become tabbable, and on focus they set up the manual area correctly and shunt the focus over to the element at their end, as if you had clicked on one end or the other of the manual area. 当区域上出现任何焦点时,tabindex值将更改为-1,并且当出现任何模糊时,它们将更改为0.这意味着当聚焦在该区域时,您可以选择标签或移位标签。正确地结束其他页面元素或浏览器UI元素,但是一旦你聚焦在那里,焦点窃取者变得可能,并且在焦点上他们正确地设置手动区域并将焦点分流到他们结尾的元素,好像你点击了手动区域的一端或另一端。

This is the solution I used on our webapp for two custom controls, a pop-up calendar and a pop-up unit / value weight selector (clicking the text box pops up a div with two selects) 这是我在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();
}

This is using the Prototype framework and expects an extended element(ie $('thing_id')) as its parameter. 这是使用Prototype框架并期望扩展元素(即$('thing_id'))作为其参数。

It gets the form the element belongs to, and loops through the elements of the form until it finds itself. 它获取元素所属的形式,并循环遍历表单的元素,直到找到它为止。

It then looks for the first element after it that is not hidden, and passes it the focus. 然后它会查找未隐藏的第一个元素,并将焦点传递给它。

If there are no elements after it in the form, it moves the focus back the to first element in the form. 如果表单后面没有元素,它会将焦点移回到表单中的第一个元素。 I could instead find the next form on the page through document.forms, but most of our pages use a single form. 我可以通过document.forms在页面上找到下一个表单,但我们的大多数页面都使用单个表单。

I created a simple jQuery plugin which does solve this problem. 我创建了一个简单的jQuery插件 ,可以解决这个问题。 It uses the ':tabbable' selector of jQuery UI to find the next 'tabbable' element and selects it. 它使用jQuery UI的':tabbable'选择器来查找下一个'tabbable'元素并选择它。

Example usage: 用法示例:

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

Actually, I guess there is a way, even if it's a major PITA. 实际上,我猜有一种方法,即使它是一个主要的PITA。 I can make sure that every element, even if naturally a tab-stop, has an Xtabindex, somehow in the proper order even though I'll be dropping in other people's widgets and so using jQuery to add these after the fact, rather than being able to specify it right in the HTML or other initial building code. 我可以确保每个元素,即使自然是一个制表符,都有一个Xtabindex,以某种方式以正确的顺序,即使我将丢弃其他人的小部件,所以使用jQuery事后添加这些,而不是能够在HTML或其他初始构建代码中指定它。 Then, my entire form will have a real tabindex. 然后,我的整个表格将有一个真正的tabindex。 While it has the focus, it will absorb keypresses, and if they're tab or shift+tab, move the fake focus based on Xtabindex. 虽然它具有焦点,但它会吸收按键,如果它们是tab或shift + tab,则根据Xtabindex移动假焦点。 If tab is pressed on the last (or shift+tab on the first) element in the form, it won't gobble the keystroke, thus allowing the browser to properly focus on other page or browser UI elements outside the form using the keyboard. 如果在表单中的最后一个(或第一个上的shift +选项卡)元素上按下tab,它将不会吞噬击键,从而允许浏览器使用键盘正确地关注表单外的其他页面或浏览器UI元素。

I can only guess what kinds of unintended side-effects this approach will introduce. 我只能猜测这种方法会引入哪种非预期的副作用。

Actually, it's not even a solution, because I still can't fake a tab on the last element using it. 实际上,它甚至不是一个解决方案,因为我仍然无法使用它伪造最后一个元素上的标签。

I think those errors are from autocomplete. 我认为这些错误来自自动完成。 You might be able to turn them off by setting, before you dispatch the event, the autocomplete attribute to 'off' 您可以通过在发送事件之前将自动完成属性设置为“关闭”来关闭它们

setAttribute('autocomplete','off')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM