Javascript 如何在 IE9 中将 Enter 转换为 Tab(焦点更改)?它在 IE8 中工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5347857/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:47:03  来源:igfitidea点击:

How do I convert Enter to Tab (with focus change) in IE9? It worked in IE8

javascriptcross-browserinternet-explorer-9

提问by David

I have a text input with an onkeydown event handler that converts <Enter> to <Tab> by changing the event's keyCode from 13 to 9.

我有一个带有 onkeydown 事件处理程序的文本输入,它通过将事件的 keyCode 从 13 更改为 9 将 <Enter> 转换为 <Tab>。

<input type="text" onkeydown="enterToTab(event);" onchange="changeEvent(this);" 
       name="" value="" />
<!-- Other inputs exist as created via the DOM, but they are not sibling elements. -->

Javascript:

Javascript:

function enterToTab(myEvent) {
    if (myEvent.keyCode == 13) {
        myEvent.keyCode = 9;
    }
}
function changeEvent(myInput) { var test = "hello"; }

In IE8, this caused the onchange event to fire, but that doesn't happen in IE9. Instead, the input field retains focus. How I can I make that happen? (It works in Firefox 3.6 and Chrome 10.0.) This even works in Browser Mode IE9 if I set the Document Mode to "IE8 standards". But it won't work with a Document Mode of "IE9 standards". (My DocType is XHTML 1.0 Transitional.)

在 IE8 中,这会导致 onchange 事件触发,但在 IE9 中不会发生这种情况。相反,输入字段保持焦点。我怎样才能做到这一点?(它适用于 Firefox 3.6 和 Chrome 10.0。)如果我将文档模式设置为“IE8 标准”,这甚至适用于浏览器模式 IE9。但它不适用于“IE9 标准”的文档模式。(我的 DocType 是 XHTML 1.0 Transitional。)

Since it works in IE7 & 8, could this be a bug in IE9 that will get fixed?

由于它适用于 IE7 和 8,这可能是 IE9 中的一个将得到修复的错误吗?

Please note: I cannotuse input.blur()or manually set a new focus, which is advised by all the other solutions that I've read. I've already tried onkeypress and onkeyup with no luck. I need a generic solution that will cause the web app to literally behave as though I'd hit <Tab>. Also, I don't have jQuery, however, Dojo 1.5 is available to me.

请注意:我无法使用input.blur()手动设置新的 focus,这是我读过的所有其他解决方案所建议的。我已经尝试过 onkeypress 和 onkeyup 没有运气。我需要一个通用的解决方案,使 Web 应用程序的行为就像我点击了 <Tab> 一样。另外,我没有 jQuery,但是我可以使用 Dojo 1.5。

Also note: I KNOW this is "wrong" behavior, and that Enter ought to submit the form. However, my client's staff originally come from a green screen environment where Enter moves them between fields. We must retain the same UI. It is what it is.

另请注意:我知道这是“错误”的行为,并且 Enter 应该提交表单。但是,我客户的员工最初来自绿屏环境,其中 Enter 在字段之间移动他们。我们必须保留相同的 UI。就是这样。

UPDATE:I found a difference between IE8 & IE9. In IE8, my setting of myEvent.keyCodeholds. In IE9, it does NOT. I can update window.event.keyCode, and it will hold, but that won't affect what happens later. Argh... Any ideas?

更新:我发现 IE8 和 IE9 之间存在差异。在 IE8 中,我的设置myEvent.keyCode保持不变。在 IE9 中,它没有。我可以更新window.event.keyCode,它会保持,但这不会影响以后发生的事情。啊...有什么想法吗?

回答by Shakakai

Looks like IE9 events are immutable. Once they've been fired you can't change the properties on them, just preventDefault() or cancel them. So you best option is to cancel any "enter" events and re-dispatch a new DOM event from the text input.

看起来 IE9 事件是不可变的。一旦它们被解雇,你就不能改变它们的属性,只需 preventDefault() 或取消它们。所以你最好的选择是取消任何“输入”事件并从文本输入重新调度一个新的 DOM 事件。

Example

例子

function enterToTab(event){
    if(event.keyCode == 13){
        var keyEvent = document.createEvent("Event");
        // This is a lovely method signature
        keyEvent.initKeyboardEvent("onkeydown", true, true, window, 9, event.location, "", event.repeat, event.locale);
        event.currentTarget.dispatchEvent(keyEvent);
        // you may want to prevent default here
    }
}

Here's the MSDN documentation around IE9 DOM events:

这是有关 IE9 DOM 事件的 MSDN 文档:

Event Object - http://msdn.microsoft.com/en-us/library/ms535863(v=vs.85).aspx

事件对象 - http://msdn.microsoft.com/en-us/library/ms535863(v=vs.85).aspx

createEvent - http://msdn.microsoft.com/en-us/library/ff975304(v=vs.85).aspx

createEvent - http://msdn.microsoft.com/en-us/library/ff975304(v=vs.85).aspx

initialize a Keyboard Event - http://msdn.microsoft.com/en-us/library/ff975297(v=vs.85).aspx

初始化键盘事件 - http://msdn.microsoft.com/en-us/library/ff975297(v=vs.85).aspx

回答by KooiInc

The previous IE-version allowed the non standard writable event.keyCodeproperty, IE9 now conforms to the standards.

以前的 IE 版本允许非标准的可写event.keyCode属性,IE9 现在符合标准。

You may want to consider the functionalityyou are after: you want to make the enter key behave like the tab key, i.e. moving the focus to the next (text) input field. There are more ways to do that. One of them is using the tabindexattribute of the text input fields. If you order the fields in your form using this tabindex attribute, the functions I present here may yield the same result as your previous keyCode method. Here are two functions I tested in this jsfiddle. An (text) input field now looks like:

您可能需要考虑您所追求的功能:您希望 Enter 键的行为类似于 Tab 键,即将焦点移动到下一个(文本)输入字段。有更多方法可以做到这一点。其中之一是使用tabindex文本输入字段的属性。如果您使用此 tabindex 属性对表单中的字段进行排序,则我在此处提供的函数可能会产生与您之前的 keyCode 方法相同的结果。这是我在这个 jsfiddle 中测试的两个函数。一个(文本)输入字段现在看起来像:

<input type="text" 
       onkeypress="nextOnEnter(this,event);" 
       name="" value="" 
       tabindex="1"/>

the functions to use for tabbing:

用于制表的函数:

function nextOnEnter(obj,e){
    e = e || event;
    // we are storing all input fields with tabindex attribute in 
    // a 'static' field of this function using the external function
    // getTabbableFields
    nextOnEnter.fields = nextOnEnter.fields || getTabbableFields();
    if (e.keyCode === 13) {
        // first, prevent default behavior for enter key (submit)
        if (e.preventDefault){
            e.preventDefault();
        } else if (e.stopPropagation){    
          e.stopPropagation();
        } else {   
          e.returnValue = false;
        }
       // determine current tabindex
       var tabi = parseInt(obj.getAttribute('tabindex'),10);
       // focus to next tabindex in line
       if ( tabi+1 < nextOnEnter.fields.length ){
         nextOnEnter.fields[tabi+1].focus();
        }
    }
}

// returns an array containing all input text/submit fields with a
// tabindex attribute, in the order of the tabindex values
function getTabbableFields(){
    var ret = [],
        inpts = document.getElementsByTagName('input'), 
        i = inpts.length;
    while (i--){
        var tabi = parseInt(inpts[i].getAttribute('tabindex'),10),
            txtType = inpts[i].getAttribute('type');
            // [txtType] could be used to filter out input fields that you
            // don't want to be 'tabbable'
            ret[tabi] = inpts[i];
    }
    return ret;
}

If you don't want to use tabindex and all your input fields are 'tabbable', see this jsfiddle

如果您不想使用 tabindex 并且所有输入字段都是“可制表的”,请参阅此 jsfiddle

[EDIT] edited functions (see jsfiddles) to make use of event delegation and make it all work in Opera too. And this versionimitates shift-TAB too.

[编辑] 编辑函数(参见 jsfiddles)以利用事件委托并使其在 Opera 中也能正常工作。而这个版本的模仿Shift-Tab键也。

回答by AndyD273

Here is a different idea; change the on submit so that it calls a function instead of processing the form. in the function check all the fields to see if they are blank, then focus on the next field that doesn't have a value.
So they type a value into field 1, hit enter, and the function runs. it sees that field 1 is full, but field 2 isn't, so focus on field 2.
Then when all the fields are full, submit the form for processing.
If the form has fields that can be blank, you could use a boolean array that would keep track of which fields received focus using the onfocus() event.

这是一个不同的想法;更改 on submit 以便它调用函数而不是处理表单。在函数中检查所有字段以查看它们是否为空,然后关注下一个没有值的字段。
所以他们在字段 1 中输入一个值,按回车键,然后函数运行。它看到字段 1 已满,但字段 2 未满,因此关注字段 2。
然后当所有字段都已满时,提交表单进行处理。
如果表单具有可以为空的字段,您可以使用布尔数组来跟踪使用 onfocus() 事件接收焦点的字段。

Just an outside the box idea.

只是一个开箱即用的想法。

回答by Mike Fdz

The code above causes problems. Here's some code that will help you. Works on IE9, FF5 etc.

上面的代码会导致问题。这是一些可以帮助您的代码。适用于 IE9、FF5 等。

function getNextElement(field) {
    var form = field.form;
    for ( var e = 0; e < form.elements.length; e++) {
        if (field == form.elements[e]) {
            break;
        }
    }
    return form.elements[++e % form.elements.length];
}

function tabOnEnter(field, evt) {
if (evt.keyCode === 13) {
        if (evt.preventDefault) {
            evt.preventDefault();
        } else if (evt.stopPropagation) {
            evt.stopPropagation();
        } else {
            evt.returnValue = false;
        }
        getNextElement(field).focus();
        return false;
    } else {
        return true;
    }
}

And then you should just create your input texts or whatever

然后你应该创建你的输入文本或其他任何东西

<input type="text" id="1" onkeydown="return tabOnEnter(this,event)"/>
<input type="text" id="2" onkeydown="return tabOnEnter(this,event)"/>
<input type="text" id="3" onkeydown="return tabOnEnter(this,event)"/>
<input type="text" id="4" onkeydown="return tabOnEnter(this,event)"/>

回答by Paul Harding

Mike Fdz's code is superb. In order to skip over hidden fields, you may want to change the line

Mike Fdz 的代码非常棒。为了跳过隐藏字段,您可能需要更改行

return form.elements[++e % form.elements.length]; 

to this:

对此:

e++;
while (form.elements[e % form.elements.length].type == "hidden") {
    e++;
}
return form.elements[e % form.elements.length];

回答by sab

Use onpaste along with onkeypress like

使用 onpaste 和 onkeypress 一样

Consider you have wrriten a javascript function which checks the text lenght so we will need to validate it on key press like as below

考虑您编写了一个检查文本长度的 javascript 函数,因此我们需要在按键时验证它,如下所示

<asp:TextBox ID="txtInputText" runat="server" Text="Please enter some text" onpaste="return textboxMultilineMaxNumber(this,1000);" onkeypress="return textboxMultilineMaxNumber(this,1000);"></asp:TextBox>

onkeypress will work in both FF and IE

onkeypress 将在 FF 和 IE 中工作

but if you try to do ctr+V in textbox then onpaste will handle in IE in FF onkeypress takes care of it

但是,如果您尝试在文本框中执行 ctr+V,则 onpaste 将在 FF onkeypress 中的 IE 中处理它

回答by robocat

A <button>element on a page will cause this problem.

一个<button>页面上的元素将导致此问题。

In IE9 a <button>element takes the focus when Enter is pressed. Any submit or reset button will cause the problem too. If you are not using submit/reset then you can fix this by changing all buttons to <input type="button">or by setting the button's type attributeto button. i.e.

在 IE9<button>中,按下 Enter 时元素会获得焦点。任何提交或重置按钮也会导致问题。如果您不使用提交/重置,那么您可以通过将所有按钮更改为<input type="button">或将按钮的类型属性设置为按钮来解决此问题。IE

<button type="button">Click me!</button>

Alternatively as per KooiInc's answer, you can edit your javascript to use event.preventDefault();to prevent the Enter key acting this way, and explicitly call focus() on the next element in the tab order.

或者,根据 KooiInc 的回答,您可以编辑 javascript 以event.preventDefault();防止 Enter 键以这种方式运行,并在 Tab 键顺序中的下一个元素上显式调用 focus()。

Here is some test code I wrote that demonstrates the problem with the button element (note the blue focus ring on button3 in IE9):

这是我编写的一些测试代码,用于演示按钮元素的问题(注意 IE9 中 button3 上的蓝色焦点环):

<!DOCTYPE HTML>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>IE problem with Enter key and &lt;button&gt; elements</title>
</head>

<body>
    <script>
        function press(event) {
            if (event.keyCode == 13) {
                document.getElementById('input2').focus();
                // In IE9 the focus shifts to the <button> unless we call preventDefault(). Uncomment following line for IE9 fix. Alternatively set type="button" on all button elements and anything else that is a submit or reset too!.
                // event.preventDefault && event.preventDefault();
            }
        }
    </script>
    <input id="input1" type="text" onkeypress="press(event)" value="input1. Press enter here." /><br />
    <input id="input2" type="text" value="input2. Press enter here." /><br />
    <input  id="button1" type="button" value='I am an <input type="button">' /><br />
    <button id="button2" type="button">I am a &lt;button type="button"&gt;</button><br />
    <button id="button3">I am a &lt;button&gt;. I get focus when enter key pressed in IE9 - wooot!</button><span>As per Microsoft docs on <a target="_tab" href="http://msdn.microsoft.com/en-us/library/ms534696%28v=vs.85%29.aspx">BUTTON.type</a> it is because type defaults to submit.</span>
</body>
</html>

回答by webselect

This is what I have done with what I found over the internet :

这是我用我在互联网上找到的东西所做的:

function stopRKey(evt) 
{ 
  var evt = (evt) ? evt : ((event) ? event : null); 
  var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null); 
  if ((evt.keyCode == 13) && ((node.type=="text") || (node.type=="radio")))  
  { 
      getNextElement(node).focus();  
      return false;   
    } 
} 

function getNextElement(field) 
{
    var form = field.form;
    for ( var e = 0; e < form.elements.length; e++) {
        if (field == form.elements[e]) {
            break;
        }
    }
    e++;
    while (form.elements[e % form.elements.length].type == "hidden") 
    {
        e++;
    }
    return form.elements[e % form.elements.length];;
}

回答by Odilon Salgado

To prevent a "submit event" triggered by Enter-Keyboard in your Form in IE9, retire any button inside the form area. Place him (button) in outside of form's area.

为防止在 IE9 中的表单中由 Enter-Keyboard 触发“提交事件”,请停用表单区域内的任何按钮。将他(按钮)放在表单区域之外。

function enterAsTab() {
  var keyPressed = event.keyCode; // get the Key that is pressed
  if (keyPressed == 13)
  { 
    //case the KeyPressed is the [Enter]
    var inputs = $('input'); // storage a array of Inputs
    var a = inputs.index(document.activeElement); 
    //get the Index of Active Element Input inside the Inputs(array)
    
    if (inputs[a + 1] !== null)
    {
      // case the next index of array is not null
      var nextBox = inputs[a + 1]; 
      nextBox.focus(); // Focus the next input element. Make him an Active Element
      event.preventDefault();
    }
    
    return false;
  } 
  
  else {return keyPressed;}
}
<HTML>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body onKeyPress="return enterAsTab();">
  <input type='text' />
  <input type='text' />
  <input type='text' />
  <input type='text' />
  <input type='text' />
</body>

</HTML>