81

我正在寻找创建一个表单,其中按 Enter 键会导致焦点转到页面上的“下一个”表单元素。我一直在网上找到的解决方案是......

 <body onkeydown="if(event.keyCode==13){event.keyCode=9; return event.keyCode}">

不幸的是,这似乎只适用于 IE。所以这个问题的真正实质是是否有人知道适用于 FF 和 Chrome 的解决方案?此外,我宁愿不必将onkeydown事件添加到表单元素本身,但如果这是唯一的方法,它就必须这样做。

这个问题与问题 905222类似,但在我看来,值得提出自己的问题。

编辑:另外,我看到人们提出这不是好的风格,因为它与用户习惯的表单行为不同。我同意!这是一个客户请求:(

4

23 回答 23

95

我使用了 Andrew 建议的逻辑,非常有效。这是我的版本:

$('body').on('keydown', 'input, select', function(e) {
    if (e.key === "Enter") {
        var self = $(this), form = self.parents('form:eq(0)'), focusable, next;
        focusable = form.find('input,a,select,button,textarea').filter(':visible');
        next = focusable.eq(focusable.index(this)+1);
        if (next.length) {
            next.focus();
        } else {
            form.submit();
        }
        return false;
    }
});

KeyboardEvent 的 keycode(即:)e.keycode折旧通知:- https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

于 2012-08-26T13:24:36.330 回答
25

我想出的最简单的香草 JS 片段:

document.addEventListener('keydown', function (event) {
  if (event.keyCode === 13 && event.target.nodeName === 'INPUT') {
    var form = event.target.form;
    var index = Array.prototype.indexOf.call(form, event.target);
    form.elements[index + 1].focus();
    event.preventDefault();
  }
});

适用于 IE 9+ 和现代浏览器。

于 2016-12-30T08:20:01.490 回答
18

映射 [Enter] 键以像 [Tab] 键一样工作

我用 jQuery 重写了 Andre Van Zuydam的答案,这对我不起作用。这会同时捕获EnterShift+ EnterEnter向前制表符,Shift+Enter向后制表符。

我还重写了self当前焦点项初始化的方式。表格也是这样选择的。这是代码:

// Map [Enter] key to work like the [Tab] key
// Daniel P. Clark 2014

// Catch the keydown for the entire document
$(document).keydown(function(e) {

  // Set self as the current item in focus
  var self = $(':focus'),
      // Set the form by the current item in focus
      form = self.parents('form:eq(0)'),
      focusable;

  // Array of Indexable/Tab-able items
  focusable = form.find('input,a,select,button,textarea,div[contenteditable=true]').filter(':visible');

  function enterKey(){
    if (e.which === 13 && !self.is('textarea,div[contenteditable=true]')) { // [Enter] key

      // If not a regular hyperlink/button/textarea
      if ($.inArray(self, focusable) && (!self.is('a,button'))){
        // Then prevent the default [Enter] key behaviour from submitting the form
        e.preventDefault();
      } // Otherwise follow the link/button as by design, or put new line in textarea

      // Focus on the next item (either previous or next depending on shift)
      focusable.eq(focusable.index(self) + (e.shiftKey ? -1 : 1)).focus();

      return false;
    }
  }
  // We need to capture the [Shift] key and check the [Enter] key either way.
  if (e.shiftKey) { enterKey() } else { enterKey() }
});

原因textarea

包含在内是因为我们“确实”想要加入它。此外,一旦进入,我们不想阻止默认行为Enter插入新行。

原因abutton

允许默认操作,“”仍然专注于下一项,是因为它们并不总是加载另一个页面。可以对诸如手风琴或选项卡式内容之类的内容产生触发/影响。因此,一旦您触发了默认行为,并且页面产生了特殊效果,您仍然希望转到下一项,因为您的触发器可能已经很好地介绍了它。

于 2014-12-18T11:21:33.293 回答
12

谢谢你的好剧本。

我刚刚在上述函数上添加了 shift 事件以在元素之间返回,我想有人可能需要这个。

$('body').on('keydown', 'input, select, textarea', function(e) {
var self = $(this)
  , form = self.parents('form:eq(0)')
  , focusable
  , next
  , prev
  ;

if (e.shiftKey) {
 if (e.keyCode == 13) {
     focusable =   form.find('input,a,select,button,textarea').filter(':visible');
     prev = focusable.eq(focusable.index(this)-1); 

     if (prev.length) {
        prev.focus();
     } else {
        form.submit();
    }
  }
}
  else
if (e.keyCode == 13) {
    focusable = form.find('input,a,select,button,textarea').filter(':visible');
    next = focusable.eq(focusable.index(this)+1);
    if (next.length) {
        next.focus();
    } else {
        form.submit();
    }
    return false;
}
});
于 2013-11-20T14:50:18.733 回答
11

这对我有用:

$(document).on('keydown', ':tabbable', function(e) {

    if (e.key === "Enter") {
        e.preventDefault();

        var $canfocus = $(':tabbable:visible');
        var index = $canfocus.index(document.activeElement) + 1;

        if (index >= $canfocus.length) index = 0;
        $canfocus.eq(index).focus();
    }

});
于 2016-10-20T05:59:27.987 回答
6

这里给出的所有实现都存在问题。有些不能正常使用 textareas 和提交按钮,大多数不允许您使用 shift 向后退,如果您有它们,它们都不会使用 tabindexes,并且它们都不会从最后一个到第一个或第一个环绕到最后。

要使 [enter] 键的作用类似于 [tab] 键,但仍可与文本区域和提交按钮正常工作,请使用以下代码。此外,此代码允许您使用 shift 键向后移动,并且制表符从前到后和从后到前环绕。

源代码:https ://github.com/mikbe/SaneEnterKey

咖啡脚本

mbsd_sane_enter_key = ->
  input_types = "input, select, button, textarea"
  $("body").on "keydown", input_types, (e) ->
    enter_key = 13
    tab_key = 9

    if e.keyCode in [tab_key, enter_key]
      self = $(this)

      # some controls should just press enter when pressing enter
      if e.keyCode == enter_key and (self.prop('type') in ["submit", "textarea"])
        return true

      form = self.parents('form:eq(0)')

      # Sort by tab indexes if they exist
      tab_index = parseInt(self.attr('tabindex'))
      if tab_index
        input_array = form.find("[tabindex]").filter(':visible').sort((a,b) -> 
          parseInt($(a).attr('tabindex')) - parseInt($(b).attr('tabindex'))
        )
      else
        input_array = form.find(input_types).filter(':visible')

      # reverse the direction if using shift
      move_direction = if e.shiftKey then -1 else 1
      new_index = input_array.index(this) + move_direction

      # wrap around the controls
      if new_index == input_array.length
        new_index = 0
      else if new_index == -1
        new_index = input_array.length - 1

      move_to = input_array.eq(new_index)
      move_to.focus()
      move_to.select()

      false

$(window).on 'ready page:load', ->
  mbsd_sane_enter_key()

JavaScript

var mbsd_sane_enter_key = function() {
  var input_types;
  input_types = "input, select, button, textarea";

  return $("body").on("keydown", input_types, function(e) {
    var enter_key, form, input_array, move_direction, move_to, new_index, self, tab_index, tab_key;
    enter_key = 13;
    tab_key = 9;

    if (e.keyCode === tab_key || e.keyCode === enter_key) {
      self = $(this);

      // some controls should react as designed when pressing enter
      if (e.keyCode === enter_key && (self.prop('type') === "submit" || self.prop('type') === "textarea")) {
        return true;
      }

      form = self.parents('form:eq(0)');

      // Sort by tab indexes if they exist
      tab_index = parseInt(self.attr('tabindex'));
      if (tab_index) {
        input_array = form.find("[tabindex]").filter(':visible').sort(function(a, b) {
          return parseInt($(a).attr('tabindex')) - parseInt($(b).attr('tabindex'));
        });
      } else {
        input_array = form.find(input_types).filter(':visible');
      }

      // reverse the direction if using shift
      move_direction = e.shiftKey ? -1 : 1;
      new_index = input_array.index(this) + move_direction;

      // wrap around the controls
      if (new_index === input_array.length) {
        new_index = 0;
      } else if (new_index === -1) {
        new_index = input_array.length - 1;
      }

      move_to = input_array.eq(new_index);
      move_to.focus();
      move_to.select();
      return false;
    }
  });
};

$(window).on('ready page:load', function() {
  mbsd_sane_enter_key();
}
于 2014-11-12T19:48:18.760 回答
4

更改此行为实际上会创建比本机实现的默认行为更好的用户体验。考虑回车键的行为从用户的角度来看已经不一致,因为在单行输入中,回车倾向于提交表单,而在多行文本区域中,它只是在内容中添加换行符场地。

我最近这样做(使用 jQuery):

$('input.enterastab, select.enterastab, textarea.enterastab').live('keydown', function(e) {
 if (e.keyCode==13) {
  var focusable = $('input,a,select,button,textarea').filter(':visible');
  focusable.eq(focusable.index(this)+1).focus();
  return false;
 }
});

这不是非常有效,但运行良好且可靠 - 只需将“enterastab”类添加到应该以这种方式运行的任何输入元素。

于 2010-10-04T16:17:56.333 回答
4

我将 OPs 解决方案重新设计为 Knockout 绑定,并认为我会分享它。非常感谢 :-)

这是一个小提琴

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" type="text/javascript"></script>
    <script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js" type="text/javascript"></script>


</head>
<body>

    <div data-bind="nextFieldOnEnter:true">
        <input type="text" />
        <input type="text" />
        <select>
          <option value="volvo">Volvo</option>
          <option value="saab">Saab</option>
          <option value="mercedes">Mercedes</option>
          <option value="audi">Audi</option>
        </select>
        <input type="text" />
        <input type="text" />
    </div>


    <script type="text/javascript">
    ko.bindingHandlers.nextFieldOnEnter = {
        init: function(element, valueAccessor, allBindingsAccessor) {
            $(element).on('keydown', 'input, select', function (e) {
                var self = $(this)
                , form = $(element)
                  , focusable
                  , next
                ;
                if (e.keyCode == 13) {
                    focusable = form.find('input,a,select,button,textarea').filter(':visible');
                    var nextIndex = focusable.index(this) == focusable.length -1 ? 0 : focusable.index(this) + 1;
                    next = focusable.eq(nextIndex);
                    next.focus();
                    return false;
                }
            });
        }
    };

    ko.applyBindings({});
    </script>
</body>
</html>
于 2013-04-11T22:56:04.617 回答
2

这是一个 angular.js 指令,使用其他答案作为灵感,使输入进入下一个字段。这里可能有一些看起来很奇怪的代码,因为我只使用 angular 打包的 jQlite。我相信这里的大部分功能都适用于所有浏览器> IE8。

angular.module('myapp', [])
.directive('pdkNextInputOnEnter', function() {
    var includeTags = ['INPUT', 'SELECT'];

    function link(scope, element, attrs) {
        element.on('keydown', function (e) {
            // Go to next form element on enter and only for included tags
            if (e.keyCode == 13 && includeTags.indexOf(e.target.tagName) != -1) {
                // Find all form elements that can receive focus
                var focusable = element[0].querySelectorAll('input,select,button,textarea');

                // Get the index of the currently focused element
                var currentIndex = Array.prototype.indexOf.call(focusable, e.target)

                // Find the next items in the list
                var nextIndex = currentIndex == focusable.length - 1 ? 0 : currentIndex + 1;

                // Focus the next element
                if(nextIndex >= 0 && nextIndex < focusable.length)
                    focusable[nextIndex].focus();

                return false;
            }
        });
    }

    return {
        restrict: 'A',
        link: link
    };
});

这是我在正在开发的应用程序中使用它的方法,只需pdk-next-input-on-enter在元素上添加指令即可。我正在使用条形码扫描仪将数据输入字段,扫描仪的默认功能是模拟键盘,在输入扫描的条形码数据后注入一个回车键。

此代码有一个副作用(对我的用例来说是一个积极的影响),如果它将焦点移到按钮上,则 enter keyup 事件将导致按钮的操作被激活。这对我的流程非常有效,因为我的标记中的最后一个表单元素是一个按钮,一旦通过扫描条形码“标记”了所有字段,我希望激活该按钮。

<!DOCTYPE html>
<html ng-app=myapp>
  <head>
      <script src="angular.min.js"></script>
      <script src="controller.js"></script>
  </head>
  <body ng-controller="LabelPrintingController">
      <div class='.container' pdk-next-input-on-enter>
          <select ng-options="p for p in partNumbers" ng-model="selectedPart" ng-change="selectedPartChanged()"></select>
          <h2>{{labelDocument.SerialNumber}}</h2>
          <div ng-show="labelDocument.ComponentSerials">
              <b>Component Serials</b>
              <ul>
                  <li ng-repeat="serial in labelDocument.ComponentSerials">
                      {{serial.name}}<br/>
                      <input type="text" ng-model="serial.value" />
                  </li>
              </ul>
          </div>
          <button ng-click="printLabel()">Print</button>
      </div>
  </body>
</html>
于 2014-01-21T21:05:07.447 回答
1

我遇到了类似的问题,我想按+小键盘以跳到下一个字段。现在我发布了一个我认为会对你有所帮助的库。

PlusAsTab : 一个 jQuery 插件,使用小键盘加键作为 Tab 键等效项。

由于您想要enter/而不是,您可以设置选项。找出你想在jQuery event.which 演示中使用哪个键。

JoelPurra.PlusAsTab.setOptions({
  // Use enter instead of plus
  // Number 13 found through demo at
  // https://api.jquery.com/event.which/
  key: 13
});

// Matches all inputs with name "a[]" (needs some character escaping)
$('input[name=a\\[\\]]').plusAsTab();

您可以在PlusAsTab 中自己尝试一下 enter as tab demo

于 2012-02-17T12:15:23.473 回答
1

试试这个...

$(document).ready(function () {
    $.fn.enterkeytab = function () {
        $(this).on('keydown', 'input,select,text,button', function (e) {
            var self = $(this)
              , form = self.parents('form:eq(0)')
              , focusable
              , next
            ;
            if (e.keyCode == 13) {
                focusable = form.find('input,a,select').filter(':visible');
                next = focusable.eq(focusable.index(this) + 1);
                if (next.length) {
                    //if disable try get next 10 fields
                    if (next.is(":disabled")){
                        for(i=2;i<10;i++){
                            next = focusable.eq(focusable.index(this) + i);
                            if (!next.is(":disabled"))
                                break;
                        }
                    }
                    next.focus();
                }
                return false;
            }
        });
    }
    $("form").enterkeytab();
});
于 2017-04-26T20:32:17.793 回答
1
function return2tab (div)
{
    document.addEventListener('keydown', function (ev) {
        if (ev.key === "Enter" && ev.target.nodeName === 'INPUT') {

            var focusableElementsString = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]';

            let ol= div.querySelectorAll(focusableElementsString);

            for (let i=0; i<ol.length; i++) {
                if (ol[i] === ev.target) {
                    let o= i<ol.length-1? ol[i+1]: o[0];
                    o.focus(); break;
                }
            }
            ev.preventDefault();
        }
    });
}
于 2021-01-11T13:18:52.503 回答
0

如果可以的话,我会重新考虑这样做:<Enter>在表单中按下时的默认操作会提交表单,并且您为更改此默认操作/预期行为所做的任何事情都可能导致网站出现一些可用性问题。

于 2009-06-18T09:26:24.893 回答
0

我让它只在 JavaScript 中工作。Firefox 不会让您更新 keyCode,因此您所能做的就是捕获 keyCode 13 并强制它通过 tabIndex 将注意力集中在下一个元素上,就像按下 keyCode 9 一样。棘手的部分是找到下一个 tabIndex。我仅在 IE8-IE10 和 Firefox 上对此进行了测试,并且可以正常工作:

function ModifyEnterKeyPressAsTab(event)
{
    var caller;
    var key;
    if (window.event)
    {
        caller = window.event.srcElement; //Get the event caller in IE.
        key = window.event.keyCode; //Get the keycode in IE.
    }
    else
    {
        caller = event.target; //Get the event caller in Firefox.
        key = event.which; //Get the keycode in Firefox.
    }
    if (key == 13) //Enter key was pressed.
    {
        cTab = caller.tabIndex; //caller tabIndex.
        maxTab = 0; //highest tabIndex (start at 0 to change)
        minTab = cTab; //lowest tabIndex (this may change, but start at caller)
        allById = document.getElementsByTagName("input"); //Get input elements.
        allByIndex = []; //Storage for elements by index.
        c = 0; //index of the caller in allByIndex (start at 0 to change)
        i = 0; //generic indexer for allByIndex;
        for (id in allById) //Loop through all the input elements by id.
        {
            allByIndex[i] = allById[id]; //Set allByIndex.
            tab = allByIndex[i].tabIndex;
            if (caller == allByIndex[i])
                c = i; //Get the index of the caller.
            if (tab > maxTab)
                maxTab = tab; //Get the highest tabIndex on the page.
            if (tab < minTab && tab >= 0)
                minTab = tab; //Get the lowest positive tabIndex on the page.
            i++;
        }
        //Loop through tab indexes from caller to highest.
        for (tab = cTab; tab <= maxTab; tab++)
        {
            //Look for this tabIndex from the caller to the end of page.
            for (i = c + 1; i < allByIndex.length; i++)
            {
                if (allByIndex[i].tabIndex == tab)
                {
                    allByIndex[i].focus(); //Move to that element and stop.
                    return;
                }
            }
            //Look for the next tabIndex from the start of page to the caller.
            for (i = 0; i < c; i++)
            {
                if (allByIndex[i].tabIndex == tab + 1)
                {
                    allByIndex[i].focus(); //Move to that element and stop.
                    return;
                }
            }
            //Continue searching from the caller for the next tabIndex.
        }

        //The caller was the last element with the highest tabIndex,
        //so find the first element with the lowest tabIndex.
        for (i = 0; i < allByIndex.length; i++)
        {
            if (allByIndex[i].tabIndex == minTab)
            {
                allByIndex[i].focus(); //Move to that element and stop.
                return;
            }
        }
    }
}

要使用此代码,请将其添加到您的 html 输入标记中:

<input id="SomeID" onkeydown="ModifyEnterKeyPressAsTab(event);" ... >

或者将其添加到 javascript 中的元素中:

document.getElementById("SomeID").onKeyDown = ModifyEnterKeyPressAsTab;

其他几点注意事项:

我只需要它来处理我的输入元素,但如果需要,您可以将它扩展到其他文档元素。为此,getElementsByClassName 非常有帮助,但那是另一个话题了。

一个限制是它仅在您添加到 allById 数组的元素之间使用制表符。它不会围绕您的浏览器可能的其他内容进行选项卡,例如 html 文档之外的工具栏和菜单。也许这是一个功能而不是限制。如果您愿意,请捕获 keyCode 9,此行为也适用于 tab 键。

于 2013-03-17T12:57:54.307 回答
0

你可以使用下面我的代码,在 Mozilla、IE 和 Chrome 中测试过

   // Use to act like tab using enter key
    $.fn.enterkeytab=function(){
         $(this).on('keydown', 'input, select,', function(e) {
        var self = $(this)
          , form = self.parents('form:eq(0)')
          , focusable
          , next
          ;
            if (e.keyCode == 13) {
                focusable = form.find('input,a,select,button').filter(':visible');
                next = focusable.eq(focusable.index(this)+1);
                if (next.length) {
                    next.focus();
                } else {
                    alert("wd");
                    //form.submit();
                }
                return false;
            }
        });

    }

如何使用?

$("#form").enterkeytab(); // 进入键选项卡

于 2013-07-31T15:34:56.037 回答
0

Vanilla js 支持 Shift + Enter 并能够选择哪些 HTML 标记是可聚焦的。应该工作IE9 +。

  onKeyUp(e) {
    switch (e.keyCode) {
      case 13: //Enter
        var focusableElements = document.querySelectorAll('input, button')
        var index = Array.prototype.indexOf.call(focusableElements, document.activeElement)
        if(e.shiftKey)
          focus(focusableElements, index - 1)
        else
          focus(focusableElements, index + 1)

        e.preventDefault()
        break;
    }
    function focus(elements, index) {
      if(elements[index])
        elements[index].focus()
    }
  }
于 2017-02-16T08:21:51.580 回答
0

e.keyCode此处使用的许多答案e.which已被弃用。

相反,您应该使用e.key === 'Enter'.

文档:https ://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

  • 很抱歉,我现在无法测试这些片段。测试后会回来。

使用 HTML:

<body onkeypress="if(event.key==='Enter' && event.target.form){focusNextElement(event); return false;}">

使用 jQuery:

$(window).on('keypress', function (ev)
{
    if (ev.key === "Enter" && ev.currentTarget.form) focusNextElement(ev)
}

使用香草 JS:

document.addEventListener('keypress', function (ev) {
    if (ev.key === "Enter" && ev.currentTarget.form) focusNextElement(ev);
});

您可以focusNextElement()从这里获取功能: https ://stackoverflow.com/a/35173443/3356679

于 2019-05-06T09:33:34.653 回答
0

这就是我想出的。

form.addEventListener("submit", (e) => { //On Submit
 let key = e.charCode || e.keyCode || 0 //get the key code
 if (key = 13) { //If enter key
    e.preventDefault()
    const inputs = Array.from(document.querySelectorAll("form input")) //Get array of inputs
    let nextInput = inputs[inputs.indexOf(document.activeElement) + 1] //get index of input after the current input
    nextInput.focus() //focus new input
}
}
于 2019-05-10T22:25:24.847 回答
0

用 JavaScript 的焦点函数解决这个问题的最简单方法如下:

你可以复制并尝试@home!

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>

    <input id="input1" type="text" onkeypress="pressEnter()" />
    <input id="input2" type="text" onkeypress="pressEnter2()" />
    <input id="input3" type="text"/>

    <script type="text/javascript">
    function pressEnter() {
      // Key Code for ENTER = 13
      if ((event.keyCode == 13)) {
        document.getElementById("input2").focus({preventScroll:false});
      }
    }
    function pressEnter2() {
      if ((event.keyCode == 13)) {
        document.getElementById("input3").focus({preventScroll:false});
      }
    }
    </script>

  </body>
</html>
于 2019-09-20T11:23:02.237 回答
-1

我有一个类似的需求。这是我所做的:

  <script type="text/javascript" language="javascript">
    function convertEnterToTab() {
      if(event.keyCode==13) {
        event.keyCode = 9;
      }
    }
    document.onkeydown = convertEnterToTab;    
  </script>  
于 2009-12-09T16:52:17.590 回答
-1

在所有这些情况下,仅适用于 Chrome 和 IE,我添加了以下代码来解决该问题:

var key = (window.event) ? e.keyCode : e.which;

我测试了键值是否等于 13

    $('body').on('keydown', 'input, select, textarea', function (e) {
    var self = $(this)
      , form = self.parents('form:eq(0)')
      , focusable
      , next
    ;

    var key = (window.event) ? e.keyCode : e.which;

    if (key == 13) {
        focusable = form.find('input,a,select,button,textarea').filter(':visible');
        next = focusable.eq(focusable.index(this) + 1);
        if (next.length) {
            next.focus();
        } else {
            focusable.click();
        }
        return false;
    }
});
于 2016-09-09T15:23:20.193 回答
-1
$("#form input , select , textarea").keypress(function(e){
    if(e.keyCode == 13){
        var enter_position = $(this).index();
        $("#form input , select , textarea").eq(enter_position+1).focus();
    }
});
于 2019-06-27T06:44:24.860 回答
-2

您可以在进行时以编程方式迭代添加 onkeydown 处理程序的表单元素。这样您就可以重用代码。

于 2009-06-17T22:23:57.783 回答