输入按键的行为类似于Javascript中的Tab

Ros*_*oss 68 html javascript cross-browser dom-events

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

 <body onkeydown="if(event.keyCode==13){event.keyCode=9; return event.keyCode}">
Run Code Online (Sandbox Code Playgroud)

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

这个问题类似于问题905222,但在我看来,这个问题值得我自己提出.

编辑:另外,我已经看到人们提出这个问题并不好,因为它与用户习惯的形式行为不同.我同意!这是客户要求:(

小智 80

我使用了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;
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 我建议从第一行的选择器中删除`textarea`.在textarea中,您希望能够使用回车键开始新行. (28认同)
  • 我建议忽略带有 `readonly` 和 `disabled` 的字段:`filter(':visible:not([readonly]):enabled')` (2认同)

6ft*_*Dan 17

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

我在jQuery中重写了Andre Van Zuydam的回答,这对我来说不起作用.这可以兼顾EnterShift+ Enter. Enter选项卡向前,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() }
});
Run Code Online (Sandbox Code Playgroud)

原因 textarea

包含是因为我们" "想要标记到它.此外,一旦进入,我们不希望停止Enter放入新行的默认行为.

原因abutton

允许默认操作," "仍然专注于下一个项目,因为它们并不总是加载另一个页面.可能会对手风琴或标签内容等触发/影响产生影响.因此,一旦触发默认行为,并且页面发挥其特殊效果,您仍然希望转到下一个项目,因为您的触发器可能已经很好地引入了它.

  • 最后一位的目的是什么:`if(e.shiftKey){enterKey()} else {enterKey()}`?似乎应该只是:`enterKey()`。 (3认同)
  • @AVProgrammer要*输入*表示像*tab*,如果保持*shift*键,它需要反向运行.您询问的行允许在按下*shift*键时检查*enter*键. (2认同)
  • 在这两种情况下检查 e.shiftKey 和调用 enterKey 都没有意义。 (2认同)
  • 无论是否按下 shift,您都在执行相同的操作。所以 if 语句不是必需的,正如 avprogrammer 也指出的 (2认同)

May*_*ang 13

这对我有用

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

 if (e.which == 13  || e.keyCode == 13  ) 
 {      e.preventDefault();
        var $canfocus = $(':tabbable:visible')
        var index = $canfocus.index(document.activeElement) + 1;
        if (index >= $canfocus.length) index = 0;
        $canfocus.eq(index).focus();
}   

});
Run Code Online (Sandbox Code Playgroud)

的jsfiddle


Vit*_*sov 12

我想出了最简单的vanilla 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();
  }
});
Run Code Online (Sandbox Code Playgroud)

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

  • 我相信这应该是正确的答案。OP并没有要求使用jquery,这更简单,更兼容。 (2认同)
  • 不知道为什么这么多答案都假设存在一个表单...这不起作用:`Uncaught TypeError:Array.prototype.indexOf 在 null 或 undefined 上调用` (2认同)

And*_*dam 11

谢谢你的好脚本.

我刚刚在上面的函数中添加了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;
}
});
Run Code Online (Sandbox Code Playgroud)


Mik*_*any 6

这里给出的所有实现都存在问题.有些不能正常使用textareas并提交按钮,大多数都不允许你使用shift来向后移动,如果你有它们,它们都没有使用tabindexes,并且它们都没有从最后一个到第一个或第一个包裹到最后.

要使[enter]键像[tab]键一样,但仍能正常使用文本区域和提交按钮,请使用以下代码.此外,此代码允许您使用shift键向后移动,并且tabbing从前到后并从前到后包裹.

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

CoffeeScript的

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()
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)