Ввод нажатия клавиши ведет себя как вкладка в Javascript

Я ищу, чтобы создать форму, в которой нажатие клавиши ввода приводит к тому, что фокус переходит к элементу "следующей" формы на странице. Решение, которое я продолжаю искать в Интернете, - это...

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

К сожалению, это похоже только в IE. Итак, реальное мясо этого вопроса - если кто-нибудь знает о решении, которое работает для FF и Chrome? Кроме того, я бы предпочел не добавлять события onkeydown самим элементам формы, но если это единственный способ, это нужно будет сделать.

Этот вопрос похож на вопрос вопрос 905222, но, на мой взгляд, он заслуживает собственного вопроса.

Edit: также, я видел, как люди поднимают вопрос о том, что это не хороший стиль, поскольку он отклоняется от поведения формы, к которому привыкли пользователи. Согласен! Это запрос клиента: (

Ответ 1

Я использовал логику, предложенную Эндрю, которая очень эффективна. И это моя версия:

$('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

Ответ 2

Клавиша [Enter] для работы с клавишей [Tab]

Я переписал Andre Van Zuydam ответ, который не работал у меня, в jQuery. Это создает как Enter, так и Shift + 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() }
});

Причина textarea

включен, потому что мы " do" хотим вставить в него вкладку. Кроме того, один раз внутри, мы не хотим останавливать поведение по умолчанию Enter от ввода новой строки.

Причина a и button

разрешить действие по умолчанию " и" по-прежнему сосредоточиться на следующем элементе, потому что они не всегда загружают другую страницу. Там может быть триггер/эффект для таких, как аккордеон или содержимое с вкладками. Поэтому, как только вы запускаете поведение по умолчанию, и страница делает особый эффект, вы все равно хотите перейти к следующему элементу, так как ваш триггер мог бы его ввести.

Ответ 3

Это работало для меня

 $(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();
}   

});

JsFiddle

Ответ 4

Спасибо за хороший script.

Я только что добавил событие 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;
}
});

Ответ 5

Самый простой ванильный 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+ и современных браузерах.

Ответ 6

Существуют проблемы со всеми реализациями, приведенными здесь. Некоторые из них не работают должным образом с текстовыми полями и кнопками отправки, большинство из них не позволяют использовать сдвиг для перехода назад, ни один из них не использует tabindexes, если он у вас есть, и ни один из них не обертывается с последнего на первый или первый до последнего.

Чтобы клавиша [enter] действовала как клавиша [tab], но все еще правильно работает с текстовыми областями и кнопками отправки, используйте следующий код. Кроме того, этот код позволяет вам использовать клавишу переключения, чтобы вернуться назад, а табуляция обертывается спереди назад и назад.

Исходный код: 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()

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();
}

Ответ 7

Изменение этого поведения на самом деле создает гораздо лучший пользовательский интерфейс, чем поведение по умолчанию, реализованное изначально. Подумайте, что поведение ключа ввода уже несовместимо с пользовательской точкой зрения, потому что в одном вводе строки вводится тенденция отправки формы, а в многострочной текстовой области она просто добавляет новую строку к содержимому поле.

Я недавно сделал это так (использует 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' к любому элементу ввода, который должен вести себя таким образом.

Ответ 8

Я переделал решение 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>

Ответ 9

Вот директива angular.js, чтобы сделать переход в следующее поле, используя другие ответы в качестве вдохновения. Здесь есть, возможно, нечетный код, потому что я использую только jQlite, упакованный в angular. Я считаю, что большинство функций здесь работают во всех браузерах > 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 к элементу. Я использую сканер штрих-кода для ввода данных в поля, функция по умолчанию для сканера - эмулировать кейборд, вводя ключ ввода после ввода данных отсканированного штрих-кода.

Существует один побочный эффект для этого кода (положительный для моего прецедента), если он перемещает фокус на кнопку, событие ввода 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>

Ответ 10

У меня была аналогичная проблема, когда я хотел нажать + на numpad, чтобы перейти к следующему полю. Теперь я выпустил библиотеку, которая, я думаю, поможет вам.

PlusAsTab: плагин jQuery для использования клавиши numpad plus в качестве эквивалента табуляции.

Так как вы хотите enter/, вы можете установить параметры. Узнайте, какой ключ вы хотите использовать с jQuery event.which demo.

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 введите как демонстрацию вкладок.

Ответ 11

Если вы можете пересмотреть это: действие по умолчанию при нажатии <Enter>, а в форме отправляет форму, и все, что вы делаете, чтобы изменить это действие по умолчанию/ожидаемое поведение, может вызвать некоторые проблемы с удобством использования сайта.

Ответ 12

Я работаю только с 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, и это поведение также будет работать с клавишей табуляции.

Ответ 13

Вы можете использовать мой код ниже, протестированный в 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;
            }
        });

    }

Как использовать?

$( "# форма" ) enterkeytab().//введите вкладку клавиш

Ответ 14

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()
    }
  }

Ответ 15

Попробуйте это...

$(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();
});

Ответ 16

Многие ответы здесь используют 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)
}

И с Vanilla JS:

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

Вы можете воспользоваться focusNextElement() отсюда: fooobar.com/questions/22413/...

Ответ 17

Вот что я придумала.

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
}
}

Ответ 18

Самый простой способ решить эту проблему с помощью функции фокуса 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>

Ответ 19

У меня была симулятивная потребность. Вот что я сделал:

  <script type="text/javascript" language="javascript">
    function convertEnterToTab() {
      if(event.keyCode==13) {
        event.keyCode = 9;
      }
    }
    document.onkeydown = convertEnterToTab;    
  </script>  

Ответ 20

Во всех этих случаях, работает только в 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;
    }
});

Ответ 21

$("#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();
    }
});

Ответ 22

Вы можете запрограммировать итерацию элементов формы, добавляя обработчик onkeydown, когда вы идете. Таким образом вы можете повторно использовать код.