Enter нажатие клавиши ведет себя как вкладка в Javascript
Я ищу, чтобы создать форму, где нажатие клавиши enter вызывает фокус, чтобы перейти к "следующему" элементу формы на странице. Решение я продолжаю находить в интернете...
<body onkeydown="if(event.keyCode==13){event.keyCode=9; return event.keyCode}">
к сожалению, это работает только в IE. Итак, настоящее мясо этого вопроса - если кто-нибудь знает решение, которое работает для FF и Chrome? Кроме того, я бы предпочел не добавлять onkeydown события для самих элементов формы, но если это единственный способ, он должен будет делать.
эта проблема похожа на вопрос 905222, но заслуживает свой собственный вопрос на мой взгляд.
Edit: кроме того, я видел, как люди поднимают вопрос о том, что это не хороший стиль, поскольку он отличается от поведения формы, к которому привыкли пользователи. Я согласен! Это запрос клиента: (
18 ответов:
я использовал логику, предложенную Андреем, которая очень эффективна. И это моя версия:
$('body').on('keydown', 'input, select, textarea', function(e) { var self = $(this) , form = self.parents('form:eq(0)') , focusable , next ; 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; } });
Map [Enter] ключ для работы, как [Tab] ключ
я переписал Андре Ван Зуйдамответ, который не работал для меня, в jQuery. Это снимки как введите и Shift+введите. введите вкладки вперед, и Shift+введите вкладки.
Я также переписал путь
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" хочу, чтобы вкладки в него. Кроме того, после входа мы не хотим останавливать поведение по умолчанию введите от ввода новой строки.
причина
aиbuttonразрешить действие по умолчанию, "и " по-прежнему сосредоточиться на следующем пункте, потому что они не делают всегда загружайте другую страницу. Там может быть триггер / эффект на тех, кто, например, аккордеон или вкладки контента. Поэтому, как только вы запускаете поведение по умолчанию, и страница делает свой специальный эффект, вы все равно хотите перейти к следующему элементу, так как ваш триггер, возможно, хорошо представил его.
это сработало для меня
$(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(); } });
Спасибо за хороший сценарий.
Я только что добавил событие 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; } });
есть проблемы со всеми реализациями, приведенными здесь. Некоторые из них не работают должным образом с текстовыми областями и кнопками отправки, большинство из них не позволяют использовать shift для перехода назад, ни один из них не использует tabindexes, если они у вас есть, и ни один из них не обертывается от последнего до первого или от первого до последнего.
чтобы клавиша [enter] действовала как клавиша [tab], но все еще работала правильно с текстовыми областями и кнопками отправки, используйте следующий код. Кроме того, этот код позволяет использовать клавиша shift для перехода назад, а вкладка обертывается спереди назад и обратно.
исходный код: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(); }
самый простой фрагмент 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(); } });работает в IE 9+ и современных браузеров.
изменение этого поведения фактически создает гораздо лучший пользовательский интерфейс, чем поведение по умолчанию, реализованное изначально. Учтите, что поведение клавиши enter уже противоречиво с точки зрения пользователя, потому что в однострочном вводе enter имеет тенденцию отправлять форму, а в многострочном текстовом поле он просто добавляет новую строку к содержимому поля.
недавно я сделал это так (использует 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" к любому входному элементу, который должен вести себя таким образом.
я переработал решение OPs в нокаут-привязку и подумал, что поделюсь им. Спасибо большое :-)
вот!--5--> Скрипка
<!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>
вот угловой.директива js, чтобы заставить enter перейти к следующему полю, используя другие ответы в качестве вдохновения. Здесь есть какой-то, возможно, странный код, потому что я использую только 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директива по элементу. Я использую сканер штрих-кода для ввода данных в поля, функция по умолчанию сканер эмулировать keayboard, впрыскивая клавишу 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>
У меня была аналогичная проблема, где я хотел нажать + на цифровой клавиатуре, чтобы перейти в следующее поле. Теперь я выпустил библиотеку, которая я думаю, поможет вам.
PlusAsTab: плагин jQuery для использования клавиши numpad plus в качестве эквивалента клавиши tab.
Так как вы хотите введите/↵ вместо этого, вы можете установить параметры. Узнайте, какой ключ вы хотите использовать событий jQuery.который демо.
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 введите как tab demo.
у меня он работает только на JavaScript. Firefox не позволит вам обновить код ключа, поэтому все, что вы можете сделать, это поймать код ключа 13 и заставить его сосредоточиться на следующем элементе tabIndex, как если бы был нажат код ключа 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-документа. Возможно, это особенность, а не недостаток. Если вам нравится, ловушка ключ 9 и в таком поведении тоже будет работать с помощью клавиши Tab.
вы можете использовать мой код ниже, протестированный в 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; } }); }Как использовать?
если можно я бы пересмотрел это действие по умолчанию клавишей
<Enter>в то время как в форме отправляет форму и все, что вы делаете, чтобы изменить это действие по умолчанию / ожидаемое поведение может вызвать некоторые проблемы юзабилити с сайтом.
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() } }
попробуйте это...
$(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(); });
У меня была аналогичная необходимость. Вот что я сделал:
<script type="text/javascript" language="javascript"> function convertEnterToTab() { if(event.keyCode==13) { event.keyCode = 9; } } document.onkeydown = convertEnterToTab; </script>
во всех этих случаях работает только в Chrome и IE, я добавил следующий код, чтобы решить эту проблему:
var key = (окно.событие) ? е.код : электронная.которых;
и я проверил значение ключа, если ключ равен 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; } });
вы можете программно повторять элементы формы, добавляя обработчик onkeydown по мере прохождения. Таким образом, вы можете повторно использовать код.
Comments